From 9d5ac7304583952239cf71a3b3a58f7d3cc742b3 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 20 Oct 2011 10:33:31 +0200 Subject: misc: Add audio_io_dev driver Signed-off-by: Robert Marklund --- .../mach-ux500/include/mach/ste_audio_io_ioctl.h | 224 + .../include/mach/ste_audio_io_vibrator.h | 37 + drivers/misc/audio_io_dev/Kconfig | 11 + drivers/misc/audio_io_dev/Makefile | 9 + .../audio_io_dev/ste_audio_io_ab8500_reg_defs.h | 349 ++ drivers/misc/audio_io_dev/ste_audio_io_core.c | 1464 +++++++ drivers/misc/audio_io_dev/ste_audio_io_core.h | 133 + drivers/misc/audio_io_dev/ste_audio_io_dev.c | 738 ++++ drivers/misc/audio_io_dev/ste_audio_io_dev.h | 32 + drivers/misc/audio_io_dev/ste_audio_io_func.c | 4371 ++++++++++++++++++++ drivers/misc/audio_io_dev/ste_audio_io_func.h | 359 ++ .../misc/audio_io_dev/ste_audio_io_hwctrl_common.c | 189 + .../misc/audio_io_dev/ste_audio_io_hwctrl_common.h | 50 + 13 files changed, 7966 insertions(+) create mode 100644 arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h create mode 100644 arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h create mode 100644 drivers/misc/audio_io_dev/Kconfig create mode 100644 drivers/misc/audio_io_dev/Makefile create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_ab8500_reg_defs.h create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_core.c create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_core.h create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_dev.c create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_dev.h create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_func.c create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_func.h create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.c create mode 100644 drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.h diff --git a/arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h b/arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h new file mode 100644 index 00000000000..73dc9d9ee7e --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h @@ -0,0 +1,224 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#ifndef _AUDIOIO_IOCTL_H_ +#define _AUDIOIO_IOCTL_H_ + + +#define AUDIOIO_IOC_MAGIC 'N' +#define AUDIOIO_READ_REGISTER _IOWR(AUDIOIO_IOC_MAGIC, 1,\ + struct audioio_data_t) +#define AUDIOIO_WRITE_REGISTER _IOW(AUDIOIO_IOC_MAGIC, 2,\ + struct audioio_data_t) +#define AUDIOIO_PWR_CTRL_TRNSDR _IOW(AUDIOIO_IOC_MAGIC, 3,\ + struct audioio_pwr_ctrl_t) +#define AUDIOIO_PWR_STS_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 4,\ + struct audioio_pwr_ctrl_t) +#define AUDIOIO_LOOP_CTRL _IOW(AUDIOIO_IOC_MAGIC, 5,\ + struct audioio_loop_ctrl_t) +#define AUDIOIO_LOOP_STS _IOR(AUDIOIO_IOC_MAGIC, 6,\ + struct audioio_loop_ctrl_t) +#define AUDIOIO_GET_TRNSDR_GAIN_CAPABILITY _IOR(AUDIOIO_IOC_MAGIC, 7,\ + struct audioio_get_gain_t) +#define AUDIOIO_GAIN_CAP_LOOP _IOR(AUDIOIO_IOC_MAGIC, 8,\ + struct audioio_gain_loop_t) +#define AUDIOIO_SUPPORT_LOOP _IOR(AUDIOIO_IOC_MAGIC, 9,\ + struct audioio_support_loop_t) +#define AUDIOIO_GAIN_DESC_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 10,\ + struct audioio_gain_desc_trnsdr_t) +#define AUDIOIO_GAIN_CTRL_TRNSDR _IOW(AUDIOIO_IOC_MAGIC, 11,\ + struct audioio_gain_ctrl_trnsdr_t) +#define AUDIOIO_GAIN_QUERY_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 12,\ + struct audioio_gain_ctrl_trnsdr_t) +#define AUDIOIO_MUTE_CTRL_TRNSDR _IOW(AUDIOIO_IOC_MAGIC, 13,\ + struct audioio_mute_trnsdr_t) +#define AUDIOIO_MUTE_STS_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 14,\ + struct audioio_mute_trnsdr_t) +#define AUDIOIO_FADE_CTRL _IOW(AUDIOIO_IOC_MAGIC, 15,\ + struct audioio_fade_ctrl_t) +#define AUDIOIO_BURST_CTRL _IOW(AUDIOIO_IOC_MAGIC, 16,\ + struct audioio_burst_ctrl_t) +#define AUDIOIO_READ_ALL_ACODEC_REGS_CTRL _IOW(AUDIOIO_IOC_MAGIC, 17,\ + struct audioio_read_all_acodec_reg_ctrl_t) +#define AUDIOIO_FSBITCLK_CTRL _IOW(AUDIOIO_IOC_MAGIC, 18,\ + struct audioio_fsbitclk_ctrl_t) +#define AUDIOIO_PSEUDOBURST_CTRL _IOW(AUDIOIO_IOC_MAGIC, 19,\ + struct audioio_pseudoburst_ctrl_t) +#define AUDIOIO_AUDIOCODEC_PWR_CTRL _IOW(AUDIOIO_IOC_MAGIC, 20, \ + struct audioio_acodec_pwr_ctrl_t) +#define AUDIOIO_FIR_COEFFS_CTRL _IOW(AUDIOIO_IOC_MAGIC, 21, \ + struct audioio_fir_coefficients_t) +#define AUDIOIO_LOOP_GAIN_DESC_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 22,\ + struct audioio_gain_desc_trnsdr_t) +/* audio codec channel ids */ +#define EAR_CH 0 +#define HS_CH 1 +#define IHF_CH 2 +#define VIBL_CH 3 +#define VIBR_CH 4 +#define MIC1A_CH 5 +#define MIC1B_CH 6 +#define MIC2_CH 7 +#define LIN_CH 8 +#define DMIC12_CH 9 +#define DMIC34_CH 10 +#define DMIC56_CH 11 +#define MULTI_MIC_CH 12 +#define FMRX_CH 13 +#define FMTX_CH 14 +#define BLUETOOTH_CH 15 + +#define FIRST_CH EAR_CH +#define LAST_CH BLUETOOTH_CH + +#define MAX_NO_TRANSDUCERS 16 +#define STE_AUDIOIO_MAX_COEFFICIENTS 128 +#define MAX_NO_OF_LOOPS 19 + +#define AUDIOIO_TRUE 1 +#define AUDIOIO_FALSE 0 + +enum AUDIOIO_COMMON_SWITCH { + AUDIOIO_COMMON_OFF = 0, + AUDIOIO_COMMON_ON, + AUDIOIO_COMMON_ALLCHANNEL_UNSUPPORTED = 0xFFFF +}; + +enum AUDIOIO_HAL_HW_LOOPS { + AUDIOIO_NO_LOOP = 0x0, + AUDIOIO_SIDETONE_LOOP = 0x01, + AUDIOIO_MIC1B_TO_HFL = 0x02, + AUDIOIO_MIC1B_TO_HFR = 0x04, + AUDIOIO_MIC1B_TO_EAR = 0x08, + AUDIOIO_MIC1A_TO_HSL = 0x10, + AUDIOIO_MIC1A_TO_HSR = 0x20, + AUDIOIO_MIC1A_TO_HSR_HSL = 0x40, + AUDIOIO_LINEIN_TO_HF = 0x80, + AUDIOIO_DMIC12_TO_HSR_HSL = 0x100, + AUDIOIO_DIC34_TO_HSR_HSL = 0x200, + AUDIOIO_DIC56_TO_HSR_HSL = 0x400, + AUDIOIO_DMIC12_TO_ST = 0x800, + AUDIOIO_DMIC34_TO_ST = 0x1000, + AUDIOIO_DMIC56_TO_ST = 0x2000, + AUDIOIO_ANC_LOOP = 0x4000, + AUDIOIO_LININ_HS = 0x8000, + AUDIOIO_LININL_HSL = 0x10000, + AUDIOIO_LININ_HSR = 0x20000 +}; + + +enum AUDIOIO_FADE_PERIOD { + e_FADE_00, + e_FADE_01, + e_FADE_10, + e_FADE_11 +}; + +enum AUDIOIO_CH_INDEX { + e_CHANNEL_1 = 0x01, + e_CHANNEL_2 = 0x02, + e_CHANNEL_3 = 0x04, + e_CHANNEL_4 = 0x08, + e_CHANNEL_ALL = 0x0f +}; + +struct audioio_data_t { + unsigned char block; + unsigned char addr; + unsigned char data; +}; + +struct audioio_pwr_ctrl_t { + enum AUDIOIO_COMMON_SWITCH ctrl_switch; + int channel_type; + enum AUDIOIO_CH_INDEX channel_index; +}; + +struct audioio_acodec_pwr_ctrl_t { + enum AUDIOIO_COMMON_SWITCH ctrl_switch; +}; + +struct audioio_loop_ctrl_t { + enum AUDIOIO_HAL_HW_LOOPS hw_loop; + enum AUDIOIO_COMMON_SWITCH ctrl_switch; + int channel_type; + enum AUDIOIO_CH_INDEX channel_index; + int loop_gain; +}; + +struct audioio_get_gain_t { + unsigned int num_channels; + unsigned short max_num_gain; +}; + +struct audioio_gain_loop_t { + int channel_type; + unsigned short num_loop; + unsigned short max_gains; +}; + +struct audioio_support_loop_t { + int channel_type; + unsigned short spprtd_loop_index; +}; + +struct audioio_gain_desc_trnsdr_t { + enum AUDIOIO_CH_INDEX channel_index; + int channel_type; + unsigned short gain_index; + int min_gain; + int max_gain; + unsigned int gain_step; +}; + +struct audioio_gain_ctrl_trnsdr_t { + enum AUDIOIO_CH_INDEX channel_index; + int channel_type; + unsigned short gain_index; + int gain_value; + unsigned int linear; +}; + +struct audioio_mute_trnsdr_t { + int channel_type; + enum AUDIOIO_CH_INDEX channel_index; + enum AUDIOIO_COMMON_SWITCH ctrl_switch; +}; + +struct audioio_fade_ctrl_t { + enum AUDIOIO_COMMON_SWITCH ctrl_switch; + enum AUDIOIO_FADE_PERIOD fade_period; + int channel_type; + enum AUDIOIO_CH_INDEX channel_index; +}; + +struct audioio_burst_ctrl_t { + enum AUDIOIO_COMMON_SWITCH ctrl_switch; + int channel_type; + int burst_fifo_interrupt_sample_count; + int burst_fifo_length;/* BFIFOTx */ + int burst_fifo_switch_frame; + int burst_fifo_sample_number; +}; + +struct audioio_read_all_acodec_reg_ctrl_t { + unsigned char data[200]; +}; + +struct audioio_fsbitclk_ctrl_t { + enum AUDIOIO_COMMON_SWITCH ctrl_switch; +}; + +struct audioio_pseudoburst_ctrl_t { + enum AUDIOIO_COMMON_SWITCH ctrl_switch; +}; + +struct audioio_fir_coefficients_t { + unsigned char start_addr; + unsigned short coefficients[STE_AUDIOIO_MAX_COEFFICIENTS]; +}; + +#endif diff --git a/arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h b/arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h new file mode 100644 index 00000000000..6b6a558e90a --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h @@ -0,0 +1,37 @@ +/* +* Overview: +* Header File defining vibrator kernel space interface +* +* Copyright (C) 2010 ST Ericsson +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ + +#ifndef _STE_AUDIO_IO_VIBRATOR_H_ +#define _STE_AUDIO_IO_VIBRATOR_H_ + +/* Client definitions which can use vibrator, defined as bitmask */ +#define STE_AUDIOIO_CLIENT_AUDIO_L 1 +#define STE_AUDIOIO_CLIENT_AUDIO_R 2 +#define STE_AUDIOIO_CLIENT_FF_VIBRA 4 +#define STE_AUDIOIO_CLIENT_TIMED_VIBRA 8 + +/* + * Define vibrator's maximum speed allowed + * Duty cycle supported by vibrator's PWM is 0-100 + */ +#define STE_AUDIOIO_VIBRATOR_MAX_SPEED 100 + +/* Vibrator speed structure */ +struct ste_vibra_speed { + unsigned char positive; + unsigned char negative; +}; + +/* Vibrator control function - uses PWM source */ +int ste_audioio_vibrator_pwm_control(int client, + struct ste_vibra_speed left_speed, struct ste_vibra_speed right_speed); + +#endif diff --git a/drivers/misc/audio_io_dev/Kconfig b/drivers/misc/audio_io_dev/Kconfig new file mode 100644 index 00000000000..57bb77172f7 --- /dev/null +++ b/drivers/misc/audio_io_dev/Kconfig @@ -0,0 +1,11 @@ +# +# AB8500 Audio IO Device Driver configuration +# +config STE_AUDIO_IO_DEV + bool "AB8500 Audio IO device driver" + depends on ARCH_U8500 && AB8500_CORE && STM_MSP_I2S + default y + ---help--- + If you say Y here, you will enable the AB8500 Audio IO device driver. + + If unsure, say N. diff --git a/drivers/misc/audio_io_dev/Makefile b/drivers/misc/audio_io_dev/Makefile new file mode 100644 index 00000000000..44b21fcc573 --- /dev/null +++ b/drivers/misc/audio_io_dev/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for AB8500 device drivers +# +obj-$(CONFIG_STE_AUDIO_IO_DEV) += ste_audio_io.o +ste_audio_io-objs := ste_audio_io_dev.o\ + ste_audio_io_core.o\ + ste_audio_io_func.o\ + ste_audio_io_hwctrl_common.o + diff --git a/drivers/misc/audio_io_dev/ste_audio_io_ab8500_reg_defs.h b/drivers/misc/audio_io_dev/ste_audio_io_ab8500_reg_defs.h new file mode 100644 index 00000000000..1436430f7de --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_ab8500_reg_defs.h @@ -0,0 +1,349 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + + +#ifndef _AUDIOIO_REG_DEFS_H_ +#define _AUDIOIO_REG_DEFS_H_ + + + /* Registers */ +#define POWER_UP_CONTROL_REG 0x0D00 +#define SOFTWARE_RESET_REG 0x0D01 +#define DIGITAL_AD_CHANNELS_ENABLE_REG 0x0D02 +#define DIGITAL_DA_CHANNELS_ENABLE_REG 0x0D03 +#define LOW_POWER_HS_EAR_CONF_REG 0x0D04 +#define LINE_IN_MIC_CONF_REG 0x0D05 +#define DMIC_ENABLE_REG 0x0D06 +#define ADC_DAC_ENABLE_REG 0x0D07 +#define ANALOG_OUTPUT_ENABLE_REG 0x0D08 +#define DIGITAL_OUTPUT_ENABLE_REG 0x0D09 +#define MUTE_HS_EAR_REG 0x0D0A +#define SHORT_CIRCUIT_DISABLE_REG 0x0D0B +#define NCP_ENABLE_HS_AUTOSTART_REG 0x0D0C +#define ENVELOPE_THRESHOLD_REG 0x0D0D +#define ENVELOPE_DECAY_TIME_REG 0x0D0E +#define VIB_DRIVER_CONF_REG 0x0D0F +#define PWM_VIBNL_CONF_REG 0x0D10 +#define PWM_VIBPL_CONF_REG 0x0D11 +#define PWM_VIBNR_CONF_REG 0x0D12 +#define PWM_VIBPR_CONF_REG 0x0D13 +#define ANALOG_MIC1_GAIN_REG 0x0D14 +#define ANALOG_MIC2_GAIN_REG 0x0D15 +#define ANALOG_HS_GAIN_REG 0x0D16 +#define ANALOG_LINE_IN_GAIN_REG 0x0D17 +#define LINE_IN_TO_HSL_GAIN_REG 0x0D18 +#define LINE_IN_TO_HSR_GAIN_REG 0x0D19 +#define AD_FILTER_CONF_REG 0x0D1A +#define IF0_IF1_MASTER_CONF_REG 0x0D1B +#define IF0_CONF_REG 0x0D1C +#define TDM_IF_BYPASS_B_FIFO_REG 0x0D1D +#define IF1_CONF_REG 0x0D1E +#define AD_ALLOCATION_TO_SLOT0_1_REG 0x0D1F +#define AD_ALLOCATION_TO_SLOT2_3_REG 0x0D20 +#define AD_ALLOCATION_TO_SLOT4_5_REG 0x0D21 +#define AD_ALLOCATION_TO_SLOT6_7_REG 0x0D22 +#define AD_ALLOCATION_TO_SLOT8_9_REG 0x0D23 +#define AD_ALLOCATION_TO_SLOT10_11_REG 0x0D24 +#define AD_ALLOCATION_TO_SLOT12_13_REG 0x0D25 +#define AD_ALLOCATION_TO_SLOT14_15_REG 0x0D26 +#define AD_ALLOCATION_TO_SLOT16_17_REG 0x0D27 +#define AD_ALLOCATION_TO_SLOT18_19_REG 0x0D28 +#define AD_ALLOCATION_TO_SLOT20_21_REG 0x0D29 +#define AD_ALLOCATION_TO_SLOT22_23_REG 0x0D2A +#define AD_ALLOCATION_TO_SLOT24_25_REG 0x0D2B +#define AD_ALLOCATION_TO_SLOT26_27_REG 0x0D2C +#define AD_ALLOCATION_TO_SLOT28_29_REG 0x0D2D +#define AD_ALLOCATION_TO_SLOT30_31_REG 0x0D2E +#define AD_SLOT_0_TO_7_TRISTATE_REG 0x0D2F +#define AD_SLOT_8_TO_15_TRISTATE_REG 0x0D30 +#define AD_SLOT_16_TO_23_TRISTATE_REG 0x0D31 +#define AD_SLOT_24_TO_31_TRISTATE_REG 0x0D32 +#define SLOT_SELECTION_TO_DA1_REG 0x0D33 +#define SLOT_SELECTION_TO_DA2_REG 0x0D34 +#define SLOT_SELECTION_TO_DA3_REG 0x0D35 +#define SLOT_SELECTION_TO_DA4_REG 0x0D36 +#define SLOT_SELECTION_TO_DA5_REG 0x0D37 +#define SLOT_SELECTION_TO_DA6_REG 0x0D38 +#define SLOT_SELECTION_TO_DA7_REG 0x0D39 +#define SLOT_SELECTION_TO_DA8_REG 0x0D3A +#define CLASS_D_EMI_PARALLEL_CONF_REG 0x0D3B +#define CLASS_D_PATH_CONTROL_REG 0x0D3C +#define CLASS_D_DITHER_CONTROL_REG 0x0D3D +#define DMIC_DECIMATOR_FILTER_REG 0x0D3E +#define DIGITAL_MUXES_REG1 0x0D3F +#define DIGITAL_MUXES_REG2 0x0D40 +#define AD1_DIGITAL_GAIN_REG 0x0D41 +#define AD2_DIGITAL_GAIN_REG 0x0D42 +#define AD3_DIGITAL_GAIN_REG 0x0D43 +#define AD4_DIGITAL_GAIN_REG 0x0D44 +#define AD5_DIGITAL_GAIN_REG 0x0D45 +#define AD6_DIGITAL_GAIN_REG 0x0D46 +#define DA1_DIGITAL_GAIN_REG 0x0D47 +#define DA2_DIGITAL_GAIN_REG 0x0D48 +#define DA3_DIGITAL_GAIN_REG 0x0D49 +#define DA4_DIGITAL_GAIN_REG 0x0D4A +#define DA5_DIGITAL_GAIN_REG 0x0D4B +#define DA6_DIGITAL_GAIN_REG 0x0D4C +#define AD1_TO_HFL_DIGITAL_GAIN_REG 0x0D4D +#define AD2_TO_HFR_DIGITAL_GAIN_REG 0x0D4E +#define HSL_EAR_DIGITAL_GAIN_REG 0x0D4F +#define HSR_DIGITAL_GAIN_REG 0x0D50 +#define SIDETONE_FIR1_GAIN_REG 0x0D51 +#define SIDETONE_FIR2_GAIN_REG 0x0D52 +#define ANC_FILTER_CONTROL_REG 0x0D53 +#define ANC_WARPED_GAIN_REG 0x0D54 +#define ANC_FIR_OUTPUT_GAIN_REG 0x0D55 +#define ANC_IIR_OUTPUT_GAIN_REG 0x0D56 +#define ANC_FIR_COEFF_MSB_REG 0x0D57 +#define ANC_FIR_COEFF_LSB_REG 0x0D58 +#define ANC_IIR_COEFF_MSB_REG 0x0D59 +#define ANC_IIR_COEFF_LSB_REG 0x0D5A +#define ANC_WARP_DELAY_MSB_REG 0x0D5B +#define ANC_WARP_DELAY_LSB_REG 0x0D5C +#define ANC_FIR_PEAK_MSB_REG 0x0D5D +#define ANC_FIR_PEAK_LSB_REG 0x0D5E +#define ANC_IIR_PEAK_MSB_REG 0x0D5F +#define ANC_IIR_PEAK_LSB_REG 0x0D60 +#define SIDETONE_FIR_ADDR_REG 0x0D61 +#define SIDETONE_FIR_COEFF_MSB_REG 0x0D62 +#define SIDETONE_FIR_COEFF_LSB_REG 0x0D63 +#define FILTERS_CONTROL_REG 0x0D64 +#define IRQ_MASK_LSB_REG 0x0D65 +#define IRQ_STATUS_LSB_REG 0x0D66 +#define IRQ_MASK_MSB_REG 0x0D67 +#define IRQ_STATUS_MSB_REG 0x0D68 +#define BURST_FIFO_INT_CONTROL_REG 0x0D69 +#define BURST_FIFO_LENGTH_REG 0x0D6A +#define BURST_FIFO_CONTROL_REG 0x0D6B +#define BURST_FIFO_SWITCH_FRAME_REG 0x0D6C +#define BURST_FIFO_WAKE_UP_DELAY_REG 0x0D6D +#define BURST_FIFO_SAMPLES_REG 0x0D6E +#define REVISION_REG 0x0D6F + +/* POWER_UP_CONTROL_REG Masks */ +#define DEVICE_POWER_UP 0x80 +#define ANALOG_PARTS_POWER_UP 0x08 + +/* SOFTWARE_RESET_REG Masks */ +#define SW_RESET 0x80 + +/* DIGITAL_AD_CHANNELS_ENABLE_REG Masks */ +#define EN_AD1 0x80 +#define EN_AD2 0x80 +#define EN_AD3 0x20 +#define EN_AD4 0x20 +#define EN_AD5 0x08 +#define EN_AD6 0x04 + +/* DIGITAL_DA_CHANNELS_ENABLE_REG Masks */ +#define EN_DA1 0x80 +#define EN_DA2 0x40 +#define EN_DA3 0x20 +#define EN_DA4 0x10 +#define EN_DA5 0x08 +#define EN_DA6 0x04 + +/* LOW_POWER_HS_EAR_CONF_REG Masks */ +#define LOW_POWER_HS 0x80 +#define HS_DAC_DRIVER_LP 0x40 +#define HS_DAC_LP 0x20 +#define EAR_DAC_LP 0x10 + +/* LINE_IN_MIC_CONF_REG Masks */ +#define EN_MIC1 0x80 +#define EN_MIC2 0x40 +#define EN_LIN_IN_L 0x20 +#define EN_LIN_IN_R 0x10 +#define MUT_MIC1 0x08 +#define MUT_MIC2 0x04 +#define MUT_LIN_IN_L 0x02 +#define MUT_LIN_IN_R 0x01 + +/* DMIC_ENABLE_REG Masks */ +#define EN_DMIC1 0x80 +#define EN_DMIC2 0x40 +#define EN_DMIC3 0x20 +#define EN_DMIC4 0x10 +#define EN_DMIC5 0x08 +#define EN_DMIC6 0x04 + +/* ADC_DAC_ENABLE_REG Masks */ +#define SEL_MIC1B_CLR_MIC1A 0x80 +#define SEL_LINR_CLR_MIC2 0x40 +#define POWER_UP_HSL_DAC 0x20 +#define POWER_UP_HSR_DAC 0x10 +#define POWER_UP_ADC1 0x04 +#define POWER_UP_ADC3 0x02 +#define POWER_UP_ADC2 0x01 + +/* ANALOG_OUTPUT_ENABLE_REG and DIGITAL_OUTPUT_ENABLE_REG and + MUTE_HS_EAR_REG Masks */ +#define EN_EAR_DAC_MASK 0x04 +#define EN_HSL_DAC_MASK 0x02 +#define EN_HSR_DAC_MASK 0x01 +#define EN_EAR_MASK 0x40 +#define EN_HSL_MASK 0x20 +#define EN_HSR_MASK 0x10 +#define EN_HFL_MASK 0x08 +#define EN_HFR_MASK 0x04 +#define EN_VIBL_MASK 0x02 +#define EN_VIBR_MASK 0x01 + +/* SHORT_CIRCUIT_DISABLE_REG Masks */ +#define HS_SHORT_DIS 0x20 +#define HS_PULL_DOWN_EN 0x10 +#define HS_OSC_EN 0x04 +#define DIS_HS_FAD 0x02 +#define HS_ZCD_DIS 0x01 + +/* NCP_ENABLE_HS_AUTOSTART_REG Masks */ +#define EN_NEG_CP 0x80 +#define HS_AUTO_EN 0x01 + +/* ANALOG_MIC1_GAIN_REG and ANALOG_MIC1_GAIN_REG Masks */ +#define MIC_ANALOG_GAIN_MASK 0x1F + +/*ANALOG_HS_GAIN_REG and ANALOG_LINE_IN_GAIN_REG Masks*/ +#define L_ANALOG_GAIN_MASK 0xF0 +#define R_ANALOG_GAIN_MASK 0x0F + +/* IF0_IF1_MASTER_CONF_REG Masks */ +#define EN_MASTGEN 0x80 +#define BITCLK_OSR_N_64 0x02 +#define BITCLK_OSR_N_128 0x04 +#define BITCLK_OSR_N_256 0x06 +#define EN_FSYNC_BITCLK 0x01 +#define EN_FSYNC_BITCLK1 0x10 + +/* IF0_CONF_REG and IF1_CONF_REG Masks */ +#define FSYNC_FALLING_EDGE 0x40 +#define BITCLK_FALLING_EDGE 0x20 +#define IF_DELAYED 0x10 +#define I2S_LEFT_ALIGNED_FORMAT 0x08 +#define TDM_FORMAT 0x04 +#define WORD_LENGTH_32 0x03 +#define WORD_LENGTH_24 0x02 +#define WORD_LENGTH_20 0x01 +#define WORD_LENGTH_16 0x00 + +/* TDM_IF_BYPASS_B_FIFO_REG Masks */ +#define IF0_BFifoEn 0x01 +#define IF0_MASTER 0x02 + +#define IF1_MASTER 0x20 +/* + * AD_ALLOCATION_TO_SLOT0_1_REG and AD_ALLOCATION_TO_SLOT2_3_REG and + * AD_ALLOCATION_TO_SLOT4_5_REG and AD_ALLOCATION_TO_SLOT6_7_REG Masks + */ +#define DATA_FROM_AD_OUT1 0x00 +#define DATA_FROM_AD_OUT2 0x01 +#define DATA_FROM_AD_OUT3 0x02 +#define DATA_FROM_AD_OUT4 0x03 +#define DATA_FROM_AD_OUT5 0x04 +#define DATA_FROM_AD_OUT6 0x05 +#define DATA_FROM_AD_OUT7 0x06 +#define DATA_FROM_AD_OUT8 0x07 +#define TRISTATE 0x0C + +/* + * SLOT_SELECTION_TO_DA1_REG and SLOT_SELECTION_TO_DA2_REG and + * SLOT_SELECTION_TO_DA3_REG and SLOT_SELECTION_TO_DA4_REG Masks + * SLOT_SELECTION_TO_DA5_REG and SLOT_SELECTION_TO_DA6_REG Masks + */ +#define SLOT08_FOR_DA_PATH 0x08 +#define SLOT09_FOR_DA_PATH 0x09 +#define SLOT10_FOR_DA_PATH 0x0A +#define SLOT11_FOR_DA_PATH 0x0B +#define SLOT12_FOR_DA_PATH 0x0C +#define SLOT13_FOR_DA_PATH 0x0D +#define SLOT14_FOR_DA_PATH 0x0E +#define SLOT15_FOR_DA_PATH 0x0F + +/* DIGITAL_MUXES_REG1 Masks */ +#define DA1_TO_HSL 0x80 +#define DA2_TO_HSR 0x40 +#define SEL_DMIC1_FOR_AD_OUT1 0x20 +#define SEL_DMIC2_FOR_AD_OUT2 0x10 +#define SEL_DMIC3_FOR_AD_OUT3 0x08 +/*#define SEL_DMIC5_FOR_AD_OUT5 0x04*/ +/*#define SEL_DMIC6_FOR_AD_OUT6 0x02*/ +/*#define SEL_DMIC1_FOR_AD_OUT1 0x01*/ + +/* + * AD1_DIGITAL_GAIN_REG and AD2_DIGITAL_GAIN_REG & AD3_DIGITAL_GAIN_REG Masks + * AD4_DIGITAL_GAIN_REG and AD5_DIGITAL_GAIN_REG & AD6_DIGITAL_GAIN_REG Masks + * DA1_DIGITAL_GAIN_REG and DA2_DIGITAL_GAIN_REG & DA3_DIGITAL_GAIN_REG Masks + * DA4_DIGITAL_GAIN_REG and DA5_DIGITAL_GAIN_REG & DA6_DIGITAL_GAIN_REG Masks + */ +#define DIS_FADING 0x40 +#define DIGITAL_GAIN_MASK 0x3F + +/* + * HSL_EAR_DIGITAL_GAIN_REG and HSR_DIGITAL_GAIN_REG Masks + */ +#define FADE_SPEED_MASK 0xC0 +#define DIS_DIG_GAIN_FADING 0x10 +#define HS_DIGITAL_GAIN_MASK 0x0F + +/* FMRx/FMTx Masks */ +#define SLOT24_FOR_DA_PATH 0x18 +#define SEL_AD_OUT8_FROM_DAIN7 0x20 +#define SLOT25_FOR_DA_PATH 0x19 +#define SEL_AD_OUT6_FROM_DAIN8 0x20 +#define SEL_IF8_FROM_AD_OUT7 0x60 +#define SEL_IF17_FROM_AD_OUT7 0x60 +#define SEL_IF16_FROM_AD_OUT8 0x07 + +#define SEL_IF6_FROM_AD_OUT5 0x04 +#define SEL_IF7_FROM_AD_OUT6 0x50 +#define SEL_IF17_FROM_AD_OUT6 0x50 +#define SEL_AD_OUT5_FROM_DAIN7 0x20 + +/* Burst FIFO Control Masks */ +#define WAKEUP_SIGNAL_SAMPLE_COUNT 0x1B +#define BURST_FIFO_TRANSFER_LENGTH 0xC0 +#define BURST_FIFO_INF_RUNNING 0x01 +#define BURST_FIFO_INF_IN_MASTER_MODE 0x02 +#define PRE_BIT_CLK0_COUNT 0x1C +#define BURST_FIFO_WAKUP_DEALAY 0x70 + +/* Filter Control Masks */ +/* SideTone Masks */ +#define SIDETONE_DIGITAL_GAIN_MASK 0x1F +#define FIR1_FROMAD1 0x0C +#define FIR1_FROMAD2 0x03 +#define FIR1_FROMAD3 0x08 +#define FIR1_DAIN1 0x0C + +#define FIR2_FROMAD2 0x00 +#define FIR2_FROMAD3 0x01 +#define FIR2_FROMAD4 0x02 +#define FIR2_DAIN2 0x03 + +#define FIR2_ANDFIR1AD3 0x09 +#define FIR_FILTERCONTROL 0x04 +#define APPLY_FIR_COEFFS_MASK 0x80 + +/* IRQ status masks */ +#define NCP_READY_MASK 0x80 + +/* AB8500 power control Masks */ +#define AB8500_VER_1_0 0x10 +#define AB8500_VER_1_1 0x11 +#define CLK_32K_OUT2_DISABLE 0x01 +#define INACTIVE_RESET_AUDIO 0x02 +#define AB8500_REQ_SYS_CLK 0x08 +#define ENABLE_AUDIO_CLK_TO_AUDIO_BLK 0x10 +#define ENABLE_VINTCORE12_SUPPLY 0x04 +#define VAMIC2_ENABLE 0x10 +#define VAMIC1_ENABLE 0x08 +#define VDMIC_ENABLE 0x04 +#define VAUDIO_ENABLE 0x02 +#define GPIO27_DIR_OUTPUT 0x04 +#define GPIO29_DIR_OUTPUT 0x10 +#define GPIO31_DIR_OUTPUT 0x40 +#define GPIO35_DIR_OUTPUT 0X04 +#endif diff --git a/drivers/misc/audio_io_dev/ste_audio_io_core.c b/drivers/misc/audio_io_dev/ste_audio_io_core.c new file mode 100644 index 00000000000..129cd041e24 --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_core.c @@ -0,0 +1,1464 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#include +#include +#include +#include +#include +#include + +#include "ste_audio_io_core.h" +#include "ste_audio_io_hwctrl_common.h" +#include "ste_audio_io_ab8500_reg_defs.h" + +static struct audiocodec_context_t *ptr_audio_codec_cnxt; + +static struct clk *clk_ptr_msp1; +static struct clk *clk_ptr_msp3; +static struct clk *clk_ptr_sysclk; + +static struct regulator *regulator_vdmic; +static struct regulator *regulator_vaudio; +static struct regulator *regulator_vamic1; +static struct regulator *regulator_vamic2; +struct regulator *regulator_avsource; +static void ste_audio_io_init_transducer_cnxt(void); + +bool ste_audio_io_core_is_ready_for_suspend() +{ + bool err = false; + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + if ((!ptr_audio_codec_cnxt->power_client) && + (!ptr_audio_codec_cnxt->audio_codec_powerup)) + err = true; + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + return err; +} +int ste_audio_io_core_api_init_data(struct platform_device *pdev) +{ + struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); + struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); + int status = 0; + ptr_audio_codec_cnxt = kmalloc(sizeof(struct audiocodec_context_t), + GFP_KERNEL); + if (!ptr_audio_codec_cnxt) + return -ENOMEM; + + memset(ptr_audio_codec_cnxt, 0, sizeof(*ptr_audio_codec_cnxt)); + ptr_audio_codec_cnxt->dev = &pdev->dev; + mutex_init(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + if (pdata) { + if (pdata->audio) { + ptr_audio_codec_cnxt->gpio_altf_init = + pdata->audio->ste_gpio_altf_init; + ptr_audio_codec_cnxt->gpio_altf_exit = + pdata->audio->ste_gpio_altf_exit; + } + } + + regulator_vdmic = regulator_get(NULL, "v-dmic"); + if (IS_ERR(regulator_vdmic)) { + status = PTR_ERR(regulator_vdmic); + dev_err(ptr_audio_codec_cnxt->dev, + "Register error for v-dmic=%d", status); + goto free_audio_codec_cnxt; + } + regulator_vamic1 = regulator_get(NULL, "v-amic1"); + if (IS_ERR(regulator_vamic1)) { + status = PTR_ERR(regulator_vamic1); + dev_err(ptr_audio_codec_cnxt->dev, + "Register error for v-amic1=%d", status); + goto free_regulator_vdmic; + } + regulator_vamic2 = regulator_get(NULL, "v-amic2"); + if (IS_ERR(regulator_vamic2)) { + status = PTR_ERR(regulator_vamic2); + dev_err(ptr_audio_codec_cnxt->dev, + "Register error for v-amic2=%d", status); + goto free_regulator_vdmic_vamic1; + } + regulator_vaudio = regulator_get(NULL, "v-audio"); + if (IS_ERR(regulator_vaudio)) { + status = PTR_ERR(regulator_vaudio); + dev_err(ptr_audio_codec_cnxt->dev, + "Register error for v-audio=%d", status); + goto free_regulator_vdmic_vamic1_vamic2; + } + regulator_avsource = regulator_get(ptr_audio_codec_cnxt->dev, + "vcc-N2158"); + if (IS_ERR(regulator_avsource)) { + status = PTR_ERR(regulator_avsource); + dev_err(ptr_audio_codec_cnxt->dev, + "Register error for vcc-N2158=%d", status); + goto free_regulator_vdmic_vamic1_vamic2_vaudio; + } + + ste_audio_io_init_transducer_cnxt(); + return 0; + +free_regulator_vdmic_vamic1_vamic2_vaudio: + regulator_put(regulator_vaudio); +free_regulator_vdmic_vamic1_vamic2: + regulator_put(regulator_vamic2); +free_regulator_vdmic_vamic1: + regulator_put(regulator_vamic1); +free_regulator_vdmic: + regulator_put(regulator_vdmic); +free_audio_codec_cnxt: + kfree(ptr_audio_codec_cnxt); + return status; +} + +static struct transducer_context_t transducer_headset = { + .pwr_up_func = ste_audio_io_power_up_headset, + .pwr_down_func = ste_audio_io_power_down_headset, + .set_gain_func = ste_audio_io_set_headset_gain, + .get_gain_func = ste_audio_io_get_headset_gain, + .mute_func = ste_audio_io_mute_headset, + .unmute_func = ste_audio_io_unmute_headset, + .enable_fade_func = ste_audio_io_enable_fade_headset, + .disable_fade_func = ste_audio_io_disable_fade_headset, + .switch_to_burst_func = ste_audio_io_switch_to_burst_mode_headset, + .switch_to_normal_func = ste_audio_io_switch_to_normal_mode_headset +}; + +static struct transducer_context_t transducer_earpiece = { + .pwr_up_func = ste_audio_io_power_up_earpiece, + .pwr_down_func = ste_audio_io_power_down_earpiece, + .set_gain_func = ste_audio_io_set_earpiece_gain, + .get_gain_func = ste_audio_io_get_earpiece_gain, + .mute_func = ste_audio_io_mute_earpiece, + .unmute_func = ste_audio_io_unmute_earpiece, + .enable_fade_func = ste_audio_io_enable_fade_earpiece, + .disable_fade_func = ste_audio_io_disable_fade_earpiece +}; + +static struct transducer_context_t transducer_ihf = { + .pwr_up_func = ste_audio_io_power_up_ihf, + .pwr_down_func = ste_audio_io_power_down_ihf, + .set_gain_func = ste_audio_io_set_ihf_gain, + .get_gain_func = ste_audio_io_get_ihf_gain, + .mute_func = ste_audio_io_mute_ihf, + .unmute_func = ste_audio_io_unmute_ihf, + .enable_fade_func = ste_audio_io_enable_fade_ihf, + .disable_fade_func = ste_audio_io_disable_fade_ihf + +}; + +static struct transducer_context_t transducer_vibl = { + .pwr_up_func = ste_audio_io_power_up_vibl, + .pwr_down_func = ste_audio_io_power_down_vibl, + .set_gain_func = ste_audio_io_set_vibl_gain, + .get_gain_func = ste_audio_io_get_vibl_gain, + .mute_func = ste_audio_io_mute_vibl, + .unmute_func = ste_audio_io_unmute_vibl, + .enable_fade_func = ste_audio_io_enable_fade_vibl, + .disable_fade_func = ste_audio_io_disable_fade_vibl +}; + +static struct transducer_context_t transducer_vibr = { + .pwr_up_func = ste_audio_io_power_up_vibr, + .pwr_down_func = ste_audio_io_power_down_vibr, + .set_gain_func = ste_audio_io_set_vibr_gain, + .get_gain_func = ste_audio_io_get_vibr_gain, + .mute_func = ste_audio_io_mute_vibr, + .unmute_func = ste_audio_io_unmute_vibr, + .enable_fade_func = ste_audio_io_enable_fade_vibr, + .disable_fade_func = ste_audio_io_disable_fade_vibr +}; + +static struct transducer_context_t transducer_mic1a = { + .pwr_up_func = ste_audio_io_power_up_mic1a, + .pwr_down_func = ste_audio_io_power_down_mic1a, + .set_gain_func = ste_audio_io_set_mic1a_gain, + .get_gain_func = ste_audio_io_get_mic1a_gain, + .mute_func = ste_audio_io_mute_mic1a, + .unmute_func = ste_audio_io_unmute_mic1a, + .enable_fade_func = ste_audio_io_enable_fade_mic1a, + .disable_fade_func = ste_audio_io_disable_fade_mic1a +}; + +static struct transducer_context_t transducer_mic1b = { + .pwr_up_func = ste_audio_io_power_up_mic1b, + .pwr_down_func = ste_audio_io_power_down_mic1b, + .set_gain_func = ste_audio_io_set_mic1a_gain, + .get_gain_func = ste_audio_io_get_mic1a_gain, + .mute_func = ste_audio_io_mute_mic1a, + .unmute_func = ste_audio_io_unmute_mic1a, + .enable_fade_func = ste_audio_io_enable_fade_mic1a, + .disable_fade_func = ste_audio_io_disable_fade_mic1a, + .enable_loop = ste_audio_io_enable_loop_mic1b, + .disable_loop = ste_audio_io_disable_loop_mic1b +}; + +static struct transducer_context_t transducer_mic2 = { + .pwr_up_func = ste_audio_io_power_up_mic2, + .pwr_down_func = ste_audio_io_power_down_mic2, + .set_gain_func = ste_audio_io_set_mic2_gain, + .get_gain_func = ste_audio_io_get_mic2_gain, + .mute_func = ste_audio_io_mute_mic2, + .unmute_func = ste_audio_io_unmute_mic2, + .enable_fade_func = ste_audio_io_enable_fade_mic2, + .disable_fade_func = ste_audio_io_disable_fade_mic2 +}; + +static struct transducer_context_t transducer_lin = { + .pwr_up_func = ste_audio_io_power_up_lin, + .pwr_down_func = ste_audio_io_power_down_lin, + .set_gain_func = ste_audio_io_set_lin_gain, + .get_gain_func = ste_audio_io_get_lin_gain, + .mute_func = ste_audio_io_mute_lin, + .unmute_func = ste_audio_io_unmute_lin, + .enable_fade_func = ste_audio_io_enable_fade_lin, + .disable_fade_func = ste_audio_io_disable_fade_lin +}; + +static struct transducer_context_t transducer_dmic12 = { + .pwr_up_func = ste_audio_io_power_up_dmic12, + .pwr_down_func = ste_audio_io_power_down_dmic12, + .set_gain_func = ste_audio_io_set_dmic12_gain, + .get_gain_func = ste_audio_io_get_dmic12_gain, + .mute_func = ste_audio_io_mute_dmic12, + .unmute_func = ste_audio_io_unmute_dmic12, + .enable_fade_func = ste_audio_io_enable_fade_dmic12, + .disable_fade_func = ste_audio_io_disable_fade_dmic12, + .enable_loop = ste_audio_io_enable_loop_dmic12, + .disable_loop = ste_audio_io_disable_loop_dmic12 +}; + +static struct transducer_context_t transducer_dmic34 = { + .pwr_up_func = ste_audio_io_power_up_dmic34, + .pwr_down_func = ste_audio_io_power_down_dmic34, + .set_gain_func = ste_audio_io_set_dmic34_gain, + .get_gain_func = ste_audio_io_get_dmic34_gain, + .mute_func = ste_audio_io_mute_dmic34, + .unmute_func = ste_audio_io_unmute_dmic34, + .enable_fade_func = ste_audio_io_enable_fade_dmic34, + .disable_fade_func = ste_audio_io_disable_fade_dmic34 +}; + +static struct transducer_context_t transducer_dmic56 = { + .pwr_up_func = ste_audio_io_power_up_dmic56, + .pwr_down_func = ste_audio_io_power_down_dmic56, + .set_gain_func = ste_audio_io_set_dmic56_gain, + .get_gain_func = ste_audio_io_get_dmic56_gain, + .mute_func = ste_audio_io_mute_dmic56, + .unmute_func = ste_audio_io_unmute_dmic56, + .enable_fade_func = ste_audio_io_enable_fade_dmic56, + .disable_fade_func = ste_audio_io_disable_fade_dmic56, +}; + +static struct transducer_context_t transducer_fmrx = { + .pwr_up_func = ste_audio_io_power_up_fmrx, + .pwr_down_func = ste_audio_io_power_down_fmrx, +}; + +static struct transducer_context_t transducer_fmtx = { + .pwr_up_func = ste_audio_io_power_up_fmtx, + .pwr_down_func = ste_audio_io_power_down_fmtx, +}; + +static struct transducer_context_t transducer_bluetooth = { + .pwr_up_func = ste_audio_io_power_up_bluetooth, + .pwr_down_func = ste_audio_io_power_down_bluetooth, +}; + +static void ste_audio_io_init_transducer_cnxt(void) +{ + ptr_audio_codec_cnxt->transducer[HS_CH] = &transducer_headset; + ptr_audio_codec_cnxt->transducer[EAR_CH] = &transducer_earpiece; + ptr_audio_codec_cnxt->transducer[IHF_CH] = &transducer_ihf; + ptr_audio_codec_cnxt->transducer[VIBL_CH] = &transducer_vibl; + ptr_audio_codec_cnxt->transducer[VIBR_CH] = &transducer_vibr; + ptr_audio_codec_cnxt->transducer[MIC1A_CH] = &transducer_mic1a; + ptr_audio_codec_cnxt->transducer[MIC1B_CH] = &transducer_mic1b; + ptr_audio_codec_cnxt->transducer[MIC2_CH] = &transducer_mic2; + ptr_audio_codec_cnxt->transducer[LIN_CH] = &transducer_lin; + ptr_audio_codec_cnxt->transducer[DMIC12_CH] = &transducer_dmic12; + ptr_audio_codec_cnxt->transducer[DMIC34_CH] = &transducer_dmic34; + ptr_audio_codec_cnxt->transducer[DMIC56_CH] = &transducer_dmic56; + ptr_audio_codec_cnxt->transducer[FMRX_CH] = &transducer_fmrx; + ptr_audio_codec_cnxt->transducer[FMTX_CH] = &transducer_fmtx; + ptr_audio_codec_cnxt->transducer[BLUETOOTH_CH] = &transducer_bluetooth; +} + +void ste_audio_io_core_api_free_data(void) +{ + regulator_put(regulator_vdmic); + regulator_put(regulator_vamic1); + regulator_put(regulator_vamic2); + regulator_put(regulator_vaudio); + regulator_put(regulator_avsource); + kfree(ptr_audio_codec_cnxt); +} + +static int ste_audio_io_core_api_enable_regulators(int channel_type) +{ + int error = 0; + + switch (channel_type) { + case EAR_CH: + case HS_CH: + case IHF_CH: + case VIBL_CH: + case VIBR_CH: + case LIN_CH: + case FMRX_CH: + case FMTX_CH: + case BLUETOOTH_CH: + /* vaduio already enabled + no additional regualtor required */ + break; + + case MIC1A_CH: + case MIC1B_CH: + error = regulator_enable(regulator_vamic1); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "unable to enable regulator vamic1 error = %d", error); + break; + + case MIC2_CH: + error = regulator_enable(regulator_vamic2); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "unable to enable regulator vamic2 error = %d", error); + break; + + case DMIC12_CH: + case DMIC34_CH: + case DMIC56_CH: + case MULTI_MIC_CH: + error = regulator_enable(regulator_vdmic); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "unable to enable regulator vdmic error = %d", error); + } + return error; +} + +static int ste_audio_io_core_api_disable_regulators(int channel_type) +{ + int error = 0; + + switch (channel_type) { + case EAR_CH: + case HS_CH: + case IHF_CH: + case VIBL_CH: + case VIBR_CH: + case LIN_CH: + case FMRX_CH: + case FMTX_CH: + case BLUETOOTH_CH: + /* no need to disable separately*/ + break; + + case MIC1A_CH: + case MIC1B_CH: + error = regulator_disable(regulator_vamic1); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "unable to disable regulator vamic1 error = %d", error); + break; + + case MIC2_CH: + error = regulator_disable(regulator_vamic2); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "unable to disable regulator vamic2 error = %d", error); + break; + + case DMIC12_CH: + case DMIC34_CH: + case DMIC56_CH: + case MULTI_MIC_CH: + error = regulator_disable(regulator_vdmic); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "unable to disable regulator vdmic error = %d", error); + } + return error; +} + +int ste_audio_io_core_api_powerup_audiocodec(int power_client) +{ + int error = 0; + int acodec_device_id; + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + acodec_device_id = abx500_get_chip_id(&ste_audio_io_device->dev); + + /* + * If there is no power client registered, power up + * common audio blocks for audio and vibrator + */ + if (!ptr_audio_codec_cnxt->power_client) { + __u8 data, old_data; + + old_data = HW_REG_READ(AB8500_CTRL3_REG); + + /* Enable 32 Khz clock signal on Clk32KOut2 ball */ + data = (~CLK_32K_OUT2_DISABLE) & old_data; + error = HW_REG_WRITE(AB8500_CTRL3_REG, data); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "enabling 32KHz clock error = %d", error); + goto err_cleanup; + } + data = INACTIVE_RESET_AUDIO | old_data; + error = HW_REG_WRITE(AB8500_CTRL3_REG, data); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "deactivate audio codec reset error = %d", error); + goto err_cleanup; + } + old_data = HW_REG_READ(AB8500_SYSULPCLK_CTRL1_REG); + data = ENABLE_AUDIO_CLK_TO_AUDIO_BLK | old_data; + + error = HW_REG_WRITE(AB8500_SYSULPCLK_CTRL1_REG, data); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "enabling clock to audio block error = %d", error); + goto err_cleanup; + } + regulator_enable(regulator_vaudio); + + old_data = HW_REG_READ(AB8500_GPIO_DIR4_REG); + data = (GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | + GPIO31_DIR_OUTPUT) | old_data; + error = HW_REG_WRITE(AB8500_GPIO_DIR4_REG, data); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "setting gpio dir4 error = %d", error); + goto err_cleanup; + } + error = HW_REG_WRITE(SOFTWARE_RESET_REG, SW_RESET); + if (error != 0) { + dev_err(ptr_audio_codec_cnxt->dev, + "Software reset error=%d", error); + goto err_cleanup; + } + + error = HW_ACODEC_MODIFY_WRITE(POWER_UP_CONTROL_REG, + (DEVICE_POWER_UP|ANALOG_PARTS_POWER_UP), 0); + if (error != 0) { + dev_err(ptr_audio_codec_cnxt->dev, + "Device Power Up, error=%d", error); + goto err_cleanup; + } + } + /* Save information that given client already powered up audio block */ + ptr_audio_codec_cnxt->power_client |= power_client; + + /* If audio block requested power up, turn on additional audio blocks */ + if (power_client == STE_AUDIOIO_POWER_AUDIO) { + if (!ptr_audio_codec_cnxt->audio_codec_powerup) { + clk_ptr_sysclk = + clk_get(ptr_audio_codec_cnxt->dev, "sysclk"); + if (!IS_ERR(clk_ptr_sysclk)) { + error = clk_enable(clk_ptr_sysclk); + if (error) + goto err_cleanup; + } else { + error = -EFAULT; + goto err_cleanup; + } + + clk_ptr_msp1 = clk_get_sys("msp1", NULL); + if (!IS_ERR(clk_ptr_msp1)) { + error = clk_enable(clk_ptr_msp1); + if (error) + goto err_cleanup; + } else { + error = -EFAULT; + goto err_cleanup; + } + + if (AB8500_REV_20 == acodec_device_id) { + clk_ptr_msp3 = clk_get_sys("msp3", NULL); + if (!IS_ERR(clk_ptr_msp3)) { + error = clk_enable(clk_ptr_msp3); + if (error) + goto err_cleanup; + } else { + error = -EFAULT; + goto err_cleanup; + } + } + + if (ptr_audio_codec_cnxt->gpio_altf_init) { + error = ptr_audio_codec_cnxt->gpio_altf_init(); + if (error) + goto err_cleanup; + } + + error = HW_ACODEC_MODIFY_WRITE(IF0_IF1_MASTER_CONF_REG, + EN_MASTGEN, 0); + if (error != 0) { + dev_err(ptr_audio_codec_cnxt->dev, + "Enable Master Generator, error=%d", error); + goto err_cleanup; + } + + error = HW_ACODEC_MODIFY_WRITE(TDM_IF_BYPASS_B_FIFO_REG, + IF0_MASTER, 0); + if (error != 0) { + dev_err(ptr_audio_codec_cnxt->dev, + "IF0: Master Mode, error=%d", error); + goto err_cleanup; + } + + /* Configuring IF0 */ + + error = HW_ACODEC_MODIFY_WRITE(IF0_IF1_MASTER_CONF_REG, + BITCLK_OSR_N_256, 0); + if (error != 0) { + dev_err(ptr_audio_codec_cnxt->dev, + "IF0: Enable FsBitClk & FSync error=%d", error); + goto err_cleanup; + } + + error = HW_REG_WRITE(IF0_CONF_REG, IF_DELAYED + | TDM_FORMAT | WORD_LENGTH_20); + if (error != 0) { + dev_err(ptr_audio_codec_cnxt->dev, + "IF0: TDM Format 16 Bits word length, error=%d", + error); + goto err_cleanup; + } + } + ptr_audio_codec_cnxt->audio_codec_powerup++; + } +err_cleanup: + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + return error; +} + +int ste_audio_io_core_api_powerdown_audiocodec(int power_client) +{ + int error = 0; + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + /* Update power client status */ + if (power_client == STE_AUDIOIO_POWER_AUDIO) { + ptr_audio_codec_cnxt->audio_codec_powerup--; + if (!ptr_audio_codec_cnxt->audio_codec_powerup) { + ptr_audio_codec_cnxt->power_client &= ~power_client; + clk_disable(clk_ptr_sysclk); + clk_put(clk_ptr_sysclk); + clk_disable(clk_ptr_msp1); + clk_put(clk_ptr_msp1); + if (AB8500_REV_20 == + abx500_get_chip_id(&ste_audio_io_device->dev)) { + clk_disable(clk_ptr_msp3); + clk_put(clk_ptr_msp3); + } + + if (ptr_audio_codec_cnxt->gpio_altf_exit) { + error = ptr_audio_codec_cnxt->gpio_altf_exit(); + if (error) + goto err_cleanup; + } + } + } else + ptr_audio_codec_cnxt->power_client &= ~power_client; + + /* If no power client registered, power down audio block */ + if (!ptr_audio_codec_cnxt->power_client) { + regulator_disable(regulator_vaudio); + if (error != 0) { + dev_err(ptr_audio_codec_cnxt->dev, + "Device Power Down and Analog Parts Power Down error = %d ", + error); + goto err_cleanup; + } + } + +err_cleanup: + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + return error; +} +/** + * @brief Read from AB8500 device + * @dev_data Pointer to the structure __audioio_data + * @return 0 + */ + +int ste_audio_io_core_api_access_read(struct audioio_data_t *dev_data) +{ + int reg; + if (NULL == dev_data) + return -EFAULT; + reg = (dev_data->block<<8)|(dev_data->addr&0xff); + dev_data->data = HW_REG_READ(reg); + return 0; +} +/** + * @brief Write on AB8500 device + * @dev_data Pointer to the structure __audioio_data + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_core_api_access_write(struct audioio_data_t *dev_data) +{ + int retval, reg; + if (NULL == dev_data) + return -EFAULT; + + reg = (dev_data->block<<8)|(dev_data->addr&0xff); + retval = HW_REG_WRITE(reg, dev_data->data); + + return retval; +} +/** + * @brief Store the power and mute status of transducer + * @channel_index Channel-index of transducer + * @ptr Array storing the status + * @value status being stored + * @return 0 on success otherwise negative error code + */ + +void ste_audio_io_core_api_store_data(enum AUDIOIO_CH_INDEX channel_index, + int *ptr, int value) +{ + if (channel_index & e_CHANNEL_1) + ptr[0] = value; + + if (channel_index & e_CHANNEL_2) + ptr[1] = value; + + if (channel_index & e_CHANNEL_3) + ptr[2] = value; + + if (channel_index & e_CHANNEL_4) + ptr[3] = value; +} +/** + * @brief Get power or mute status on a specific channel + * @channel_index Channel-index of the transducer + * @ptr Pointer to is_power_up array or is_muted array + * @return status of control switch + */ +enum AUDIOIO_COMMON_SWITCH ste_audio_io_core_api_get_status( + enum AUDIOIO_CH_INDEX channel_index, int *ptr) +{ + if (channel_index & e_CHANNEL_1) { + if (AUDIOIO_TRUE == ptr[0]) + return AUDIOIO_COMMON_ON; + else + return AUDIOIO_COMMON_OFF; + } + + if (channel_index & e_CHANNEL_2) { + if (AUDIOIO_TRUE == ptr[1]) + return AUDIOIO_COMMON_ON; + else + return AUDIOIO_COMMON_OFF; + } + + if (channel_index & e_CHANNEL_3) { + if (AUDIOIO_TRUE == ptr[2]) + return AUDIOIO_COMMON_ON; + else + return AUDIOIO_COMMON_OFF; + } + + if (channel_index & e_CHANNEL_4) { + if (AUDIOIO_TRUE == ptr[3]) + return AUDIOIO_COMMON_ON; + else + return AUDIOIO_COMMON_OFF; + } + return 0; +} + +int ste_audio_io_core_api_acodec_power_control(struct audioio_acodec_pwr_ctrl_t + *audio_acodec_pwr_ctrl) +{ + int error = 0; + if (audio_acodec_pwr_ctrl->ctrl_switch == AUDIOIO_COMMON_ON) + error = ste_audio_io_core_api_powerup_audiocodec( + STE_AUDIOIO_POWER_AUDIO); + else + error = ste_audio_io_core_api_powerdown_audiocodec( + STE_AUDIOIO_POWER_AUDIO); + + return error; +} +/** + * @brief Control for powering on/off HW components on a specific channel + * @pwr_ctrl Pointer to the structure __audioio_pwr_ctrl + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_core_api_power_control_transducer( + struct audioio_pwr_ctrl_t *pwr_ctrl) +{ + int error = 0; + struct transducer_context_t *ptr = NULL; + enum AUDIOIO_CH_INDEX channel_index; + + channel_index = pwr_ctrl->channel_index; + + if ((pwr_ctrl->channel_type < FIRST_CH) + || (pwr_ctrl->channel_type > LAST_CH)) + return -EINVAL; + + ptr = ptr_audio_codec_cnxt->transducer[pwr_ctrl->channel_type]; + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + if (AUDIOIO_COMMON_ON == pwr_ctrl->ctrl_switch) { + if (ptr->pwr_up_func) { + error = ste_audio_io_core_api_enable_regulators( + pwr_ctrl->channel_type); + if (error) + goto free_mutex; + + error = ptr->pwr_up_func(pwr_ctrl->channel_index, + ptr_audio_codec_cnxt->dev); + if (0 == error) { + ste_audio_io_core_api_store_data(channel_index, + ptr->is_power_up, AUDIOIO_TRUE); + } + } + } else { + if (ptr->pwr_down_func) { + error = ptr->pwr_down_func(pwr_ctrl->channel_index, + ptr_audio_codec_cnxt->dev); + if (0 == error) { + ste_audio_io_core_api_store_data(channel_index, + ptr->is_power_up, AUDIOIO_FALSE); + } + error = ste_audio_io_core_api_disable_regulators( + pwr_ctrl->channel_type); + } + } + +free_mutex: + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return error; +} +/** + * @brief Query power state of HW path on specified channel + * @pwr_ctrl Pointer to the structure __audioio_pwr_ctrl + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_core_api_power_status_transducer( + struct audioio_pwr_ctrl_t *pwr_ctrl) +{ + + struct transducer_context_t *ptr = NULL; + enum AUDIOIO_CH_INDEX channel_index; + + channel_index = pwr_ctrl->channel_index; + + if ((pwr_ctrl->channel_type < FIRST_CH) + || (pwr_ctrl->channel_type > LAST_CH)) + return -EINVAL; + + ptr = ptr_audio_codec_cnxt->transducer[pwr_ctrl->channel_type]; + + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + + pwr_ctrl->ctrl_switch = ste_audio_io_core_api_get_status(channel_index, + ptr->is_power_up); + + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return 0; + +} + +int ste_audio_io_core_api_loop_control(struct audioio_loop_ctrl_t *loop_ctrl) +{ + int error = 0; + struct transducer_context_t *ptr = NULL; + + if ((loop_ctrl->channel_type < FIRST_CH) + || (loop_ctrl->channel_type > LAST_CH)) + return -EINVAL; + + ptr = ptr_audio_codec_cnxt->transducer[loop_ctrl->channel_type]; + + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + if (AUDIOIO_COMMON_ON == loop_ctrl->ctrl_switch) { + if (ptr->enable_loop) { + error = ptr->enable_loop(loop_ctrl->channel_index, + loop_ctrl->hw_loop, + loop_ctrl->loop_gain, + ptr_audio_codec_cnxt->dev, + ptr_audio_codec_cnxt->transducer); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "Loop enable failed for hw loop = %d, error = %d ", + (int)loop_ctrl->hw_loop, error); + } else { + error = -EFAULT; + dev_err(ptr_audio_codec_cnxt->dev, + "Hw Loop enable does not exist for channel= %d, error = %d ", + (int)loop_ctrl->channel_type, error); + } + } else { + if (ptr->disable_loop) { + error = ptr->disable_loop(loop_ctrl->channel_index, + loop_ctrl->hw_loop, + ptr_audio_codec_cnxt->dev, + ptr_audio_codec_cnxt->transducer); + if (error) + dev_err(ptr_audio_codec_cnxt->dev, + "Loop disable failed for hw loop = %d, error = %d ", + (int)loop_ctrl->hw_loop, error); + } else { + error = -EFAULT; + dev_err(ptr_audio_codec_cnxt->dev, + "Hw Loop disable does not exist for channel= %d, error = %d ", + (int)loop_ctrl->channel_type, error); + } + } + + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return error; +} + +int ste_audio_io_core_api_loop_status(struct audioio_loop_ctrl_t *loop_ctrl) +{ + return 0; +} + +int ste_audio_io_core_api_get_transducer_gain_capability( + struct audioio_get_gain_t *get_gain) +{ + return 0; +} + +int ste_audio_io_core_api_gain_capabilities_loop( + struct audioio_gain_loop_t *gain_loop) +{ + if ((gain_loop->channel_type < FIRST_CH) + || (gain_loop->channel_type > LAST_CH)) + return -EINVAL; + + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + gain_loop->num_loop = + transducer_max_no_Of_supported_loops[gain_loop->channel_type]; + gain_loop->max_gains = max_no_of_loop_gains[gain_loop->channel_type]; + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + return 0; +} + +int ste_audio_io_core_api_supported_loops( + struct audioio_support_loop_t *support_loop) +{ + if ((support_loop->channel_type < FIRST_CH) + || (support_loop->channel_type > LAST_CH)) + return -EINVAL; + + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + support_loop->spprtd_loop_index = + transducer_no_Of_supported_loop_indexes[support_loop->channel_type]; + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + return 0; +} + +int ste_audio_io_core_api_gain_descriptor_transducer( + struct audioio_gain_desc_trnsdr_t *gdesc_trnsdr) +{ + return 0; +} +/** + * @brief Control for muting a specific channel in HW + * @mute_trnsdr Pointer to the structure __audioio_mute_trnsdr + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_core_api_mute_control_transducer( + struct audioio_mute_trnsdr_t *mute_trnsdr) +{ + int error = 0; + struct transducer_context_t *ptr = NULL; + enum AUDIOIO_CH_INDEX channel_index; + + channel_index = mute_trnsdr->channel_index; + + if ((mute_trnsdr->channel_type < FIRST_CH) + || (mute_trnsdr->channel_type > LAST_CH)) + return -EINVAL; + + ptr = ptr_audio_codec_cnxt->transducer[mute_trnsdr->channel_type]; + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + if (AUDIOIO_COMMON_ON == mute_trnsdr->ctrl_switch) { + if (ptr->mute_func) { + error = ptr->mute_func(mute_trnsdr->channel_index, + ptr_audio_codec_cnxt->dev); + if (0 == error) { + ste_audio_io_core_api_store_data(channel_index , + ptr->is_muted, AUDIOIO_TRUE); + } + } + } else { + if (ptr->unmute_func) { + if (0 == ptr->unmute_func(channel_index, ptr->gain, + ptr_audio_codec_cnxt->dev)) { + ste_audio_io_core_api_store_data(channel_index, + ptr->is_muted, AUDIOIO_FALSE); + } + } + } + + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return error; +} +/** + * @brief Query state of mute on specified channel + * @mute_trnsdr Pointer to the structure __audioio_mute_trnsdr + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_core_api_mute_status_transducer( + struct audioio_mute_trnsdr_t *mute_trnsdr) +{ + struct transducer_context_t *ptr = NULL; + enum AUDIOIO_CH_INDEX channel_index; + + channel_index = mute_trnsdr->channel_index; + + if ((mute_trnsdr->channel_type < FIRST_CH) + || (mute_trnsdr->channel_type > LAST_CH)) + return -EINVAL; + + ptr = ptr_audio_codec_cnxt->transducer[mute_trnsdr->channel_type]; + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + mute_trnsdr->ctrl_switch = ste_audio_io_core_api_get_status( + channel_index, ptr->is_muted); + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return 0; +} +/** + * @brief control the fading on the transducer called on. + * @fade_ctrl Pointer to the structure __audioio_fade_ctrl + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_core_api_fading_control(struct audioio_fade_ctrl_t *fade_ctrl) +{ + int error = 0; + struct transducer_context_t *ptr = NULL; + + if ((fade_ctrl->channel_type < FIRST_CH) + || (fade_ctrl->channel_type > LAST_CH)) + return -EINVAL; + ptr = ptr_audio_codec_cnxt->transducer[fade_ctrl->channel_type]; + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + if (AUDIOIO_COMMON_ON == fade_ctrl->ctrl_switch) + error = ptr->enable_fade_func(ptr_audio_codec_cnxt->dev); + + else + error = ptr->disable_fade_func(ptr_audio_codec_cnxt->dev); + + + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return error; +} +/** + * @brief control the low power mode of headset. + * @burst_ctrl Pointer to the structure __audioio_burst_ctrl + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_core_api_burstmode_control( + struct audioio_burst_ctrl_t *burst_ctrl) +{ + int error = 0; + struct transducer_context_t *ptr = NULL; + int burst_fifo_switch_frame; + + burst_fifo_switch_frame = burst_ctrl->burst_fifo_switch_frame; + + if ((burst_ctrl->channel_type < FIRST_CH) + || (burst_ctrl->channel_type > LAST_CH)) + return -EINVAL; + ptr = ptr_audio_codec_cnxt->transducer[burst_ctrl->channel_type]; + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + if (AUDIOIO_COMMON_ON == burst_ctrl->ctrl_switch) { + if (ptr->switch_to_burst_func) + error = ptr->switch_to_burst_func( + burst_fifo_switch_frame, + ptr_audio_codec_cnxt->dev); + } else + if (ptr->switch_to_normal_func) + error = ptr->switch_to_normal_func( + ptr_audio_codec_cnxt->dev); + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return error; +} +/** + * @brief Convert channel index to array index + * @channel_index Channel Index of transducer + * @return Array index corresponding to the specified channel index + */ + +int convert_channel_index_to_array_index(enum AUDIOIO_CH_INDEX channel_index) +{ + if (channel_index & e_CHANNEL_1) + return 0; + else if (channel_index & e_CHANNEL_2) + return 1; + else if (channel_index & e_CHANNEL_3) + return 2; + else + return 3; +} + +/** + * @brief Set individual gain along the HW path of a specified channel + * @gctrl_trnsdr Pointer to the structure __audioio_gain_ctrl_trnsdr + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_core_api_gain_control_transducer( + struct audioio_gain_ctrl_trnsdr_t *gctrl_trnsdr) +{ + struct transducer_context_t *ptr = NULL; + enum AUDIOIO_CH_INDEX channel_index; + int ch_array_index; + u16 gain_index; + int gain_value; + u32 linear; + int channel_type; + int error; + int min_gain, max_gain, gain; + + if ((gctrl_trnsdr->channel_type < FIRST_CH) + || (gctrl_trnsdr->channel_type > LAST_CH)) + return -EINVAL; + + if (gctrl_trnsdr->gain_index >= MAX_NO_GAINS) + return -EINVAL; + + ptr = ptr_audio_codec_cnxt->transducer[gctrl_trnsdr->channel_type]; + channel_index = gctrl_trnsdr->channel_index; + gain_index = gctrl_trnsdr->gain_index; + gain_value = gctrl_trnsdr->gain_value; + linear = gctrl_trnsdr->linear; + channel_type = gctrl_trnsdr->channel_type; + + ch_array_index = convert_channel_index_to_array_index(channel_index); + if (linear) { /* Gain is in the range 0 to 100 */ + min_gain = gain_descriptor[channel_type]\ + [ch_array_index][gain_index].min_gain; + max_gain = gain_descriptor[channel_type]\ + [ch_array_index][gain_index].max_gain; + + gain = ((gain_value * (max_gain - min_gain))/100) + min_gain; + } else + /* Convert to db */ + gain = gain_value/100; + + gain_value = gain; + +#if 1 + if (gain_index >= transducer_no_of_gains[channel_type]) + return -EINVAL; + + if (gain_value < gain_descriptor[channel_type]\ + [ch_array_index][gain_index].min_gain) + return -EINVAL; + + if (gain_value > gain_descriptor[channel_type]\ + [ch_array_index][gain_index].max_gain) + return -EINVAL; + +#endif + + /* aquire mutex */ + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + error = ptr->set_gain_func(channel_index, + gain_index, gain_value, linear, + ptr_audio_codec_cnxt->dev); + if (0 == error) + ste_audio_io_core_api_store_data(channel_index , + ptr->gain, gain_value); + + + /* release mutex */ + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + return error; +} +/** + * @brief Get individual gain along the HW path of a specified channel + * @gctrl_trnsdr Pointer to the structure __audioio_gain_ctrl_trnsdr + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_core_api_gain_query_transducer( + struct audioio_gain_ctrl_trnsdr_t *gctrl_trnsdr) +{ + struct transducer_context_t *ptr = NULL; + enum AUDIOIO_CH_INDEX channel_index; + u16 gain_index; + u32 linear; + int left_volume, right_volume; + int max_gain, min_gain; + int ch_array_index; + + if ((gctrl_trnsdr->channel_type < FIRST_CH) + || (gctrl_trnsdr->channel_type > LAST_CH)) + return -EINVAL; + + if (gctrl_trnsdr->gain_index >= MAX_NO_GAINS) + return -EINVAL; + + ptr = ptr_audio_codec_cnxt->transducer[gctrl_trnsdr->channel_type]; + + channel_index = gctrl_trnsdr->channel_index; + gain_index = gctrl_trnsdr->gain_index; + linear = gctrl_trnsdr->linear; + + ptr->get_gain_func(&left_volume, &right_volume, gain_index, + ptr_audio_codec_cnxt->dev); + + ch_array_index = convert_channel_index_to_array_index(channel_index); + max_gain = gain_descriptor[gctrl_trnsdr->channel_type]\ + [ch_array_index][gain_index].max_gain; + min_gain = gain_descriptor[gctrl_trnsdr->channel_type]\ + [ch_array_index][gain_index].min_gain; + + switch (channel_index) { + case e_CHANNEL_1: + gctrl_trnsdr->gain_value = linear ? \ + min_gain+left_volume*(max_gain-min_gain)/100 : left_volume; + break; + case e_CHANNEL_2: + gctrl_trnsdr->gain_value = linear ? \ + min_gain+right_volume*(max_gain-min_gain)/100 : right_volume; + break; + case e_CHANNEL_3: + break; + case e_CHANNEL_4: + break; + case e_CHANNEL_ALL: + if (left_volume == right_volume) { + if (linear) + gctrl_trnsdr->gain_value = + min_gain+right_volume*(max_gain-min_gain)/100; + else + gctrl_trnsdr->gain_value = right_volume; + } + } + + return 0; +} + + +int ste_audio_io_core_api_fsbitclk_control( + struct audioio_fsbitclk_ctrl_t *fsbitclk_ctrl) +{ + int error = 0; + + if (AUDIOIO_COMMON_ON == fsbitclk_ctrl->ctrl_switch) + error = HW_ACODEC_MODIFY_WRITE(IF0_IF1_MASTER_CONF_REG, + EN_FSYNC_BITCLK, 0); + else + error = HW_ACODEC_MODIFY_WRITE(IF0_IF1_MASTER_CONF_REG, 0, + EN_FSYNC_BITCLK); + + return error; +} +int ste_audio_io_core_api_pseudoburst_control( + struct audioio_pseudoburst_ctrl_t *pseudoburst_ctrl) +{ + int error = 0; + + return error; +} +int ste_audio_io_core_debug(int x) +{ + debug_audioio(x); + +return 0; +} + +/** + * ste_audioio_vibrator_alloc() + * @client: Client id which allocates vibrator + * @mask: Mask against which vibrator usage is checked + * + * This function allocates vibrator. + * Mask is added here as audioio driver controls left and right vibrator + * separately (can work independently). In case when audioio has allocated + * one of its channels (left or right) it should be still able to allocate + * the other channel. + * + * Returns: + * 0 - Success + * -EBUSY - other client already registered + **/ +int ste_audioio_vibrator_alloc(int client, int mask) +{ + int error = 0; + + /* Check if other client is already using vibrator */ + if (ptr_audio_codec_cnxt->vibra_client & ~mask) + error = -EBUSY; + else + ptr_audio_codec_cnxt->vibra_client |= client; + + return error; +} + +/** + * ste_audioio_vibrator_release() + * @client: Client id which releases vibrator + * + * This function releases vibrator + **/ +void ste_audioio_vibrator_release(int client) +{ + ptr_audio_codec_cnxt->vibra_client &= ~client; +} + +/** + * ste_audioio_vibrator_pwm_control() + * @client: Client id which will use vibrator + * @left_speed: Left vibrator speed + * @right_speed: Right vibrator speed + * + * This function controls vibrator using PWM source + * + * Returns: + * 0 - success + * -EBUSY - Vibrator already used + **/ +int ste_audioio_vibrator_pwm_control( + int client, + struct ste_vibra_speed left_speed, + struct ste_vibra_speed right_speed) +{ + int error = 0; + + mutex_lock(&ptr_audio_codec_cnxt->audio_io_mutex); + + /* Try to allocate vibrator for given client */ + error = ste_audioio_vibrator_alloc(client, client); + + mutex_unlock(&ptr_audio_codec_cnxt->audio_io_mutex); + + if (error) + return error; + + /* Duty cycle supported by vibrator's PWM is 0-100 */ + if (left_speed.positive > STE_AUDIOIO_VIBRATOR_MAX_SPEED) + left_speed.positive = STE_AUDIOIO_VIBRATOR_MAX_SPEED; + + if (right_speed.positive > STE_AUDIOIO_VIBRATOR_MAX_SPEED) + right_speed.positive = STE_AUDIOIO_VIBRATOR_MAX_SPEED; + + if (left_speed.negative > STE_AUDIOIO_VIBRATOR_MAX_SPEED) + left_speed.negative = STE_AUDIOIO_VIBRATOR_MAX_SPEED; + + if (right_speed.negative > STE_AUDIOIO_VIBRATOR_MAX_SPEED) + right_speed.negative = STE_AUDIOIO_VIBRATOR_MAX_SPEED; + + if (left_speed.negative || right_speed.negative || + left_speed.positive || right_speed.positive) { + /* Power up audio block for vibrator */ + error = ste_audio_io_core_api_powerup_audiocodec( + STE_AUDIOIO_POWER_VIBRA); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Audio power up failed %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + (EN_VIBL_MASK|EN_VIBR_MASK), 0); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Powerup Vibrator Class-D driver %d", + error); + return error; + } + + error = HW_REG_WRITE(VIB_DRIVER_CONF_REG, 0xff); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Enable Vibrator PWM generator %d", + error); + return error; + } + } + + error = HW_REG_WRITE(PWM_VIBNL_CONF_REG, left_speed.negative); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Write Left Vibrator negative PWM %d", error); + goto err_cleanup; + } + + error = HW_REG_WRITE(PWM_VIBPL_CONF_REG, left_speed.positive); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Write Left Vibrator positive PWM %d", error); + goto err_cleanup; + } + + error = HW_REG_WRITE(PWM_VIBNR_CONF_REG, right_speed.negative); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Write Right Vibrator negative PWM %d", error); + goto err_cleanup; + } + + error = HW_REG_WRITE(PWM_VIBPR_CONF_REG, right_speed.positive); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Write Right Vibrator positive PWM %d", error); + goto err_cleanup; + } + + if (!left_speed.negative && !right_speed.negative && + !left_speed.positive && !right_speed.positive) { + error = HW_REG_WRITE(VIB_DRIVER_CONF_REG, 0); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Disable PWM Vibrator generator %d", + error); + goto err_cleanup; + } + + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + 0, (EN_VIBL_MASK|EN_VIBR_MASK)); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Power down Vibrator Class-D driver %d", + error); + goto err_cleanup; + } + + /* Power down audio block */ + error = ste_audio_io_core_api_powerdown_audiocodec( + STE_AUDIOIO_POWER_VIBRA); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "Audio power down failed %d", error); + goto err_cleanup; + } + } + +err_cleanup: + /* Release client */ + if (!left_speed.negative && !right_speed.negative && + !left_speed.positive && !right_speed.positive) { + mutex_lock(&ptr_audio_codec_cnxt->audio_io_mutex); + ste_audioio_vibrator_release(client); + mutex_unlock(&ptr_audio_codec_cnxt->audio_io_mutex); + } + return error; +} +EXPORT_SYMBOL(ste_audioio_vibrator_pwm_control); + +/** + * @brief This function sets FIR coefficients + * @fir_coeffs: pointer to structure audioio_fir_coefficients_t + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_core_api_fir_coeffs_control(struct audioio_fir_coefficients_t + *fir_coeffs) +{ + unsigned char coefficient; + int i, error; + + if (fir_coeffs->start_addr >= STE_AUDIOIO_MAX_COEFFICIENTS) + return -EINVAL; + + mutex_lock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + + error = HW_REG_WRITE(SIDETONE_FIR_ADDR_REG, fir_coeffs->start_addr); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "FIR start address write failed %d", error); + goto err_cleanup; + } + + for (i = fir_coeffs->start_addr; + i < STE_AUDIOIO_MAX_COEFFICIENTS; i++) { + + coefficient = (fir_coeffs->coefficients[i]>>8) & 0xff; + error = HW_REG_WRITE(SIDETONE_FIR_COEFF_MSB_REG, coefficient); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "FIR coefficient [%d] msb write failed %d", i, error); + goto err_cleanup; + } + + coefficient = fir_coeffs->coefficients[i] & 0xff; + error = HW_REG_WRITE(SIDETONE_FIR_COEFF_LSB_REG, coefficient); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "FIR coefficient [%d] lsb write failed %d", i, error); + goto err_cleanup; + } + } + + error = HW_ACODEC_MODIFY_WRITE(SIDETONE_FIR_ADDR_REG, + APPLY_FIR_COEFFS_MASK, 0); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "FIR coefficients activation failed %d", error); + goto err_cleanup; + } + + error = HW_ACODEC_MODIFY_WRITE(FILTERS_CONTROL_REG, + FIR_FILTERCONTROL, 0); + if (error) { + dev_err(ptr_audio_codec_cnxt->dev, + "ST FIR Filters enable failed %d", error); + goto err_cleanup; + } + +err_cleanup: + mutex_unlock(&(ptr_audio_codec_cnxt->audio_io_mutex)); + return error; +} diff --git a/drivers/misc/audio_io_dev/ste_audio_io_core.h b/drivers/misc/audio_io_dev/ste_audio_io_core.h new file mode 100644 index 00000000000..7d109eb9e83 --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_core.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#ifndef _AUDIOIO_CORE_H_ +#define _AUDIOIO_CORE_H_ + +#include +#include "ste_audio_io_func.h" +#include "ste_audio_io_hwctrl_common.h" + +#define MAX_NO_CHANNELS 4 + +#define STE_AUDIOIO_POWER_AUDIO 1 +#define STE_AUDIOIO_POWER_VIBRA 2 + +struct transducer_context_t { + /* public variables */ + int gain[MAX_NO_CHANNELS]; + int is_muted[MAX_NO_CHANNELS]; + int is_power_up[MAX_NO_CHANNELS]; + /* public funcs */ + int (*pwr_up_func)(enum AUDIOIO_CH_INDEX, struct device *); + int (*pwr_down_func)(enum AUDIOIO_CH_INDEX, struct device *); + int (*pwr_state_func)(struct device *); + int (*set_gain_func)(enum AUDIOIO_CH_INDEX, u16, int, u32, + struct device *); + int (*get_gain_func)(int *, int *, u16, struct device *); + int (*mute_func)(enum AUDIOIO_CH_INDEX, struct device *); + int (*unmute_func)(enum AUDIOIO_CH_INDEX, int *, struct device *); + int (*mute_state_func)(struct device *); + int (*enable_fade_func)(struct device *); + int (*disable_fade_func)(struct device *); + int (*switch_to_burst_func)(int, struct device *); + int (*switch_to_normal_func)(struct device *); + int (*enable_loop)(enum AUDIOIO_CH_INDEX, enum AUDIOIO_HAL_HW_LOOPS, + int, struct device *, void *); + int (*disable_loop)(enum AUDIOIO_CH_INDEX, enum AUDIOIO_HAL_HW_LOOPS, + struct device *, void *); +}; + +struct audiocodec_context_t { + int audio_codec_powerup; + int power_client; + int vibra_client; + struct mutex audio_io_mutex; + struct mutex vibrator_mutex; + struct transducer_context_t *transducer[MAX_NO_TRANSDUCERS]; + struct device *dev; + int (*gpio_altf_init) (void); + int (*gpio_altf_exit) (void); +}; + + +int ste_audio_io_core_api_access_read(struct audioio_data_t *dev_data); + +int ste_audio_io_core_api_access_write(struct audioio_data_t *dev_data); + +int ste_audio_io_core_api_power_control_transducer( + struct audioio_pwr_ctrl_t *pwr_ctrl); + +int ste_audio_io_core_api_power_status_transducer( + struct audioio_pwr_ctrl_t *pwr_ctrl); + +int ste_audio_io_core_api_loop_control(struct audioio_loop_ctrl_t *loop_ctrl); + +int ste_audio_io_core_api_loop_status(struct audioio_loop_ctrl_t *loop_ctrl); + +int ste_audio_io_core_api_get_transducer_gain_capability( + struct audioio_get_gain_t *get_gain); + +int ste_audio_io_core_api_gain_capabilities_loop( + struct audioio_gain_loop_t *gain_loop); + +int ste_audio_io_core_api_supported_loops( + struct audioio_support_loop_t *support_loop); + +int ste_audio_io_core_api_gain_descriptor_transducer( + struct audioio_gain_desc_trnsdr_t *gdesc_trnsdr); + +int ste_audio_io_core_api_gain_control_transducer( + struct audioio_gain_ctrl_trnsdr_t *gctrl_trnsdr); + +int ste_audio_io_core_api_gain_query_transducer( + struct audioio_gain_ctrl_trnsdr_t *gctrl_trnsdr); + +int ste_audio_io_core_api_mute_control_transducer( + struct audioio_mute_trnsdr_t *mute_trnsdr); + +int ste_audio_io_core_api_mute_status_transducer( + struct audioio_mute_trnsdr_t *mute_trnsdr); + +int ste_audio_io_core_api_fading_control(struct audioio_fade_ctrl_t *fade_ctrl); + +int ste_audio_io_core_api_burstmode_control( + struct audioio_burst_ctrl_t *burst_ctrl); + +int ste_audio_io_core_api_powerup_audiocodec(int power_client); + +int ste_audio_io_core_api_powerdown_audiocodec(int power_client); + +int ste_audio_io_core_api_init_data(struct platform_device *pdev); + +bool ste_audio_io_core_is_ready_for_suspend(void); +void ste_audio_io_core_api_free_data(void); + +int ste_audio_io_core_api_fsbitclk_control( + struct audioio_fsbitclk_ctrl_t *fsbitclk_ctrl); +int ste_audio_io_core_api_pseudoburst_control( + struct audioio_pseudoburst_ctrl_t *pseudoburst_ctrl); + +void ste_audio_io_core_api_store_data(enum AUDIOIO_CH_INDEX channel_index, + int *ptr, int value); + +int ste_audioio_vibrator_alloc(int client, int mask); + +void ste_audioio_vibrator_release(int client); + +enum AUDIOIO_COMMON_SWITCH ste_audio_io_core_api_get_status( + enum AUDIOIO_CH_INDEX channel_index, int *ptr); + +int ste_audio_io_core_api_acodec_power_control(struct audioio_acodec_pwr_ctrl_t + *audio_acodec_pwr_ctrl); + +int ste_audio_io_core_api_fir_coeffs_control(struct audioio_fir_coefficients_t + *fir_coeffs); + +int ste_audio_io_core_debug(int x); + +#endif /* _AUDIOIO_CORE_H_ */ + diff --git a/drivers/misc/audio_io_dev/ste_audio_io_dev.c b/drivers/misc/audio_io_dev/ste_audio_io_dev.c new file mode 100644 index 00000000000..8b677909104 --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_dev.c @@ -0,0 +1,738 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ste_audio_io_dev.h" + +#define STR_DEBUG_ON "debug on" +#define AUDIOIO_DEVNAME "ab8500-codec" + +static int ste_audio_io_open(struct inode *inode, struct file *filp); +static int ste_audio_io_release(struct inode *inode, struct file *filp); +static long ste_audio_io_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); +static int ste_audio_io_cmd_parser(unsigned int cmd, unsigned long arg); +static ssize_t ste_audio_io_write(struct file *filp, + const char __user *buf, size_t count, loff_t *f_pos); + + +/** + * @brief Check IOCTL type, command no and access direction + * @ inode value corresponding to the file descriptor + * @file value corresponding to the file descriptor + * @cmd IOCTL command code + * @arg Command argument + * @return 0 on success otherwise negative error code + */ +static long ste_audio_io_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int retval = 0; + int err = 0; + + /* Check type and command number */ + if (_IOC_TYPE(cmd) != AUDIOIO_IOC_MAGIC) + return -ENOTTY; + + /* IOC_DIR is from the user perspective, while access_ok is + * from the kernel perspective; so they look reversed. + */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, + _IOC_SIZE(cmd)); + if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, + _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + retval = ste_audio_io_cmd_parser(cmd, arg); + + return retval; +} +/** + * @brief IOCTL call to read the value from AB8500 device + * @cmd IOCTL command code + * @arg Command argument + * @return 0 on success otherwise negative error code + */ + +static int process_read_register_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_data_t *audio_dev_data; + + audio_dev_data = (struct audioio_data_t *)&cmd_data; + + if (copy_from_user(audio_dev_data, (void __user *)arg, + sizeof(struct audioio_data_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_access_read(audio_dev_data); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_dev_data, + sizeof(struct audioio_data_t))) + return -EFAULT; + return 0; +} +/** + * @brief IOCTL call to write the given value to the AB8500 device + * @cmd IOCTL command code + * @arg Command argument + * @return 0 on success otherwise negative error code + */ + +static int process_write_register_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_data_t *audio_dev_data; + + audio_dev_data = (struct audioio_data_t *)&cmd_data; + + if (copy_from_user(audio_dev_data, (void __user *)arg, + sizeof(struct audioio_data_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_access_write(audio_dev_data); + + return retval; +} +/** + * @brief IOCTL call to control the power on/off of hardware components + * @cmd IOCTL command code + * @arg Command argument + * @return 0 on success otherwise negative error code + */ + +static int process_pwr_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_pwr_ctrl_t *audio_pwr_ctrl; + + audio_pwr_ctrl = (struct audioio_pwr_ctrl_t *)&cmd_data; + + if (copy_from_user(audio_pwr_ctrl, (void __user *)arg, + sizeof(struct audioio_pwr_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_power_control_transducer(audio_pwr_ctrl); + + return retval; +} + +static int process_pwr_sts_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_pwr_ctrl_t *audio_pwr_sts; + + audio_pwr_sts = (struct audioio_pwr_ctrl_t *)&cmd_data; + + if (copy_from_user(audio_pwr_sts, (void __user *)arg, + sizeof(struct audioio_pwr_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_power_status_transducer(audio_pwr_sts); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_pwr_sts, + sizeof(struct audioio_pwr_ctrl_t))) + return -EFAULT; + + return 0; +} + +static int process_lp_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_loop_ctrl_t *audio_lp_ctrl; + + audio_lp_ctrl = (struct audioio_loop_ctrl_t *)&cmd_data; + + if (copy_from_user(audio_lp_ctrl, (void __user *)arg, + sizeof(struct audioio_loop_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_loop_control(audio_lp_ctrl); + + return retval; +} + +static int process_lp_sts_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_loop_ctrl_t *audio_lp_sts; + + audio_lp_sts = (struct audioio_loop_ctrl_t *)&cmd_data; + + + if (copy_from_user(audio_lp_sts, (void __user *)arg, + sizeof(struct audioio_loop_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_loop_status(audio_lp_sts); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_lp_sts, + sizeof(struct audioio_loop_ctrl_t))) + return -EFAULT; + return 0; +} + +static int process_get_trnsdr_gain_capability_cmd(unsigned int cmd, + unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_get_gain_t *audio_trnsdr_gain; + + audio_trnsdr_gain = (struct audioio_get_gain_t *)&cmd_data; + + if (copy_from_user(audio_trnsdr_gain, (void __user *)arg, + sizeof(struct audioio_get_gain_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_get_transducer_gain_capability( + audio_trnsdr_gain); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_trnsdr_gain, + sizeof(struct audioio_get_gain_t))) + return -EFAULT; + return 0; +} + +static int process_gain_cap_loop_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_gain_loop_t *audio_gain_loop; + + audio_gain_loop = (struct audioio_gain_loop_t *)&cmd_data; + + if (copy_from_user(audio_gain_loop, (void __user *)arg, + sizeof(struct audioio_gain_loop_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_gain_capabilities_loop(audio_gain_loop); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_gain_loop, + sizeof(struct audioio_gain_loop_t))) + return -EFAULT; + return 0; +} + + +static int process_support_loop_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_support_loop_t *audio_spprt_loop; + + audio_spprt_loop = (struct audioio_support_loop_t *)&cmd_data; + + if (copy_from_user(audio_spprt_loop, (void __user *)arg, + sizeof(struct audioio_support_loop_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_supported_loops(audio_spprt_loop); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_spprt_loop, + sizeof(struct audioio_support_loop_t))) + return -EFAULT; + return 0; +} + + +static int process_gain_desc_trnsdr_cmd(unsigned int cmd, unsigned long arg) + +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_gain_desc_trnsdr_t *audio_gain_desc; + + audio_gain_desc = (struct audioio_gain_desc_trnsdr_t *)&cmd_data; + + if (copy_from_user(audio_gain_desc, (void __user *)arg, + sizeof(struct audioio_gain_desc_trnsdr_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_gain_descriptor_transducer( + audio_gain_desc); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_gain_desc, + sizeof(struct audioio_gain_desc_trnsdr_t))) + return -EFAULT; + return 0; +} + + +static int process_gain_ctrl_trnsdr_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_gain_ctrl_trnsdr_t *audio_gain_ctrl; + + audio_gain_ctrl = (struct audioio_gain_ctrl_trnsdr_t *)&cmd_data; + + if (copy_from_user(audio_gain_ctrl, (void __user *)arg, + sizeof(struct audioio_gain_ctrl_trnsdr_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_gain_control_transducer( + audio_gain_ctrl); + + return retval; +} + +static int process_gain_query_trnsdr_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_gain_ctrl_trnsdr_t *audio_gain_query; + + audio_gain_query = (struct audioio_gain_ctrl_trnsdr_t *)&cmd_data; + + if (copy_from_user(audio_gain_query, (void __user *)arg, + sizeof(struct audioio_gain_ctrl_trnsdr_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_gain_query_transducer(audio_gain_query); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_gain_query, + sizeof(struct audioio_gain_ctrl_trnsdr_t))) + return -EFAULT; + return 0; +} + +static int process_mute_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_mute_trnsdr_t *audio_mute_ctrl; + + audio_mute_ctrl = (struct audioio_mute_trnsdr_t *)&cmd_data; + if (copy_from_user(audio_mute_ctrl , (void __user *)arg, + sizeof(struct audioio_mute_trnsdr_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_mute_control_transducer( + audio_mute_ctrl); + + return retval; +} + +static int process_mute_sts_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_mute_trnsdr_t *audio_mute_sts; + + audio_mute_sts = (struct audioio_mute_trnsdr_t *)&cmd_data; + + if (copy_from_user(audio_mute_sts, (void __user *)arg, + sizeof(struct audioio_mute_trnsdr_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_mute_status_transducer(audio_mute_sts); + if (0 != retval) + return retval; + + if (copy_to_user((void __user *)arg, audio_mute_sts, + sizeof(struct audioio_mute_trnsdr_t))) + return -EFAULT; + return 0; +} + +static int process_fade_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_fade_ctrl_t *audio_fade; + audio_fade = (struct audioio_fade_ctrl_t *)&cmd_data; + + if (copy_from_user(audio_fade , (void __user *)arg, + sizeof(struct audioio_fade_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_fading_control(audio_fade); + + return retval; +} + +static int process_burst_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_burst_ctrl_t *audio_burst; + + audio_burst = (struct audioio_burst_ctrl_t *)&cmd_data; + if (copy_from_user(audio_burst , (void __user *)arg, + sizeof(struct audioio_burst_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_burstmode_control(audio_burst); + + return retval; + + return 0; +} + +static int process_fsbitclk_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_fsbitclk_ctrl_t *audio_fsbitclk; + + audio_fsbitclk = (struct audioio_fsbitclk_ctrl_t *)&cmd_data; + + if (copy_from_user(audio_fsbitclk , (void __user *)arg, + sizeof(struct audioio_fsbitclk_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_fsbitclk_control(audio_fsbitclk); + + return retval; + + return 0; + +} + +static int process_pseudoburst_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_pseudoburst_ctrl_t *audio_pseudoburst; + + audio_pseudoburst = (struct audioio_pseudoburst_ctrl_t *)&cmd_data; + + if (copy_from_user(audio_pseudoburst , (void __user *)arg, + sizeof(struct audioio_pseudoburst_ctrl_t))) + return -EFAULT; + + retval = ste_audio_io_core_api_pseudoburst_control(audio_pseudoburst); + + return retval; + + return 0; + +} +static int process_audiocodec_pwr_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + union audioio_cmd_data_t cmd_data; + struct audioio_acodec_pwr_ctrl_t *audio_acodec_pwr_ctrl; + audio_acodec_pwr_ctrl = (struct audioio_acodec_pwr_ctrl_t *)&cmd_data; + if (copy_from_user(audio_acodec_pwr_ctrl, (void __user *)arg, + sizeof(struct audioio_acodec_pwr_ctrl_t))) + return -EFAULT; + retval = ste_audio_io_core_api_acodec_power_control( + audio_acodec_pwr_ctrl); + return retval; +} + +static int process_fir_coeffs_ctrl_cmd(unsigned int cmd, unsigned long arg) +{ + int retval; + struct audioio_fir_coefficients_t *cmd_data; + cmd_data = kmalloc(sizeof(struct audioio_fir_coefficients_t), + GFP_KERNEL); + if (!cmd_data) + return -ENOMEM; + if (copy_from_user(cmd_data, (void __user *)arg, + sizeof(struct audioio_fir_coefficients_t))) { + kfree(cmd_data); + return -EFAULT; + } + retval = ste_audio_io_core_api_fir_coeffs_control(cmd_data); + kfree(cmd_data); + return retval; +} + +static int ste_audio_io_cmd_parser(unsigned int cmd, unsigned long arg) +{ + int retval = 0; + + switch (cmd) { + case AUDIOIO_READ_REGISTER: + retval = process_read_register_cmd(cmd, arg); + break; + + case AUDIOIO_WRITE_REGISTER: + retval = process_write_register_cmd(cmd, arg); + break; + + case AUDIOIO_PWR_CTRL_TRNSDR: + retval = process_pwr_ctrl_cmd(cmd, arg); + break; + + case AUDIOIO_PWR_STS_TRNSDR: + retval = process_pwr_sts_cmd(cmd, arg); + break; + + case AUDIOIO_LOOP_CTRL: + retval = process_lp_ctrl_cmd(cmd, arg); + break; + + case AUDIOIO_LOOP_STS: + retval = process_lp_sts_cmd(cmd, arg); + break; + + case AUDIOIO_GET_TRNSDR_GAIN_CAPABILITY: + retval = process_get_trnsdr_gain_capability_cmd(cmd, arg); + break; + + case AUDIOIO_GAIN_CAP_LOOP: + retval = process_gain_cap_loop_cmd(cmd, arg); + break; + + case AUDIOIO_SUPPORT_LOOP: + retval = process_support_loop_cmd(cmd, arg); + break; + + case AUDIOIO_GAIN_DESC_TRNSDR: + retval = process_gain_desc_trnsdr_cmd(cmd, arg); + break; + + case AUDIOIO_GAIN_CTRL_TRNSDR: + retval = process_gain_ctrl_trnsdr_cmd(cmd, arg); + break; + + case AUDIOIO_GAIN_QUERY_TRNSDR: + retval = process_gain_query_trnsdr_cmd(cmd, arg); + break; + + case AUDIOIO_MUTE_CTRL_TRNSDR: + retval = process_mute_ctrl_cmd(cmd, arg); + break; + + case AUDIOIO_MUTE_STS_TRNSDR: + retval = process_mute_sts_cmd(cmd, arg); + break; + + case AUDIOIO_FADE_CTRL: + retval = process_fade_cmd(cmd, arg); + break; + + case AUDIOIO_BURST_CTRL: + retval = process_burst_ctrl_cmd(cmd, arg); + break; + + case AUDIOIO_FSBITCLK_CTRL: + retval = process_fsbitclk_ctrl_cmd(cmd, arg); + break; + + case AUDIOIO_PSEUDOBURST_CTRL: + retval = process_pseudoburst_ctrl_cmd(cmd, arg); + break; + + case AUDIOIO_AUDIOCODEC_PWR_CTRL: + retval = process_audiocodec_pwr_ctrl_cmd(cmd, arg); + break; + + case AUDIOIO_FIR_COEFFS_CTRL: + retval = process_fir_coeffs_ctrl_cmd(cmd, arg); + break; + } + return retval; +} + +static int ste_audio_io_open(struct inode *inode, struct file *filp) +{ + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + return 0; +} + +static int ste_audio_io_release(struct inode *inode, struct file *filp) +{ + module_put(THIS_MODULE); + return 0; +} + +static ssize_t ste_audio_io_write(struct file *filp, + const char __user *buf, size_t count, loff_t *f_pos) +{ + char *x = kmalloc(count, GFP_KERNEL); + int debug_flag = 0; + + if (copy_from_user(x, buf, count)) + return -EFAULT; + + if (count >= strlen(STR_DEBUG_ON)) { + + if (!strncmp(STR_DEBUG_ON, x, strlen(STR_DEBUG_ON))) + debug_flag = 1; + else + debug_flag = 0; + } + + ste_audio_io_core_debug(debug_flag); + + kfree(x); + + return count; +} + +static const struct file_operations ste_audio_io_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = ste_audio_io_ioctl, + .open = ste_audio_io_open, + .release = ste_audio_io_release, + .write = ste_audio_io_write, +}; + +/** + * audio_io_misc_dev - Misc device config for audio_io + */ +static struct miscdevice audio_io_misc_dev = { + MISC_DYNAMIC_MINOR, + "audioio", + &ste_audio_io_fops +}; + +/** + * ste_audio_io_probe() - probe the device + * @pdev: pointer to the platform device structure + * + * This funtion is called after the driver is registered to platform + * device framework. It does allocate the memory for the internal + * data structure and intialized core APIs. + */ +static int ste_audio_io_drv_probe(struct platform_device *pdev) +{ + int error; + + ste_audio_io_device = pdev; + + dev_dbg(&ste_audio_io_device->dev, "ste_audio_io device probe\n"); + + error = misc_register(&audio_io_misc_dev); + if (error) { + printk(KERN_WARNING "%s: registering misc device failed\n", + __func__); + return error; + } + + error = ste_audio_io_core_api_init_data(ste_audio_io_device); + if (error < 0) { + dev_err(&ste_audio_io_device->dev, + "ste_audioio_core_api_init_data failed err = %d", + error); + goto ste_audio_io_misc_deregister; + } + return 0; + +ste_audio_io_misc_deregister: + misc_deregister(&audio_io_misc_dev); + return error; +} + +/** + * ste_audio_io_remove() - Removes the device + * @pdev: pointer to the platform_device structure + * + * This function is called when this mnodule is removed using rmmod + */ +static int ste_audio_io_drv_remove(struct platform_device *pdev) +{ + ste_audio_io_core_api_free_data(); + misc_deregister(&audio_io_misc_dev); + return 0; +} + +/** + * ste_audio_io_drv_suspend - suspend audio_io + * @pdev: platform data + * @state: power down level + */ +static int ste_audio_io_drv_suspend(struct platform_device *pdev, + pm_message_t state) +{ + if (ste_audio_io_core_is_ready_for_suspend()) + return 0; + else + return -EINVAL; +} + +/** + * ste_audio_io_drv_resume - put back audio_io in the normal state + * @pdev: platform data + */ +static int ste_audio_io_drv_resume(struct platform_device *pdev) +{ + return 0; +} + +/** + * struct audio_io_driver: audio_io platform structure + * @probe: The probe funtion to be called + * @remove: The remove funtion to be called + * @resume: The resume function to be called + * @suspend: The suspend function to be called + * @driver: The driver data + */ +static struct platform_driver ste_audio_io_driver = { + .probe = ste_audio_io_drv_probe, + .remove = ste_audio_io_drv_remove, + .driver = { + .name = AUDIOIO_DEVNAME, + .owner = THIS_MODULE, + }, + .suspend = ste_audio_io_drv_suspend, + .resume = ste_audio_io_drv_resume, +}; + +/** Pointer to platform device needed to access abx500 core functions */ +struct platform_device *ste_audio_io_device; + +static int __init ste_audio_io_init(void) +{ + return platform_driver_register(&ste_audio_io_driver); +} +module_init(ste_audio_io_init); + +static void __exit ste_audio_io_exit(void) +{ + platform_driver_unregister(&ste_audio_io_driver); +} +module_exit(ste_audio_io_exit); + +MODULE_AUTHOR("Deepak KARDA "); +MODULE_DESCRIPTION("STE_AUDIO_IO"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/audio_io_dev/ste_audio_io_dev.h b/drivers/misc/audio_io_dev/ste_audio_io_dev.h new file mode 100644 index 00000000000..bcb9dce3ad2 --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_dev.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#ifndef _AUDIOIO_DEV_H_ +#define _AUDIOIO_DEV_H_ + +#include +#include "ste_audio_io_core.h" + +union audioio_cmd_data_t { + struct audioio_burst_ctrl_t audioio_burst_ctrl; + struct audioio_fade_ctrl_t audioio_fade_ctrl; + struct audioio_mute_trnsdr_t audioio_mute_trnsdr; + struct audioio_gain_ctrl_trnsdr_t audioio_gain_ctrl_trnsdr; + struct audioio_gain_desc_trnsdr_t audioio_gain_desc_trnsdr; + struct audioio_support_loop_t audioio_support_loop; + struct audioio_gain_loop_t audioio_gain_loop; + struct audioio_get_gain_t audioio_get_gain; + struct audioio_loop_ctrl_t audioio_loop_ctrl; + struct audioio_pwr_ctrl_t audioio_pwr_ctrl; + struct audioio_data_t audioio_data; + struct audioio_fsbitclk_ctrl_t audioio_fsbitclk_ctrl; + struct audioio_acodec_pwr_ctrl_t audioio_acodec_pwr_ctrl; + struct audioio_pseudoburst_ctrl_t audioio_pseudoburst_ctrl; +}; + + +#endif /* _AUDIOIO_DEV_H_ */ + diff --git a/drivers/misc/audio_io_dev/ste_audio_io_func.c b/drivers/misc/audio_io_dev/ste_audio_io_func.c new file mode 100644 index 00000000000..7238085938e --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_func.c @@ -0,0 +1,4371 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "ste_audio_io_func.h" +#include "ste_audio_io_core.h" +#include "ste_audio_io_ab8500_reg_defs.h" +#include "ste_audio_io_hwctrl_common.h" + +static struct clk *clk_ptr_msp0; +static int bluetooth_power_up_count; +static int acodec_reg_dump; + +#define NCP_TIMEOUT 200 /* 200 ms */ +/* + * TODO: Use proper register defines instead of home-made generic ones. + */ +#define SHIFT_QUARTET0 0 +#define SHIFT_QUARTET1 4 +#define MASK_QUARTET (0xFUL) +#define MASK_QUARTET1 (MASK_QUARTET << SHIFT_QUARTET1) +#define MASK_QUARTET0 (MASK_QUARTET << SHIFT_QUARTET0) + +/** + * @brief Modify the specified register + * @reg Register + * @mask_set Bit to be set + * @mask_clear Bit to be cleared + * @return 0 on success otherwise negative error code + */ + +unsigned int ab8500_acodec_modify_write(unsigned int reg, u8 mask_set, + u8 mask_clear) +{ + u8 value8, retval = 0; + value8 = HW_REG_READ(reg); + /* clear the specified bit */ + value8 &= ~mask_clear; + /* set the asked bit */ + value8 |= mask_set; + retval = HW_REG_WRITE(reg, value8); + return retval; +} + +/** + * @brief Power up headset on a specific channel + * @channel_index Channel-index of headset + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_up_headset(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + unsigned long end_time; + + /* Check if HS PowerUp request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "HS should have mono or stereo channels"); + return -EINVAL; + } + + ste_audio_io_mute_headset(channel_index, dev); + + error = HW_ACODEC_MODIFY_WRITE(NCP_ENABLE_HS_AUTOSTART_REG, + HS_AUTO_EN, 0); + if (0 != error) { + dev_err(dev, "NCP fully controlled with EnCpHs bit %d", error); + return error; + } + error = HW_ACODEC_MODIFY_WRITE(NCP_ENABLE_HS_AUTOSTART_REG, + (EN_NEG_CP|HS_AUTO_EN), 0); + if (0 != error) { + dev_err(dev, "Enable Negative Charge Pump %d", error); + return error; + } + + /* Wait for negative charge pump to start */ + end_time = jiffies + msecs_to_jiffies(NCP_TIMEOUT); + while (!(HW_REG_READ(IRQ_STATUS_MSB_REG) & NCP_READY_MASK) + && time_after_eq(end_time, jiffies)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + + if (!(HW_REG_READ(IRQ_STATUS_MSB_REG) & NCP_READY_MASK)) { + error = -EFAULT; + dev_err(dev, "Negative Charge Pump start error % d", error); + return error; + } + + /* Enable DA1 for HSL */ + if (channel_index & e_CHANNEL_1) { + + /* Power Up HSL driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + EN_HSL_MASK, 0); + if (0 != error) { + dev_err(dev, "Power Up HSL Driver %d", error); + return error; + } + + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + if (EN_DA1 & initialVal_DA) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA1_REG, + SLOT08_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA1 from Slot 08 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, + DA1_TO_HSL, 0); + if (0 != error) { + dev_err(dev, + "DA_IN1 path mixed with sidetone FIR %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + EN_DA1, 0); + if (0 != error) { + dev_err(dev, "Power up HSL %d ", error); + return error; + } + + /* Power Up HSL DAC driver */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, + POWER_UP_HSL_DAC, 0); + if (0 != error) { + dev_err(dev, "Power Up HSL DAC driver %d", error); + return error; + } + + /* Power up HSL DAC and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, + EN_HSL_MASK, 0); + if (0 != error) { + dev_err(dev, + "Power up HSL DAC and digital path %d", + error); + return error; + } + + /* + * Disable short detection. Pull Down output to ground, + * Use local oscillator, Gain change without zero cross control + */ + error = HW_ACODEC_MODIFY_WRITE(SHORT_CIRCUIT_DISABLE_REG, + HS_SHORT_DIS|HS_PULL_DOWN_EN|HS_OSC_EN|HS_ZCD_DIS, 0); + if (0 != error) { + dev_err(dev, "Disable short detection." + "Pull Down output to ground,Use local oscillator,Gain" + "change without zero cross control %d", error); + return error; + } + } + + /* Enable DA2 for HSR */ + if (channel_index & e_CHANNEL_2) { + + /* Power Up HSR driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + EN_HSR_MASK, 0); + if (0 != error) { + dev_err(dev, "Power Up HSR Driver %d", error); + return error; + } + + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (EN_DA2 & initialVal_DA) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA2_REG, + SLOT09_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, + "Data sent to DA2 from Slot 09 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, DA2_TO_HSR, + 0); + if (0 != error) { + dev_err(dev, + "DA_IN2 path mixed with sidetone FIR %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + EN_DA2, 0); + if (0 != error) { + dev_err(dev, "Power up HSR %d ", error); + return error; + } + + /* Power Up HSR DAC driver */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, + POWER_UP_HSR_DAC, 0); + if (0 != error) { + dev_err(dev, "Power Up HSR DAC driver %d", error); + return error; + } + + /* Power up HSR DAC and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, + EN_HSR_MASK, 0); + if (0 != error) { + dev_err(dev, + "Power up HSR DAC and digital path %d", + error); + return error; + } + + /* + * TEST START .havent cleared the bits in power down.Disable short + * detection. Pull Down output to ground, Use local oscillator, + * Gain change without zero cross control + */ + + error = HW_ACODEC_MODIFY_WRITE(SHORT_CIRCUIT_DISABLE_REG, + HS_SHORT_DIS|HS_PULL_DOWN_EN|HS_OSC_EN|HS_ZCD_DIS, 0); + if (0 != error) { + dev_err(dev, "Disable short detection." + "Pull Down output to ground, Use local oscillator," + "Gain change without zero cross control %d", error); + return error; + } + /* TEST END */ + } + ste_audio_io_unmute_headset(channel_index, 0, dev); + dump_acodec_registers(__func__, dev); + return error; +} + +/** + * @brief Power down headset on a specific channel + * @channel_index Channel-index of headset + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_down_headset(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + unsigned long end_time; + + /* Check if HS Power Down request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "HS should have mono or stereo channels"); + return -EINVAL; + } + + /* Disable Negative Charge Pump */ + error = HW_ACODEC_MODIFY_WRITE(NCP_ENABLE_HS_AUTOSTART_REG, + (EN_NEG_CP|HS_AUTO_EN), 0); + if (0 != error) { + dev_err(dev, "NCP not fully controlled with EnCpHs bit %d", + error); + return error; + } + error = HW_ACODEC_MODIFY_WRITE(NCP_ENABLE_HS_AUTOSTART_REG, 0, + EN_NEG_CP); + if (0 != error) { + dev_err(dev, "Disable Negative Charge Pump %d", error); + return error; + } + + /* Wait for negative charge pump to stop */ + end_time = jiffies + msecs_to_jiffies(NCP_TIMEOUT); + while ((HW_REG_READ(IRQ_STATUS_MSB_REG) & NCP_READY_MASK) + && time_after_eq(end_time, jiffies)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + + if (HW_REG_READ(IRQ_STATUS_MSB_REG) & NCP_READY_MASK) { + error = -EFAULT; + dev_err(dev, "Negative Charge Pump stop error % d", error); + return error; + } + + if (channel_index & e_CHANNEL_1) { + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (!(initialVal_DA & EN_DA1)) + return 0; + + /* Power Down HSL driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, 0, + EN_HSL_MASK); + if (0 != error) { + dev_err(dev, "Power down HSL Driver %d", error); + return error; + } + + /* Power Down HSL DAC driver */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, + POWER_UP_HSL_DAC); + if (0 != error) { + dev_err(dev, "Power Up HSL DAC Driver %d", error); + return error; + } + + /* Power Down HSL DAC and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, 0, + EN_HSL_MASK); + if (0 != error) { + dev_err(dev, + "Power down HSL DAC and digital path %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + 0, EN_DA1); + if (0 != error) { + dev_err(dev, "Disable DA1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, + 0, DA1_TO_HSL); + if (0 != error) { + dev_err(dev, + "Clear DA_IN1 path mixed with sidetone FIR %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA1_REG, 0, + SLOT08_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Data sent to DA1 cleared from Slot 08 %d", + error); + return error; + } + + + } + /* Enable DA2 for HSR */ + + if (channel_index & e_CHANNEL_2) { + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (!(initialVal_DA & EN_DA2)) + return 0; + + /* Power Down HSR driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, 0, + EN_HSR_MASK); + if (0 != error) { + dev_err(dev, "Power down HSR Driver %d", error); + return error; + } + + /* Power Down HSR DAC driver */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, + POWER_UP_HSR_DAC); + if (0 != error) { + dev_err(dev, "Power down HSR DAC Driver %d", error); + return error; + } + + /* Power Down HSR DAC and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, 0, + EN_HSR_MASK); + if (0 != error) { + dev_err(dev, + "Power down HSR DAC and digital path %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + 0, EN_DA2); + if (0 != error) { + dev_err(dev, "Disable DA2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, 0, + DA2_TO_HSR); + if (0 != error) { + dev_err(dev, + "Clear DA_IN2 path mixed with sidetone FIR %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA2_REG, 0, + SLOT09_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Data sent to DA2 cleared from Slot 09 %d", + error); + return error; + } + + } + dump_acodec_registers(__func__, dev); + return error; +} + +/** + * @brief Mute headset on a specific channel + * @channel_index Headeset channel-index + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_mute_headset(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + /* Check if HS Mute request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "HS should have mono or stereo channels"); + return -EINVAL; + } + + if (channel_index & e_CHANNEL_1) { + /* Mute HSL */ + error = HW_ACODEC_MODIFY_WRITE(MUTE_HS_EAR_REG, + EN_HSL_MASK | EN_HSL_DAC_MASK, + 0); + if (0 != error) { + dev_err(dev, "Mute HSL %d", error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + /* Mute HSR */ + error = HW_ACODEC_MODIFY_WRITE(MUTE_HS_EAR_REG, + EN_HSR_MASK | EN_HSR_DAC_MASK, + 0); + if (0 != error) { + dev_err(dev, "Mute HSR %d", error); + return error; + } + } + + dump_acodec_registers(__func__, dev); + return error; +} + +/** + * @brief Unmute headset on a specific channel + * @channel_index Headeset channel-index + * @gain Gain index of headset + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_unmute_headset(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + + /* Check if HS UnMute request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "HS should have mono or stereo channels"); + return -EINVAL; + } + + if (channel_index & e_CHANNEL_1) { + /* UnMute HSL */ + error = HW_ACODEC_MODIFY_WRITE(MUTE_HS_EAR_REG, 0, + EN_HSL_MASK | EN_HSL_DAC_MASK); + if (0 != error) { + dev_err(dev, "UnMute HSL %d", error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + /* UnMute HSR */ + error = HW_ACODEC_MODIFY_WRITE(MUTE_HS_EAR_REG, 0, + EN_HSR_MASK | EN_HSR_DAC_MASK); + if (0 != error) { + dev_err(dev, "UnMute HSR %d", error); + return error; + } + } + dump_acodec_registers(__func__, dev); + return error; +} + +/** + * @brief Enables fading of headset on a specific channel + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_enable_fade_headset(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(SHORT_CIRCUIT_DISABLE_REG, + 0, DIS_HS_FAD); + if (0 != error) { + dev_err(dev, "Enable fading for HS %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DA1_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for HSL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(HSL_EAR_DIGITAL_GAIN_REG, 0, + DIS_DIG_GAIN_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for Digital Gain of HSL %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DA2_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for HSR %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(HSR_DIGITAL_GAIN_REG, 0, + DIS_DIG_GAIN_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for Digital Gain of HSR %d", + error); + return error; + } + + return error; +} +/** + * @brief Disables fading of headset on a specific channel + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_disable_fade_headset(struct device *dev) +{ + int error = 0; + error = HW_ACODEC_MODIFY_WRITE(SHORT_CIRCUIT_DISABLE_REG, + DIS_HS_FAD, 0); + if (0 != error) { + dev_err(dev, "Disable fading for HS %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DA1_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for HSL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(HSL_EAR_DIGITAL_GAIN_REG, + DIS_DIG_GAIN_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for Digital Gain of HSL %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DA2_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for HSR %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(HSR_DIGITAL_GAIN_REG, + DIS_DIG_GAIN_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for Digital Gain of HSR %d", + error); + return error; + } + return error; +} +/** + * @brief Power up earpiece + * @channel_index Channel-index + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_up_earpiece(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if Earpiece PowerUp request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "EARPIECE should have mono channel"); + return -EINVAL; + } + + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if Earpiece is already powered up or DA1 being used by HS */ + if (EN_DA1 & initialVal_DA) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, + DA1_TO_HSL, 0); + if (0 != error) { + dev_err(dev, + "DA_IN1 path mixed with sidetone FIR %d", error); + return error; + } + + /* Enable DA1 */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA1_REG, + SLOT08_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA1 from Slot 08 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + EN_DA1, 0); + if (0 != error) { + dev_err(dev, "Enable DA1 %d", error); + return error; + } + + /* Power Up EAR class-AB driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + EN_EAR_MASK, 0); + if (0 != error) { + dev_err(dev, "Power Up EAR class-AB driver %d", error); + return error; + } + + /* Power up EAR DAC and digital path */ + error = HW_ACODEC_MODIFY_WRITE( + DIGITAL_OUTPUT_ENABLE_REG, EN_EAR_MASK, 0); + if (0 != error) { + dev_err(dev, "Power up EAR DAC and digital path %d", error); + return error; + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Power down earpiece + * @channel_index Channel-index + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_down_earpiece(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if Earpiece PowerDown request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "EARPIECE should have mono channel"); + return -EINVAL; + } + + /* Check if Earpiece is already powered down or DA1 being used by HS */ + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (!(initialVal_DA & EN_DA1)) + return 0; + + /* Power Down EAR class-AB driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + 0, EN_EAR_MASK); + if (0 != error) { + dev_err(dev, "Power Down EAR class-AB driver %d", error); + return error; + } + + /* Power Down EAR DAC and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, + 0, EN_EAR_MASK); + if (0 != error) { + dev_err(dev, + "Power Down EAR DAC and digital path %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, 0, DA1_TO_HSL); + if (0 != error) { + dev_err(dev, + "Clear DA_IN1 path mixed with sidetone FIR %d", + error); + return error; + } + + /* Disable DA1 */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + 0, EN_DA1); + if (0 != error) { + dev_err(dev, "Disable DA1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA1_REG, 0, + SLOT08_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Data sent to DA1 cleared from Slot 08 %d", error); + return error; + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Mute earpiece + * @channel_index Channel-index + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_mute_earpiece(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + + /* Check if Earpiece Mute request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "EARPIECE should have mono channel"); + return -EINVAL; + } + + /* Mute Earpiece */ + error = HW_ACODEC_MODIFY_WRITE(MUTE_HS_EAR_REG, + EN_EAR_MASK | EN_EAR_DAC_MASK, 0); + if (0 != error) { + dev_err(dev, "Mute Earpiece %d", error); + return error; + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Unmute earpiece + * @channel_index Channel-index + * @gain Gain index of earpiece + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_unmute_earpiece(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + + /* Check if Earpiece UnMute request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "EARPIECE should have mono channel"); + return -EINVAL; + } + + /* UnMute Earpiece */ + error = HW_ACODEC_MODIFY_WRITE(MUTE_HS_EAR_REG, 0, + EN_EAR_MASK | EN_EAR_DAC_MASK); + if (0 != error) { + dev_err(dev, "UnMute Earpiece %d", error); + return error; + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Enables fading of earpiece + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_enable_fade_earpiece(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(DA1_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for Ear %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(HSL_EAR_DIGITAL_GAIN_REG, 0, + DIS_DIG_GAIN_FADING); + if (0 != error) { + dev_err(dev, + "Enable fading for Digital Gain of Ear %d", error); + return error; + } + + return error; +} +/** + * @brief Disables fading of earpiece + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_disable_fade_earpiece(struct device *dev) +{ + int error = 0; + error = HW_ACODEC_MODIFY_WRITE(DA1_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for Ear %d", error); + return error; + } + return error; +} +/** + * @brief Power up IHF on a specific channel + * @channel_index Channel-index + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_up_ihf(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if IHF PowerUp request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "IHF should have mono or stereo channels"); + return -EINVAL; + } + + if (channel_index & e_CHANNEL_1) { + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (EN_DA3 & initialVal_DA) + return 0; + + /* Enable DA3 for IHFL */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA3_REG, + SLOT10_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA3 from Slot 10 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + EN_DA3, 0); + if (0 != error) { + dev_err(dev, "Power up IHFL %d", error); + return error; + } + + /* Power Up HFL Class-D driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + EN_HFL_MASK, 0); + if (0 != error) { + dev_err(dev, "Power Up HFL Class-D Driver %d", error); + return error; + } + + /* Power up HFL Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, + EN_HFL_MASK, 0); + if (0 != error) { + dev_err(dev, + "Power up HFL Class D driver & digital path %d", + error); + return error; + } + } + + /* Enable DA4 for IHFR */ + if (channel_index & e_CHANNEL_2) { + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (EN_DA4 & initialVal_DA) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA4_REG, + SLOT11_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA4 from Slot 11 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + EN_DA4, 0); + if (0 != error) { + dev_err(dev, "Enable DA4 %d", error); + return error; + } + + /* Power Up HFR Class-D driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + EN_HFR_MASK, 0); + if (0 != error) { + dev_err(dev, "Power Up HFR Class-D Driver %d", error); + return error; + } + + /* Power up HFR Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, + EN_HFR_MASK, 0); + if (0 != error) { + dev_err(dev, + "Power up HFR Class D driver and digital path %d", + error); + return error; + } + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Power down IHF on a specific channel + * @channel_index Channel-index + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_down_ihf(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if IHF Power Down request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "IHF should have mono or stereo channels"); + return -EINVAL; + } + + if (channel_index & e_CHANNEL_1) { + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (!(initialVal_DA & EN_DA3)) + return 0; + + /* Power Down HFL Class-D driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, 0, + EN_HFL_MASK); + if (0 != error) { + dev_err(dev, "Power Down HFL Class-D Driver %d", + error); + return error; + } + + /* Power Down HFL Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, 0, + EN_HFL_MASK); + if (0 != error) { + dev_err(dev, + "Power Down HFL Class D driver & digital path %d", + error); + return error; + } + + /* Disable DA3 for IHFL */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + 0, EN_DA3); + if (0 != error) { + dev_err(dev, "Disable DA3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA3_REG, 0, + SLOT10_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Data sent to DA3 cleared from Slot 10 %d", + error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if IHF is already powered Down */ + if (!(initialVal_DA & EN_DA4)) + return 0; + + /* Power Down HFR Class-D Driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, 0, + EN_HFR_MASK); + if (0 != error) { + dev_err(dev, "Power Down HFR Class-D Driver %d", + error); + return error; + } + + /* Power Down HFR Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, 0, + EN_HFR_MASK); + if (0 != error) { + dev_err(dev, + "Power Down HFR Class D driver & digital path %d", + error); + return error; + } + + /* Disable DA4 for IHFR */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + 0, EN_DA4); + if (0 != error) { + dev_err(dev, "Disable DA4 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA4_REG, 0, + SLOT11_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Data sent to DA4 cleared from Slot 11 %d", + error); + return error; + } + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Mute IHF on a specific channel + * @channel_index Channel-index + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_mute_ihf(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + + if ((channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + error = ste_audio_io_set_ihf_gain(channel_index, 0, -63, + 0, dev); + if (0 != error) { + dev_err(dev, "Mute ihf %d", error); + return error; + } + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Unmute IHF on a specific channel + * @channel_index Channel-index + * @gain Gain index of IHF + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_unmute_ihf(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + + if (channel_index & e_CHANNEL_1) { + error = ste_audio_io_set_ihf_gain(channel_index, 0, gain[0], + 0, dev); + if (0 != error) { + dev_err(dev, "UnMute ihf %d", error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + error = ste_audio_io_set_ihf_gain(channel_index, 0, gain[1], + 0, dev); + if (0 != error) { + dev_err(dev, "UnMute ihf %d", error); + return error; + } + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Enable fading of IHF + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_enable_fade_ihf(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(DA3_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for HFL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DA4_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for HFR %d", error); + return error; + } + return error; +} +/** + * @brief Disable fading of IHF + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_disable_fade_ihf(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(DA3_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for HFL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DA4_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for HFR %d", error); + return error; + } + return error; +} +/** + * @brief Power up VIBL + * @channel_index Channel-index of VIBL + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_up_vibl(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if VibL PowerUp request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "VibL should have mono channel"); + return -EINVAL; + } + + /* Try to allocate vibrator for audio left channel */ + error = ste_audioio_vibrator_alloc(STE_AUDIOIO_CLIENT_AUDIO_L, + STE_AUDIOIO_CLIENT_AUDIO_R | STE_AUDIOIO_CLIENT_AUDIO_L); + if (error) { + dev_err(dev, " Couldn't allocate vibrator %d, client %d", + error, STE_AUDIOIO_CLIENT_AUDIO_L); + return error; + } + + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if VibL is already powered up */ + if (initialVal_DA & EN_DA5) + return 0; + + /* Enable DA5 for vibl */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA5_REG, + SLOT12_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA5 from Slot 12 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + EN_DA5, 0); + if (0 != error) { + dev_err(dev, "Enable DA5 for VibL %d", error); + return error; + } + + /* Power Up VibL Class-D driver */ + error = HW_ACODEC_MODIFY_WRITE( + ANALOG_OUTPUT_ENABLE_REG, EN_VIBL_MASK, 0); + if (0 != error) { + dev_err(dev, "Power Up VibL Class-D Driver %d", error); + return error; + } + + /* Power up VibL Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, + EN_VIBL_MASK, 0); + if (0 != error) { + dev_err(dev, + "Power up VibL Class D driver and digital path %d", + error); + return error; + } + return error; +} +/** + * @brief Power down VIBL + * @channel_index Channel-index of VIBL + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_down_vibl(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if VibL Power Down request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "VibL should have mono channel"); + return -EINVAL; + } + + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if VibL is already powered down */ + if (!(initialVal_DA & EN_DA5)) + return 0; + + + /* Power Down VibL Class-D driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, + 0, EN_VIBL_MASK); + if (0 != error) { + dev_err(dev, "Power Down VibL Class-D Driver %d", error); + return error; + } + + /* Power Down VibL Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, 0, + EN_VIBL_MASK); + if (0 != error) { + dev_err(dev, + "Power Down VibL Class D driver & digital path %d", + error); + return error; + } + + /* Disable DA5 for VibL */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + 0, EN_DA5); + if (0 != error) { + dev_err(dev, "Disable DA5 for VibL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA5_REG, 0, + SLOT12_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Data sent to DA5 cleared from Slot 12 %d", error); + return error; + } + + /* Release vibrator */ + ste_audioio_vibrator_release(STE_AUDIOIO_CLIENT_AUDIO_L); + + return error; +} +/** + * @brief Enable fading of VIBL + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_enable_fade_vibl(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(DA5_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for VibL %d", error); + return error; + } + return error; +} +/** + * @brief Disable fading of VIBL + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_disable_fade_vibl(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(DA5_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for VibL %d", error); + return error; + } + return error; +} +/** + * @brief Power up VIBR + * @channel_index Channel-index of VIBR + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_up_vibr(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if VibR PowerUp request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "VibR should have mono channel"); + return -EINVAL; + } + + /* Try to allocate vibrator for audio right channel */ + error = ste_audioio_vibrator_alloc(STE_AUDIOIO_CLIENT_AUDIO_R, + STE_AUDIOIO_CLIENT_AUDIO_R | STE_AUDIOIO_CLIENT_AUDIO_L); + if (error) { + dev_err(dev, " Couldn't allocate vibrator %d, client %d", + error, STE_AUDIOIO_CLIENT_AUDIO_R); + return error; + } + + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if VibR is already powered up */ + if (initialVal_DA & EN_DA6) + return 0; + + /* Enable DA6 for vibr */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA6_REG, + SLOT13_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA5 from Slot 13 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE( + DIGITAL_DA_CHANNELS_ENABLE_REG, EN_DA6, 0); + if (0 != error) { + dev_err(dev, "Enable DA6 for VibR %d", error); + return error; + } + + /* Power Up VibR Class-D driver */ + error = HW_ACODEC_MODIFY_WRITE( + ANALOG_OUTPUT_ENABLE_REG, EN_VIBR_MASK, 0); + if (0 != error) { + dev_err(dev, "Power Up VibR Class-D Driver %d", error); + return error; + } + + /* Power up VibR Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, + EN_VIBR_MASK, 0); + if (0 != error) { + dev_err(dev, + "Power up VibR Class D driver & digital path %d", + error); + return error; + } + return error; +} +/** + * @brief Power down VIBR + * @channel_index Channel-index of VIBR + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_down_vibr(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_DA = 0; + + /* Check if VibR PowerDown request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "VibR should have mono channel"); + return -EINVAL; + } + + initialVal_DA = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if VibR is already powered down */ + if (!(initialVal_DA & EN_DA6)) + return 0; + + + /* Power Down VibR Class-D driver */ + error = HW_ACODEC_MODIFY_WRITE(ANALOG_OUTPUT_ENABLE_REG, 0, + EN_VIBR_MASK); + if (0 != error) { + dev_err(dev, "Power Down VibR Class-D Driver %d", error); + return error; + } + + /* Power Down VibR Class D driver and digital path */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_OUTPUT_ENABLE_REG, 0, + EN_VIBR_MASK); + if (0 != error) { + dev_err(dev, + "Power Down VibR Class D driver & digital path %d", + error); + return error; + } + + /* Disable DA6 for VibR */ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_DA_CHANNELS_ENABLE_REG, + 0, EN_DA6); + if (0 != error) { + dev_err(dev, "Disable DA6 for VibR %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA6_REG, 0, + SLOT13_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, "Data sent to DA5 cleared from Slot 13 %d", + error); + return error; + } + + /* Release vibrator */ + ste_audioio_vibrator_release(STE_AUDIOIO_CLIENT_AUDIO_R); + + return error; +} +/** + * @brief Enable fading of VIBR + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_enable_fade_vibr(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(DA6_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for VibR %d", error); + return error; + } + return error; +} +/** + * @brief Disable fading of VIBR + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_disable_fade_vibr(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(DA6_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for VibR %d", error); + return error; + } + return error; +} +/** + * @brief Power up MIC1A + * @channel_index Channel-index of MIC1A + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_up_mic1a(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if Mic1 PowerUp request is mono channel */ + + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "MIC1 should have mono channel"); + return -EINVAL; + } + + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + /* Check if Mic1 is already powered up or used by Dmic3 */ + if (EN_AD3 & initialVal_AD) + return 0; + + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, DATA_FROM_AD_OUT3); + if (0 != error) { + dev_err(dev, "Slot 02 outputs data from AD_OUT3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + EN_AD3, 0); + if (0 != error) { + dev_err(dev, "Enable AD3 for Mic1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, 0, + SEL_DMIC3_FOR_AD_OUT3); + if (0 != error) { + dev_err(dev, "Select ADC1 for AD_OUT3 %d", error); + return error; + } + + /* Select MIC1A */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, + SEL_MIC1B_CLR_MIC1A); + if (0 != error) { + dev_err(dev, "Select MIC1A %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, EN_MIC1, 0); + if (0 != error) { + dev_err(dev, "Power up Mic1 %d", error); + return error; + } + + /* Power Up ADC1 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, POWER_UP_ADC1, 0); + if (0 != error) { + dev_err(dev, "Power Up ADC1 %d", error); + return error; + } + +return error; +} +/** + * @brief Power down MIC1A + * @channel_index Channel-index of MIC1A + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_down_mic1a(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if Mic1 PowerDown request is mono channel */ + + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic1 should have mono channel"); + return -EINVAL; + } + + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + /* Check if Mic1 is already powered down or used by Dmic3 */ + if (!(initialVal_AD & EN_AD3)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, EN_MIC1); + if (0 != error) { + dev_err(dev, "Power Down Mic1 %d", error); + return error; + } + + /* Power Down ADC1 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, POWER_UP_ADC1); + if (0 != error) { + dev_err(dev, "Power Down ADC1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, EN_AD3); + if (0 != error) { + dev_err(dev, "Disable AD3 for Mic1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT2_3_REG, 0, + DATA_FROM_AD_OUT3); + if (0 != error) { + dev_err(dev, "Slot 02 outputs data cleared from AD_OUT3 %d", + error); + return error; + } + return error; +} +/** + * @brief Mute MIC1A + * @channel_index Channel-index of MIC1A + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_mute_mic1a(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "MIC1 should have mono channel"); + return -EINVAL; + } + + /* Mute mic1 */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, MUT_MIC1, 0); + if (0 != error) { + dev_err(dev, "Mute Mic1 %d", error); + return error; + } + return error; +} +/** + * @brief Unmute MIC1A + * @channel_index Channel-index of MIC1A + * @gain Gain index of MIC1A + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_unmute_mic1a(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic1 should have mono channel"); + return -EINVAL; + } + /* UnMute mic1 */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, MUT_MIC1); + if (0 != error) { + dev_err(dev, "UnMute Mic1 %d", error); + return error; + } + return error; +} +/** + * @brief Enable fading of MIC1A + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_enable_fade_mic1a(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(AD3_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for Mic1 %d", error); + return error; + } + return error; +} +/** + * @brief Disable fading of MIC1A + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_disable_fade_mic1a(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(AD3_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for Mic1 %d", error); + return error; + } + return error; +} +/** + * @brief Power up MIC1B + * @channel_index Channel-index of MIC1B + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_up_mic1b(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error; + unsigned char initialVal_AD = 0; + + error = regulator_enable(regulator_avsource); + if (0 != error) { + dev_err(dev, "regulator avsource enable failed = %d", error); + return error; + } + /* GPIO35 settings to enable MIC 1B input instead of TVOUT */ + error = HW_ACODEC_MODIFY_WRITE(AB8500_GPIO_DIR5_REG, + GPIO35_DIR_OUTPUT, 0); + if (0 != error) { + dev_err(dev, "setting AB8500_GPIO_DIR5_REG reg %d", error); + return error; + } + error = HW_ACODEC_MODIFY_WRITE(AB8500_GPIO_OUT5_REG, + GPIO35_DIR_OUTPUT, 0); + if (0 != error) { + dev_err(dev, "setting AB8500_GPIO_OUT5_REG reg %d", error); + return error; + } + + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic1 should have mono channel"); + return -EINVAL; + } + + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + /* Check if Mic1 is already powered up or used by Dmic3 */ + if (EN_AD3 & initialVal_AD) + return 0; + + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, DATA_FROM_AD_OUT3); + if (0 != error) { + dev_err(dev, "Slot 02 outputs data from AD_OUT3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + EN_AD3, 0); + if (0 != error) { + dev_err(dev, "Enable AD3 for Mic1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, 0, + SEL_DMIC3_FOR_AD_OUT3); + if (0 != error) { + dev_err(dev, "Select ADC1 for AD_OUT3 %d", error); + return error; + } + + /* Select MIC1B */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, SEL_MIC1B_CLR_MIC1A, + 0); + if (0 != error) { + dev_err(dev, "Select MIC1B %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, EN_MIC1, 0); + if (0 != error) { + dev_err(dev, "Power up Mic1 %d", error); + return error; + } + + /* Power Up ADC1 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, POWER_UP_ADC1, 0); + if (0 != error) { + dev_err(dev, "Power Up ADC1 %d", error); + return error; + } + return error; +} +/** + * @brief Power down MIC1B + * @channel_index Channel-index of MIC1B + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_down_mic1b(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error; + unsigned char initialVal_AD = 0; + + /* Check if Mic1 PowerDown request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic1 should have mono channel"); + return -EINVAL; + } + + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if Mic1 is already powered down or used by Dmic3 */ + if (!(initialVal_AD & EN_AD3)) + return 0; + + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, EN_MIC1); + if (0 != error) { + dev_err(dev, "Power Down Mic1 %d", error); + return error; + } + + /* Power Down ADC1 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, POWER_UP_ADC1); + if (0 != error) { + dev_err(dev, "Power Down ADC1 %d", error); + return error; + } + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, 0, + EN_AD3); + if (0 != error) { + dev_err(dev, "Disable AD3 for Mic1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT2_3_REG, 0, + DATA_FROM_AD_OUT3); + if (0 != error) { + dev_err(dev, "Slot 02 outputs data cleared from AD_OUT3 %d", + error); + return error; + } + + /* undo GPIO35 settings */ + error = HW_ACODEC_MODIFY_WRITE(AB8500_GPIO_DIR5_REG, + 0, GPIO35_DIR_OUTPUT); + if (0 != error) { + dev_err(dev, "resetting AB8500_GPIO_DIR5_REG reg %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AB8500_GPIO_OUT5_REG, + 0, GPIO35_DIR_OUTPUT); + if (0 != error) { + dev_err(dev, "resetting AB8500_GPIO_OUT5_REG reg %d", error); + return error; + } + + error = regulator_disable(regulator_avsource); + if (0 != error) { + dev_err(dev, "regulator avsource disable failed = %d", error); + return error; + } + dump_acodec_registers(__func__, dev); + return error; +} + +/** + * @brief enable hardware loop of mic1b + * @chnl_index Channel-index of MIC1B + * @hw_loop type of hardware loop + * @loop_gain gain value to be used in hardware loop + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_enable_loop_mic1b(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS hw_loop, + int loop_gain, struct device *dev, + void *cookie) +{ + int error; + struct transducer_context_t *trnsdr; + trnsdr = (struct transducer_context_t *)cookie; + + switch (hw_loop) { + /* Check if HSL is active */ + case AUDIOIO_SIDETONE_LOOP: + if (!(trnsdr[HS_CH].is_power_up[e_CHANNEL_1]) + && !(trnsdr[EAR_CH].is_power_up[e_CHANNEL_1])) { + error = -EFAULT; + dev_err(dev, + "HS or Earpiece not powered up error = %d", + error); + return error; + } + + /* For ch1, Power On STFIR1, data comes from AD3*/ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG2, + FIR1_FROMAD3, 0); + if (error) + dev_err(dev, "FIR1 data comes from AD_OUT3 %d", + error); + error = HW_REG_WRITE(SIDETONE_FIR1_GAIN_REG, loop_gain); + if (error) { + dev_err(dev, + "Set FIR1 Gain index = %d", + error); + return error; + } + break; + default: + error = -EINVAL; + dev_err(dev, "loop not supported %d", error); + } + return error; +} + +/** + * @brief disable hardware loop of mic1b + * @chnl_index Channel-index of MIC1B + * @hw_loop type of hardware loop + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_disable_loop_mic1b(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS hw_loop, + struct device *dev, void *cookie) +{ + int error; + struct transducer_context_t *trnsdr; + trnsdr = (struct transducer_context_t *)cookie; + + switch (hw_loop) { + /* Check if HSL is active */ + case AUDIOIO_SIDETONE_LOOP: + if (!trnsdr[HS_CH].is_power_up[e_CHANNEL_1] + && !trnsdr[EAR_CH].is_power_up[e_CHANNEL_1]) { + error = -EFAULT; + dev_err(dev, "HS or Earpiece not powered up, err = %d", + error); + return error; + } + + /* For ch1, Power down STFIR1, data comes from AD3*/ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG2, + 0, FIR1_FROMAD3); + if (error) { + dev_err(dev, "FIR1 data comes from AD_OUT3, err = %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(FILTERS_CONTROL_REG, + 0, FIR_FILTERCONTROL); + if (error) { + dev_err(dev, + "ST FIR Filters disable failed %d", error); + return error; + } + break; + default: + error = -EINVAL; + dev_err(dev, "loop not supported %d", error); + } + return error; +} + +/** + * @brief Power up MIC2 + * @channel_index Channel-index of MIC2 + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_up_mic2(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if Mic2 PowerUp request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic2 should have mono channel"); + return -EINVAL; + } + + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if Mic2 is already powered up or used by LINR or Dmic2 */ + if (EN_AD2 & initialVal_AD) + return 0; + + + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, DATA_FROM_AD_OUT2); + if (0 != error) { + dev_err(dev, "Slot 01 outputs data from AD_OUT2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, EN_AD2, + 0); + if (0 != error) { + dev_err(dev, "Enable AD2 for Mic2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, 0, + SEL_DMIC2_FOR_AD_OUT2); + if (0 != error) { + dev_err(dev, "Select ADC2 for AD_OUT2 %d", error); + return error; + } + + /* Select mic2 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, + SEL_LINR_CLR_MIC2); + if (0 != error) { + dev_err(dev, "Select MIC2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, EN_MIC2, 0); + if (0 != error) { + dev_err(dev, "Power up Mic2 %d", error); + return error; + } + + /* Power Up ADC1 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, POWER_UP_ADC2, 0); + if (0 != error) { + dev_err(dev, "Power Up ADC2 %d", error); + return error; + } + return error; +} +/** + * @brief Power down MIC2 + * @channel_index Channel-index of MIC2 + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_power_down_mic2(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if Mic2 PowerDown request is mono channel */ + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic2 should have mono channel"); + return -EINVAL; + } + + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + + /* Check if Mic2 is already powered down or used by LINR or Dmic2 */ + if (!(initialVal_AD & EN_AD2)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, EN_MIC2); + if (0 != error) { + dev_err(dev, "Power Down Mic2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, EN_AD2); + if (0 != error) { + dev_err(dev, "Disable AD2 for Mic2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, 0, + (DATA_FROM_AD_OUT2<<4)); + if (0 != error) { + dev_err(dev, "Slot 01 outputs data cleared from AD_OUT2 %d", + error); + return error; + } + return error; +} +/** + * @brief Mute MIC2 + * @channel_index Channel-index of MIC2 + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_mute_mic2(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic2 should have mono channel"); + return -EINVAL; + } + + /* Mute mic2 */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, MUT_MIC2, 0); + if (0 != error) { + dev_err(dev, "Mute Mic2 %d", error); + return error; + } + return error; +} +/** + * @brief Unmute MIC2 + * @channel_index Channel-index of MIC2 + * @gain Gain index of MIC2 + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_unmute_mic2(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + if (!(channel_index & e_CHANNEL_1)) { + dev_err(dev, "Mic2 should have mono channel"); + return -EINVAL; + } + /* UnMute mic2 */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, MUT_MIC2); + if (0 != error) { + dev_err(dev, "UnMute Mic2 %d", error); + return error; + } + return error; +} +/** + * @brief Enable fading of MIC2 + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_enable_fade_mic2(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(AD2_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for Mic2 %d", error); + return error; + } + return error; +} +/** + * @brief Disable fading of MIC2 + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_disable_fade_mic2(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(AD2_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for Mic2 %d", error); + return error; + } + + return error; +} +/** + * @brief Power up LinIn + * @channel_index Channel-index of LinIn + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_up_lin(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if LinIn PowerUp request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "LinIn should have mono or stereo channels"); + return -EINVAL; + } + + /* Enable AD1 for LinInL */ + if (channel_index & e_CHANNEL_1) { + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (initialVal_AD & EN_AD1) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, + DATA_FROM_AD_OUT1, 0); + if (0 != error) { + dev_err(dev, "Slot 00 outputs data from AD_OUT1 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + EN_AD1, 0); + if (0 != error) { + dev_err(dev, "Enable AD1 for LinInL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, 0, + SEL_DMIC1_FOR_AD_OUT1); + if (0 != error) { + dev_err(dev, "Select ADC3 for AD_OUT1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE( + LINE_IN_MIC_CONF_REG, EN_LIN_IN_L, 0); + if (0 != error) { + dev_err(dev, "Power up LinInL %d", error); + return error; + } + + /* Power Up ADC3 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, + POWER_UP_ADC3, 0); + if (0 != error) { + dev_err(dev, "Power Up ADC3 %d", error); + return error; + } + } + /* Enable AD2 for LinInR */ + + if (channel_index & e_CHANNEL_2) { + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (EN_AD2 & initialVal_AD) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, + (DATA_FROM_AD_OUT2<<4), 0); + if (0 != error) { + dev_err(dev, "Slot 01 outputs data from AD_OUT2 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + EN_AD2, 0); + if (0 != error) { + dev_err(dev, "Enable AD2 LinInR %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, 0, + SEL_DMIC2_FOR_AD_OUT2); + if (0 != error) { + dev_err(dev, "Select ADC2 for AD_OUT2 %d", error); + return error; + } + + /* Select LinInR */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, + SEL_LINR_CLR_MIC2, 0); + if (0 != error) { + dev_err(dev, "Select LinInR %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, + EN_LIN_IN_R, 0); + if (0 != error) { + dev_err(dev, "Power up LinInR %d", error); + return error; + } + + /* Power Up ADC2 */ + error = HW_ACODEC_MODIFY_WRITE( + ADC_DAC_ENABLE_REG, POWER_UP_ADC2, 0); + if (0 != error) { + dev_err(dev, "Power Up ADC2 %d", error); + return error; + } + } + return error; +} +/** + * @brief Power down LinIn + * @channel_index Channel-index of LinIn + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_down_lin(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if LinIn PowerDown request is mono or Stereo channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "LinIn should have mono or stereo channels"); + return -EINVAL; + } + + /* Enable AD1 for LinInL */ + if (channel_index & e_CHANNEL_1) { + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (!(initialVal_AD & EN_AD1)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, + EN_LIN_IN_L); + if (0 != error) { + dev_err(dev, "Power Down LinInL %d", error); + return error; + } + + /* Power Down ADC3 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, + POWER_UP_ADC3); + if (0 != error) { + dev_err(dev, "Power Down ADC3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, EN_AD1); + if (0 != error) { + dev_err(dev, "Disable AD1 for LinInL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, 0, + DATA_FROM_AD_OUT1); + if (0 != error) { + dev_err(dev, + "Slot 00 outputs data cleared from AD_OUT1 %d", + error); + return error; + } + } + + /* Enable AD2 for LinInR */ + if (channel_index & e_CHANNEL_2) { + initialVal_AD = HW_REG_READ(DIGITAL_DA_CHANNELS_ENABLE_REG); + if (!(initialVal_AD & EN_AD2)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, + EN_LIN_IN_R); + if (0 != error) { + dev_err(dev, "Power Down LinInR %d", error); + return error; + } + + /* Power Down ADC2 */ + error = HW_ACODEC_MODIFY_WRITE(ADC_DAC_ENABLE_REG, 0, + POWER_UP_ADC2); + if (0 != error) { + dev_err(dev, "Power Down ADC2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, EN_AD2); + if (0 != error) { + dev_err(dev, "Disable AD2 LinInR %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, 0, + (DATA_FROM_AD_OUT2<<4)); + if (0 != error) { + dev_err(dev, + "Slot01 outputs data cleared from AD_OUT2 %d", + error); + return error; + } + } + return error; +} +/** + * @brief Mute LinIn + * @channel_index Channel-index of LinIn + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_mute_lin(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "LinIn should have mono or stereo channels"); + return -EINVAL; + } + + if (channel_index & e_CHANNEL_1) { + /* Mute LinInL */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, + MUT_LIN_IN_L, 0); + if (0 != error) { + dev_err(dev, "Mute LinInL %d", error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + /* Mute LinInR */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, + MUT_LIN_IN_R, + 0); + if (0 != error) { + dev_err(dev, "Mute LinInR %d", error); + return error; + } + } + return error; +} +/** + * @brief Unmute LinIn + * @channel_index Channel-index of LinIn + * @gain Gain index of LinIn + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_unmute_lin(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "LinIn should have mono or stereo channels"); + return -EINVAL; + } + + if (channel_index & e_CHANNEL_1) { + /* UnMute LinInL */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, + MUT_LIN_IN_L); + if (0 != error) { + dev_err(dev, "UnMute LinInL %d", error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + /* UnMute LinInR */ + error = HW_ACODEC_MODIFY_WRITE(LINE_IN_MIC_CONF_REG, 0, + MUT_LIN_IN_R); + if (0 != error) { + dev_err(dev, "UnMute LinInR %d", error); + return error; + } + } + return error; +} +/** + * @brief Enables fading of LinIn + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_enable_fade_lin(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(AD1_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for LinInL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD2_DIGITAL_GAIN_REG, 0, DIS_FADING); + if (0 != error) { + dev_err(dev, "Enable fading for LinInR %d", error); + return error; + } + return error; +} +/** + * @brief Disables fading of LinIn + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_disable_fade_lin(struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(AD1_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for LinInL %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD2_DIGITAL_GAIN_REG, DIS_FADING, 0); + if (0 != error) { + dev_err(dev, "Disable fading for LinInR %d", error); + return error; + } + return error; +} +/** + * @brief Power Up DMIC12 LinIn + * @channel_index Channel-index of DMIC12 + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_power_up_dmic12(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if DMic12 request is mono or Stereo */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "DMic12 does not support more than 2 channels"); + + return -EINVAL; + } + + /* Setting Direction for GPIO pins on AB8500 */ + error = HW_REG_WRITE(AB8500_GPIO_DIR4_REG, GPIO27_DIR_OUTPUT); + if (0 != error) { + dev_err(dev, "Setting Direction for GPIO pins on AB8500 %d", + error); + return error; + } + + /* Enable AD1 for Dmic1 */ + if (channel_index & e_CHANNEL_1) { + /* Check if DMIC1 is already powered up or used by LinInL */ + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + if (initialVal_AD & EN_AD1) + return 0; + + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, + DATA_FROM_AD_OUT1); + if (0 != error) { + dev_err(dev, "Slot 00 outputs data from AD_OUT1 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + EN_AD1, 0); + if (0 != error) { + dev_err(dev, "Enable AD1 for DMIC1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, + SEL_DMIC1_FOR_AD_OUT1, 0); + if (0 != error) { + dev_err(dev, "Select DMIC1 for AD_OUT1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, EN_DMIC1, 0); + if (0 != error) { + dev_err(dev, "Enable DMIC1 %d", error); + return error; + } + } + /* Enable AD2 for Dmic2 */ + + if (channel_index & e_CHANNEL_2) { + /* Check if DMIC2 is already powered up + or used by Mic2 or LinInR */ + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + if (initialVal_AD & EN_AD2) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, + (DATA_FROM_AD_OUT2<<4), 0); + if (0 != error) { + dev_err(dev, "Slot 01 outputs data from AD_OUT2 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + EN_AD2, 0); + if (0 != error) { + dev_err(dev, "Enable AD2 for DMIC2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, + SEL_DMIC2_FOR_AD_OUT2, 0); + if (0 != error) { + dev_err(dev, "Select DMIC2 for AD_OUT2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, EN_DMIC2, 0); + if (0 != error) { + dev_err(dev, "Enable DMIC2 %d", error); + return error; + } + } + + return error; +} +/** + * @brief Power down DMIC12 LinIn + * @channel_index Channel-index of DMIC12 + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_power_down_dmic12(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if DMic12 request is mono or Stereo or multi channel */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "DMic12 does not support more than 2 channels"); + + return -EINVAL; + } + + /* Setting Direction for GPIO pins on AB8500 */ + error = HW_ACODEC_MODIFY_WRITE(AB8500_GPIO_DIR4_REG, 0, + GPIO27_DIR_OUTPUT); + if (0 != error) { + dev_err(dev, "Clearing Direction for GPIO pins on AB8500 %d", + error); + return error; + } + /* Enable AD1 for Dmic1 */ + if (channel_index & e_CHANNEL_1) { + /* Check if DMIC1 is already powered Down or used by LinInL */ + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + if (!(initialVal_AD & EN_AD1)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, 0, EN_DMIC1); + if (0 != error) { + dev_err(dev, "Enable DMIC1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, EN_AD1); + if (0 != error) { + dev_err(dev, "Disable AD1 for DMIC1 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, 0, + DATA_FROM_AD_OUT1); + if (0 != error) { + dev_err(dev, + "Slot 00 outputs data cleared from AD_OUT1 %d", + error); + return error; + } + } + + /* Enable AD2 for Dmic2 */ + if (channel_index & e_CHANNEL_2) { + /* MIC2 is already powered Down or used by Mic2 or LinInR */ + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + if (!(initialVal_AD & EN_AD2)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, 0, EN_DMIC2); + if (0 != error) { + dev_err(dev, "Enable DMIC2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, EN_AD2); + if (0 != error) { + dev_err(dev, "Disable AD2 for DMIC2 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT0_1_REG, 0, + (DATA_FROM_AD_OUT2<<4)); + if (0 != error) { + dev_err(dev, + "Slot 01 outputs data cleared from AD_OUT2 %d", + error); + return error; + } + } + return error; +} +/** + * @brief Get headset gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_get_headset_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + int i = 0; + if (gain_index == 0) { + + *left_volume = 0 - HW_REG_READ(DA1_DIGITAL_GAIN_REG); + *right_volume = 0 - HW_REG_READ(DA2_DIGITAL_GAIN_REG); + + } + + if (gain_index == 1) { + *left_volume = 8 - HW_REG_READ(HSL_EAR_DIGITAL_GAIN_REG); + *right_volume = 8 - HW_REG_READ(HSR_DIGITAL_GAIN_REG); + } + + if (gain_index == 2) { + i = (HW_REG_READ(ANALOG_HS_GAIN_REG)>>4); + *left_volume = hs_analog_gain_table[i]; + i = (HW_REG_READ(ANALOG_HS_GAIN_REG) & MASK_QUARTET0); + *right_volume = hs_analog_gain_table[i]; + } + return 0; +} +/** + * @brief Get earpiece gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_get_earpiece_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + if (0 == gain_index) + *left_volume = 0 - HW_REG_READ(DA1_DIGITAL_GAIN_REG); + if (1 == gain_index) + *left_volume = 8 - HW_REG_READ(HSL_EAR_DIGITAL_GAIN_REG); + return 0; +} +/** + * @brief Get ihf gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_get_ihf_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + + *left_volume = 0 - HW_REG_READ(DA3_DIGITAL_GAIN_REG); + *right_volume = 0 - HW_REG_READ(DA4_DIGITAL_GAIN_REG); + return 0; +} +/** + * @brief Get vibl gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_get_vibl_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + + *left_volume = 0 - HW_REG_READ(DA5_DIGITAL_GAIN_REG); + + return 0; +} +/** + * @brief Get vibr gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_get_vibr_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + + *right_volume = 0 - HW_REG_READ(DA6_DIGITAL_GAIN_REG); + return 0; +} +/** + * @brief Get MIC1A & MIC2A gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_get_mic1a_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + if (gain_index == 0) + *left_volume = 31 - HW_REG_READ(AD3_DIGITAL_GAIN_REG); + if (gain_index == 1) + *left_volume = HW_REG_READ(ANALOG_MIC1_GAIN_REG); + + return 0; +} +/** + * @brief Get MIC2 gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_get_mic2_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + if (gain_index == 0) + *left_volume = 31 - HW_REG_READ(AD2_DIGITAL_GAIN_REG); + if (gain_index == 1) + *left_volume = HW_REG_READ(ANALOG_MIC2_GAIN_REG); + + return 0; +} +/** + * @brief Get Lin IN gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_get_lin_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + if (gain_index == 0) { + *left_volume = 31 - HW_REG_READ(AD1_DIGITAL_GAIN_REG); + *right_volume = 31 - HW_REG_READ(AD2_DIGITAL_GAIN_REG); + } + + if (gain_index == 0) { + *left_volume = 2 * ((HW_REG_READ(ANALOG_HS_GAIN_REG)>>4) - 5); + *right_volume = 2 * (HW_REG_READ(ANALOG_LINE_IN_GAIN_REG) - 5); + } + + return 0; +} +/** + * @brief Get DMIC12 gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_get_dmic12_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + + *left_volume = HW_REG_READ(AD1_DIGITAL_GAIN_REG); + + *right_volume = HW_REG_READ(AD2_DIGITAL_GAIN_REG); + + return 0; +} +/** + * @brief Get DMIC34 gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_get_dmic34_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + *left_volume = HW_REG_READ(AD3_DIGITAL_GAIN_REG); + *right_volume = HW_REG_READ(AD4_DIGITAL_GAIN_REG); + + return 0; +} +/** + * @brief Get DMIC56 gain + * @left_volume + * @right_volume + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_get_dmic56_gain(int *left_volume, int *right_volume, + u16 gain_index, struct device *dev) +{ + *left_volume = HW_REG_READ(AD5_DIGITAL_GAIN_REG); + + *right_volume = HW_REG_READ(AD6_DIGITAL_GAIN_REG); + return 0; +} +/** + * @brief Set gain of headset along a specified channel + * @channel_index Channel-index of headset + * @gain_index Gain index of headset + * @gain_value Gain value of headset + * @linear + * @return 0 on success otherwise negative error code + */ + + +int ste_audio_io_set_headset_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + int i = 0; + int acodec_device_id; + + acodec_device_id = abx500_get_chip_id(dev); + + if (channel_index & e_CHANNEL_1) { + if (gain_index == 0) { + int gain = 0; + gain = 0 - gain_value; + + initial_val = HW_REG_READ(DA1_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(DA1_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain HSL gainindex = %d %d", + gain_index, error); + return error; + } + } + + if (gain_index == 1) { + int gain = 0; + gain = 8 - gain_value; + + initial_val = HW_REG_READ(HSL_EAR_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(HSL_EAR_DIGITAL_GAIN_REG, + ((initial_val & (~HS_DIGITAL_GAIN_MASK)) | (gain & + HS_DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain HSL gain index = %d %d", + gain_index, error); + return error; + } + } + + if (gain_index == 2) { + /* Set Analog gain */ + int gain = -1; + + if (gain_value % 2) { + gain_value -= 1; + dev_err(dev, + "Odd Gain received.Fixing it to 2dB step gain_value = %d", + gain_value); + } + /* Fix for 4dB step gains. Select one lower value */ + if (gain_value == -22) + gain_value = -24; + + if (gain_value == -26) + gain_value = -28; + + if (gain_value == -30) + gain_value = -32; + + for (i = 0 ; i < 16; i++) { + if (hs_analog_gain_table[i] == gain_value) { + gain = i<<4; + break; + } + } + if (gain == -1) + return -1; + + if ((AB8500_REV_10 == acodec_device_id) || + (AB8500_REV_11 == acodec_device_id)) { + if (!gain) + gain = 0x10; + gain = 0xF0 - gain; + } + initial_val = HW_REG_READ(ANALOG_HS_GAIN_REG); + + /* Write gain */ + error = HW_REG_WRITE(ANALOG_HS_GAIN_REG, ((initial_val & + (~L_ANALOG_GAIN_MASK)) | (gain & L_ANALOG_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain HSL gain index = %d %d", + gain_index, error); + return error; + } + } + } + + /* for HSR */ + if (channel_index & e_CHANNEL_2) { + /* Set Gain HSR */ + if (gain_index == 0) { + int gain = 0; + gain = 0 - gain_value; + + initial_val = HW_REG_READ(DA2_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(DA2_DIGITAL_GAIN_REG, ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain HSR gain index = %d %d", + gain_index, error); + return error; + } + } + + if (gain_index == 1) { + int gain = 0; + gain = 8 - gain_value; + + initial_val = HW_REG_READ(HSR_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(HSR_DIGITAL_GAIN_REG, ((initial_val + & (~HS_DIGITAL_GAIN_MASK)) | (gain & + HS_DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain HSR gain index = %d %d", + gain_index, error); + return error; + } + + } + + if (gain_index == 2) { + /* Set Analog gain */ + int gain = -1; + + if (gain_value % 2) { + gain_value -= 1; + dev_err(dev, + "Odd Gain received.Fixing it to 2dB step gain_value = %d", + gain_value); + } + /* Fix for 4dB step gains. Select one lower value */ + if (gain_value == -22) + gain_value = -24; + + if (gain_value == -26) + gain_value = -28; + + if (gain_value == -30) + gain_value = -32; + + for (i = 0 ; i < 16 ; i++) { + if (hs_analog_gain_table[i] == gain_value) { + gain = i; + break; + } + } + if (gain == -1) + return -1; + + if ((AB8500_REV_10 == acodec_device_id) || + (AB8500_REV_11 == acodec_device_id)) { + if (!gain) + gain = 1; + gain = 0x0F - gain; + } + initial_val = HW_REG_READ(ANALOG_HS_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(ANALOG_HS_GAIN_REG, ((initial_val & + (~R_ANALOG_GAIN_MASK)) | (gain & R_ANALOG_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain HSR gainindex = %d %d", + gain_index, error); + return error; + } + } + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Set gain of earpiece + * @channel_index Channel-index of earpiece + * @gain_index Gain index of earpiece + * @gain_value Gain value of earpiece + * @linear + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_set_earpiece_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + if (channel_index & e_CHANNEL_1) { + if (0 == gain_index) { + int gain = 0; + gain = 0 - gain_value; + + initial_val = HW_REG_READ(DA1_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(DA1_DIGITAL_GAIN_REG, ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain Ear gainindex = %d %d", + gain_index, error); + return error; + } + } + + if (gain_index == 1) { + int gain = 0; + gain = 8 - gain_value; + + initial_val = HW_REG_READ(HSL_EAR_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(HSL_EAR_DIGITAL_GAIN_REG, + ((initial_val & (~HS_DIGITAL_GAIN_MASK)) | (gain & + HS_DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain Ear gainindex = %d %d", + gain_index, error); + return error; + } + } + } + dump_acodec_registers(__func__, dev); + return error; +} +/** + * @brief Set gain of vibl + * @channel_index Channel-index of vibl + * @gain_index Gain index of vibl + * @gain_value Gain value of vibl + * @linear + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_set_vibl_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + /* Set Gain vibl */ + if (gain_index == 0) { + int gain = 0; + gain = 0 - gain_value; + + initial_val = HW_REG_READ(DA5_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(DA5_DIGITAL_GAIN_REG, ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain VibL gain index = %d %d", + gain_index, error); + return error; + } + } + } + return error; +} +/** + * @brief Set gain of vibr + * @channel_index Channel-index of vibr + * @gain_index Gain index of vibr + * @gain_value Gain value of vibr + * @linear + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_set_vibr_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, + u32 linear, + struct device *dev) +{ + + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + /* Set Gain vibr */ + if (gain_index == 0) { + int gain = 0; + gain = 0 - gain_value; + + initial_val = HW_REG_READ(DA6_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(DA6_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain VibR gain index = %d %d", + gain_index, error); + return error; + } + } + } + return error; +} +/** + * @brief Set gain of ihf along a specified channel + * @channel_index Channel-index of ihf + * @gain_index Gain index of ihf + * @gain_value Gain value of ihf + * @linear + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_set_ihf_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + /* Set Gain IHFL */ + if (gain_index == 0) { + int gain = 0; + gain = 0 - gain_value; + + initial_val = HW_REG_READ(DA3_DIGITAL_GAIN_REG); + error = HW_REG_WRITE(DA3_DIGITAL_GAIN_REG, ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain IHFL gain index = %d %d", + gain_index, error); + return error; + } + + } + } + if (channel_index & e_CHANNEL_2) { + /* Set Gain IHFR */ + if (gain_index == 0) { + int gain = 0; + gain = 0 - gain_value; + + initial_val = HW_REG_READ(DA4_DIGITAL_GAIN_REG); + error = HW_REG_WRITE(DA4_DIGITAL_GAIN_REG, ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain IHFR gain index = %d %d", + gain_index, error); + return error; + } + } + } + + return error; +} +/** + * @brief Set gain of MIC1A & MIC1B + * @channel_index Channel-index of MIC1 + * @gain_index Gain index of MIC1 + * @gain_value Gain value of MIC1 + * @linear + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_set_mic1a_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + /* Set Gain mic1 */ + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD3_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(AD3_DIGITAL_GAIN_REG, ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain Mic1 gain index = %d %d", + gain_index, error); + return error; + } + + } + + if (gain_index == 1) { + /* Set Analog gain */ + initial_val = HW_REG_READ(ANALOG_MIC1_GAIN_REG); + + /* Write gain */ + error = HW_REG_WRITE(ANALOG_MIC1_GAIN_REG, ((initial_val + & (~MIC_ANALOG_GAIN_MASK)) | (gain_value & + MIC_ANALOG_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain Mic1 gain index = %d %d", + gain_index, error); + return error; + } + } + } + return error; +} +/** + * @brief Set gain of MIC2 + * @channel_index Channel-index of MIC2 + * @gain_index Gain index of MIC2 + * @gain_value Gain value of MIC2 + * @linear + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_set_mic2_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, + u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + /* Set Gain mic2 */ + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD2_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(AD2_DIGITAL_GAIN_REG, ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain Mic2 gain index = %d %d", + gain_index, error); + return error; + } + + } + + if (gain_index == 1) { + /* Set Analog gain */ + initial_val = HW_REG_READ(ANALOG_MIC2_GAIN_REG); + + /* Write gain */ + error = HW_REG_WRITE(ANALOG_MIC2_GAIN_REG, ((initial_val + & (~MIC_ANALOG_GAIN_MASK)) | (gain_value & + MIC_ANALOG_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain Mic2 gain index = %d %d", + gain_index, error); + return error; + } + } + } + return error; +} +/** + * @brief Set gain of Lin IN along a specified channel + * @channel_index Channel-index of Lin In + * @gain_index Gain index of Lin In + * @gain_value Gain value of Lin In + * @linear + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_set_lin_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD1_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(AD1_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain LinInL gain index = %d %d", + gain_index, error); + return error; + } + + } + + if (gain_index == 1) { + int gain = 0; + /* + * Converting -10 to 20 range into 0 - 15 + * & shifting it left by 4 bits + */ + gain = ((gain_value/2) + 5)<<4; + + initial_val = HW_REG_READ(ANALOG_LINE_IN_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(ANALOG_LINE_IN_GAIN_REG, + ((initial_val & (~L_ANALOG_GAIN_MASK)) | (gain & + L_ANALOG_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain LinInL gain index = %d %d", + gain_index, error); + return error; + } + } + } + + if (channel_index & e_CHANNEL_2) { + /* Set Gain LinInR */ + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD2_DIGITAL_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(AD2_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain LinInR gain index = %d%d", + gain_index, error); + return error; + } + } + if (gain_index == 1) { + int gain = 0; + /* Converting -10 to 20 range into 0 - 15 */ + gain = ((gain_value/2) + 5); + + initial_val = HW_REG_READ(ANALOG_LINE_IN_GAIN_REG); + /* Write gain */ + error = HW_REG_WRITE(ANALOG_LINE_IN_GAIN_REG, + ((initial_val & (~R_ANALOG_GAIN_MASK)) | (gain & + R_ANALOG_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain LinInR gain index = %d %d", + gain_index, error); + return error; + } + } + } + + return error; +} +/** + * @brief Set gain of DMIC12 along a specified channel + * @channel_index Channel-index of DMIC12 + * @gain_index Gain index of DMIC12 + * @gain_value Gain value of DMIC12 + * @linear + * @return 0 on success otherwise negative error code + */ + +int ste_audio_io_set_dmic12_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + /* Set Gain Dmic1 */ + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD1_DIGITAL_GAIN_REG); + error = HW_REG_WRITE(AD1_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain DMic1 gain index = %d %d", + gain_index, error); + return error; + } + } + } + if (channel_index & e_CHANNEL_2) { + /* Set Gain Dmic2 */ + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD2_DIGITAL_GAIN_REG); + error = HW_REG_WRITE(AD2_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain DMic2 gain index = %d %d", + gain_index, error); + return error; + } + } + } + return error; +} + +int ste_audio_io_switch_to_burst_mode_headset(int burst_fifo_switch_frame, + struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_INT_CONTROL_REG, + WAKEUP_SIGNAL_SAMPLE_COUNT, 0); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_LENGTH_REG, + BURST_FIFO_TRANSFER_LENGTH, 0); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_CONTROL_REG, + (BURST_FIFO_INF_RUNNING | BURST_FIFO_INF_IN_MASTER_MODE + |PRE_BIT_CLK0_COUNT), 0); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_WAKE_UP_DELAY_REG, + BURST_FIFO_WAKUP_DEALAY, 0); + if (0 != error) + return error; + + error = HW_REG_WRITE(BURST_FIFO_SWITCH_FRAME_REG, + burst_fifo_switch_frame); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(TDM_IF_BYPASS_B_FIFO_REG, + IF0_BFifoEn, 0); + if (0 != error) + return error; + + return error; +} +int ste_audio_io_switch_to_normal_mode_headset( + struct device *dev) +{ + int error = 0; + + error = HW_ACODEC_MODIFY_WRITE(TDM_IF_BYPASS_B_FIFO_REG, 0, + IF0_BFifoEn); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_INT_CONTROL_REG, + 0, WAKEUP_SIGNAL_SAMPLE_COUNT); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_LENGTH_REG, + 0, BURST_FIFO_TRANSFER_LENGTH); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_CONTROL_REG, 0, + (BURST_FIFO_INF_RUNNING | BURST_FIFO_INF_IN_MASTER_MODE + |PRE_BIT_CLK0_COUNT)); + if (0 != error) + return error; + + error = HW_ACODEC_MODIFY_WRITE(BURST_FIFO_WAKE_UP_DELAY_REG, + 0, BURST_FIFO_WAKUP_DEALAY); + if (0 != error) + return error; + + return error; +} + + +int ste_audio_io_mute_vibl(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + return 0; +} + +int ste_audio_io_unmute_vibl(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + return 0; +} + +int ste_audio_io_mute_vibr(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + return 0; +} +int ste_audio_io_unmute_vibr(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + return 0; +} + +int ste_audio_io_mute_dmic12(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + if ((channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + error = ste_audio_io_set_dmic12_gain(channel_index, 0, -32, + 0, dev); + if (0 != error) { + dev_err(dev, "Mute dmic12 %d", error); + return error; + } + } + + return error; + +} + +int ste_audio_io_unmute_dmic12(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + if ((channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + error = ste_audio_io_set_dmic12_gain(channel_index, + 0, gain[0], 0, dev); + if (0 != error) { + dev_err(dev, "UnMute dmic12 %d", error); + return error; + } + } + return error; +} +int ste_audio_io_enable_fade_dmic12(struct device *dev) +{ + return 0; +} + +int ste_audio_io_disable_fade_dmic12(struct device *dev) +{ + return 0; +} + +/** + * @brief enable hardware loop of dmic12 + * @chnl_index Channel-index of dmic12 + * @hw_loop type of hardware loop + * @loop_gain gain value to be used in hardware loop + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_enable_loop_dmic12(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS hw_loop, + int loop_gain, struct device *dev, + void *cookie) +{ + int error = 0; + struct transducer_context_t *trnsdr; + trnsdr = (struct transducer_context_t *)cookie; + + switch (hw_loop) { + /* Check if HSL is active */ + case AUDIOIO_SIDETONE_LOOP: + if (!trnsdr[HS_CH].is_power_up[e_CHANNEL_1] + && !trnsdr[EAR_CH].is_power_up[e_CHANNEL_1]) { + error = -EFAULT; + dev_err(dev, + "Sidetone enable needs HS or Earpiece powered up, err = %d", + error); + return error; + } + + if (chnl_index & e_CHANNEL_1) { + /* For ch1, Power On STFIR1, data comes from AD1*/ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG2, + 0, FIR1_FROMAD1); + if (error) { + dev_err(dev, "FIR1 data comes from AD_OUT1 %d", + error); + return error; + } + + error = HW_REG_WRITE(SIDETONE_FIR1_GAIN_REG, loop_gain); + if (error) { + dev_err(dev, + "Set FIR1 Gain index = %d", error); + return error; + } + } + + if (chnl_index & e_CHANNEL_2) { + /* For ch2, Power On STFIR1, data comes from AD2*/ + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG2, + 0, FIR1_FROMAD2); + if (error) { + dev_err(dev, "FIR1 data comes from AD_OUT2 %d", + error); + return error; + } + error = HW_REG_WRITE(SIDETONE_FIR2_GAIN_REG, loop_gain); + if (error) { + dev_err(dev, + "Set FIR2 Gain error = %d", error); + return error; + } + } + break; + default: + error = -EINVAL; + dev_err(dev, "loop not supported %d", error); + } + dump_acodec_registers(__func__, dev); + return error; +} + +/** + * @brief disable hardware loop of dmic12 + * @chnl_index Channel-index of dmic12 + * @hw_loop type of hardware loop + * @return 0 on success otherwise negative error code + */ +int ste_audio_io_disable_loop_dmic12(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS hw_loop, + struct device *dev, void *cookie) +{ + int error = -EINVAL; + struct transducer_context_t *trnsdr; + trnsdr = (struct transducer_context_t *)cookie; + + switch (hw_loop) { + /* Check if HSL is active */ + case AUDIOIO_SIDETONE_LOOP: + if (!trnsdr[HS_CH].is_power_up[e_CHANNEL_1] + && !trnsdr[EAR_CH].is_power_up[e_CHANNEL_1]) { + error = -EFAULT; + dev_err(dev, + "Sidetone disable needs HS or Earpiece powered up, err = %d", + error); + return error; + } + + if (chnl_index & e_CHANNEL_1) { + /* For ch1, Power On STFIR1, data comes from AD1*/ + error = + HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG2, + 0, FIR1_FROMAD1); + if (error) + dev_err(dev, "FIR1 data comes from AD_OUT1 %d", + error); + } + + if (chnl_index & e_CHANNEL_2) { + /* For ch2, Power On STFIR1, data comes from AD2*/ + error = + HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG2, + 0, FIR1_FROMAD2); + if (error) + dev_err(dev, "FIR1 data comes from AD_OUT2 %d", + error); + } + error = HW_ACODEC_MODIFY_WRITE(FILTERS_CONTROL_REG, + 0, FIR_FILTERCONTROL); + if (error) { + dev_err(dev, + "ST FIR Filters disable failed %d", error); + return error; + } + break; + default: + dev_err(dev, "loop not supported %d", error); + } + dump_acodec_registers(__func__, dev); + return error; +} + +int ste_audio_io_power_up_dmic34(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + /* Check if DMic34 request is mono or Stereo */ + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "DMic34 does not support more than 2 channels"); + return -EINVAL; + } + + /* Setting Direction for GPIO pins on AB8500 */ + error = HW_REG_WRITE(AB8500_GPIO_DIR4_REG, GPIO29_DIR_OUTPUT); + if (0 != error) { + dev_err(dev, "Setting Direction for GPIO pins on AB8500 %d", + error); + return error; + } + + if (channel_index & e_CHANNEL_1) { + /* Check if DMIC3 is already powered up or used by Mic1A + or Mic1B */ + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + + if (initialVal_AD & (EN_AD3)) + return 0; + + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT2_3_REG, + DATA_FROM_AD_OUT3, 0); + if (0 != error) { + dev_err(dev, "Slot 02 outputs data from AD_OUT3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, EN_AD3, + 0); + if (0 != error) { + dev_err(dev, "Enable AD3 for DMIC3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_MUXES_REG1, + SEL_DMIC3_FOR_AD_OUT3, + 0); + if (0 != error) { + dev_err(dev, "Select DMIC3 for AD_OUT3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, EN_DMIC3, 0); + if (0 != error) { + dev_err(dev, "Enable DMIC3 %d", error); + return error; + } +} + + /* Enable AD4 for Dmic4 */ + if (channel_index & e_CHANNEL_2) { + /* Check if DMIC4 is already powered up */ + if (initialVal_AD & (EN_AD4)) + return 0; + + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT2_3_REG, + (DATA_FROM_AD_OUT4<<4), 0); + if (0 != error) { + dev_err(dev, "Slot 03 outputs data from AD_OUT4 %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + EN_AD4, 0); + if (0 != error) { + dev_err(dev, "Enable AD4 for DMIC4 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, EN_DMIC4, 0); + if (0 != error) { + dev_err(dev, "Enable DMIC4 %d", error); + return error; + } + } + return error; +} + +int ste_audio_io_power_down_dmic34(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "DMic34 does not support more than 2 channels"); + return -EINVAL; + } + + /* Setting Direction for GPIO pins on AB8500 */ + error = HW_ACODEC_MODIFY_WRITE(AB8500_GPIO_DIR4_REG, 0, + GPIO29_DIR_OUTPUT); + if (0 != error) { + dev_err(dev, "Clearing Direction for GPIO pins on AB8500 %d", + error); + return error; + } + + /* Enable AD1 for Dmic1 */ + if (channel_index & e_CHANNEL_1) { + /* Check if DMIC3 is already powered Down or used by Mic1A + or Mic1B */ + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + if (!(initialVal_AD & EN_AD3)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, 0, EN_DMIC3); + if (0 != error) { + dev_err(dev, "Enable DMIC3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, + EN_AD3); + if (0 != error) { + dev_err(dev, "Disable AD3 for DMIC3 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT2_3_REG, 0, + DATA_FROM_AD_OUT3); + if (0 != error) { + dev_err(dev, + "Slot 02 outputs data cleared from AD_OUT3 %d", + error); + return error; + } + } + + /* Enable AD4 for Dmic4 */ + if (channel_index & e_CHANNEL_2) { + /* Check if DMIC4 is already powered down */ + initialVal_AD = HW_REG_READ(DIGITAL_AD_CHANNELS_ENABLE_REG); + if (!(initialVal_AD & EN_AD4)) + return 0; + + error = HW_ACODEC_MODIFY_WRITE(DMIC_ENABLE_REG, 0, EN_DMIC4); + if (0 != error) { + dev_err(dev, "Enable DMIC4 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(DIGITAL_AD_CHANNELS_ENABLE_REG, + 0, EN_AD4); + if (0 != error) { + dev_err(dev, "Disable AD4 for DMIC4 %d", error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT2_3_REG, 0, + (DATA_FROM_AD_OUT4<<4)); + if (0 != error) { + dev_err(dev, + "Slot 03 outputs data cleared from AD_OUT4 %d", + error); + return error; + } + } + return error; +} +int ste_audio_io_set_dmic34_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + int error = 0; + unsigned char initial_val = 0; + + if (channel_index & e_CHANNEL_1) { + /* Set Gain Dmic3 */ + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD3_DIGITAL_GAIN_REG); + error = HW_REG_WRITE(AD3_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + if (0 != error) { + dev_err(dev, + "Set Gain DMic3 gain index = %d %d", + gain_index, error); + return error; + } + } + } + + if (channel_index & e_CHANNEL_2) { + /* Set Gain Dmic4 */ + if (gain_index == 0) { + int gain = 0; + gain = 31 - gain_value; + + initial_val = HW_REG_READ(AD4_DIGITAL_GAIN_REG); + error = HW_REG_WRITE(AD4_DIGITAL_GAIN_REG, + ((initial_val + & (~DIGITAL_GAIN_MASK)) | (gain & DIGITAL_GAIN_MASK))); + + if (0 != error) { + dev_err(dev, + "Set Gain DMic4 gain index = %d %d", + gain_index, error); + return error; + } + } + } + + return error; +} +int ste_audio_io_mute_dmic34(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + if ((channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + error = ste_audio_io_set_dmic34_gain(channel_index, 0, -32, + 0, dev); + if (0 != error) { + dev_err(dev, "Mute dmic34 %d", error); + return error; + } + } + return error; +} +int ste_audio_io_unmute_dmic34(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + int error = 0; + if ((channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + error = ste_audio_io_set_dmic34_gain(channel_index, + 0, gain[0], 0, dev); + if (0 != error) { + dev_err(dev, "UnMute dmic34 %d", error); + return error; + } + } + return error; +} +int ste_audio_io_enable_fade_dmic34(struct device *dev) +{ + return 0; +} + +int ste_audio_io_disable_fade_dmic34(struct device *dev) +{ + return 0; +} + +int ste_audio_io_power_up_dmic56(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + return 0; +} +int ste_audio_io_power_down_dmic56(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + return 0; +} +int ste_audio_io_set_dmic56_gain(enum AUDIOIO_CH_INDEX channel_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev) +{ + return 0; +} +int ste_audio_io_mute_dmic56(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + return 0; +} +int ste_audio_io_unmute_dmic56(enum AUDIOIO_CH_INDEX channel_index, int *gain, + struct device *dev) +{ + return 0; +} +int ste_audio_io_enable_fade_dmic56(struct device *dev) +{ + return 0; +} + +int ste_audio_io_disable_fade_dmic56(struct device *dev) +{ + return 0; +} + +int ste_audio_io_configure_if1(struct device *dev) +{ + int error = 0; + + error = HW_REG_WRITE(IF1_CONF_REG, IF_DELAYED | + I2S_LEFT_ALIGNED_FORMAT | WORD_LENGTH_16); + if (error != 0) { + dev_err(dev, + "Configure IF1: I2S Format 16 Bits word length error = %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(TDM_IF_BYPASS_B_FIFO_REG, IF1_MASTER, 0); + if (error != 0) { + dev_err(dev, + "Configure IF1: IF1 master error = %d", + error); + return error; + } + + error = HW_ACODEC_MODIFY_WRITE(IF0_IF1_MASTER_CONF_REG, + EN_FSYNC_BITCLK1, 0); + if (error != 0) { + dev_err(dev, + "ConfigIF1 bitclk is 32x48KHz, enable Fsync1 and Bitclk1 error = %d", + error); + return error; + } + return error; +} + +int ste_audio_io_power_up_fmrx(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal = 0; + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "FMRX should have mono or stereo channels"); + return -EINVAL; + } + + ste_audio_io_configure_if1(dev); + + if (channel_index & e_CHANNEL_1) { + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA7_REG, + SLOT24_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA_IN7 from Slot 24 %d", + error); + return error; + } + /* DA_IN7 to AD_OUT8 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA5_REG, + SEL_AD_OUT8_FROM_DAIN7, 0); + if (0 != error) { + dev_err(dev, "Data sent to AD_OUT5 from DA_IN7 %d", + error); + return error; + } + + initialVal = HW_REG_READ(AD_ALLOCATION_TO_SLOT6_7_REG); + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT6_7_REG, + ((initialVal & MASK_QUARTET1)|SEL_IF6_FROM_AD_OUT5)); + if (0 != error) { + dev_err(dev, "Data sent to IF slot 6 from AD_OUT5 %d", + error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA8_REG, + SLOT25_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA_IN8 from Slot 25 %d", + error); + return error; + } + + /* DA_IN7 to AD_OUT8 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA6_REG, + SEL_AD_OUT6_FROM_DAIN8, 0); + if (0 != error) { + dev_err(dev, "Data sent to AD_OUT6 from DA_IN8 %d", + error); + return error; + } + + initialVal = HW_REG_READ(AD_ALLOCATION_TO_SLOT6_7_REG); + + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT6_7_REG, + (initialVal & MASK_QUARTET0)|SEL_IF7_FROM_AD_OUT6); + /* 5x is written */ + if (0 != error) { + dev_err(dev, "Data sent to IF7 from AD_OUT6 %d", + error); + return error; + } + } + return error; +} +int ste_audio_io_power_down_fmrx(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "FMRX should have mono or stereo channels"); + return -EINVAL; + } + if (channel_index & e_CHANNEL_1) { + /* data sent to DA7 input of DA filter form IF1 */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA7_REG, 0, + SLOT24_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, "Clearing Data sent to DA_IN7 from Slot 24 %d", + error); + return error; + } + /* DA_IN7 to AD_OUT8 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA5_REG, 0, + SEL_AD_OUT8_FROM_DAIN7); + if (0 != error) { + dev_err(dev, "Clearing Data sent to AD_OUT5 from DA_IN7 %d", + error); + return error; + } + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT6_7_REG, 0, + SEL_IF6_FROM_AD_OUT5); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to IF slot 6 from AD_OUT5 %d", + error); + return error; + } +} + + if (channel_index & e_CHANNEL_2) { + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA8_REG, 0, + SLOT25_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to DA_IN8 from Slot 25 %d", + error); + return error; + } + + /* DA_IN7 to AD_OUT8 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA6_REG, 0, + SEL_AD_OUT6_FROM_DAIN8); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to AD_OUT6 from DA_IN8 %d", + error); + return error; + } + error = HW_ACODEC_MODIFY_WRITE(AD_ALLOCATION_TO_SLOT6_7_REG, 0, + SEL_IF7_FROM_AD_OUT6); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to IF7 from AD_OUT6 %d", + error); + return error; + } + } + return error; +} + +int ste_audio_io_power_up_fmtx(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal = 0; + + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "FMTX should have mono or stereo channels"); + return -EINVAL; + } + + ste_audio_io_configure_if1(dev); + + if (channel_index & e_CHANNEL_1) { + /* data sent to DA7 input of DA filter form IF1 14 slot */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA7_REG, + SLOT14_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, + "Data sent to DA_IN7 from Slot 14 %d", error); + return error; + } + /* DA_IN7 to AD_OUT5 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA5_REG, + SEL_AD_OUT5_FROM_DAIN7, 0); + if (0 != error) { + dev_err(dev, "Data sent to AD_OUT5 from DA_IN7 %d", + error); + return error; + } + + initialVal = HW_REG_READ(AD_ALLOCATION_TO_SLOT16_17_REG); + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT16_17_REG, + (initialVal & MASK_QUARTET1)|SEL_IF6_FROM_AD_OUT5); + if (0 != error) { + dev_err(dev, "Data sent to IF16 from AD_OUT5 %d", + error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + /* data sent to DA8 input of DA filter */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA8_REG, + SLOT15_FOR_DA_PATH, 0); + if (0 != error) { + dev_err(dev, "Data sent to DA_IN8 from Slot 15 %d", + error); + return error; + } + + /* DA_IN8 to AD_OUT6 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA6_REG, + SEL_AD_OUT6_FROM_DAIN8, 0); + if (0 != error) { + dev_err(dev, "Data sent to AD_OUT6 from DA_IN8 %d", + error); + return error; + } + + initialVal = HW_REG_READ(AD_ALLOCATION_TO_SLOT16_17_REG); + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT16_17_REG, + (initialVal & MASK_QUARTET0)|SEL_IF17_FROM_AD_OUT6); + if (0 != error) { + dev_err(dev, "Data sent to IF17 from AD_OUT6 %d", + error); + return error; + } + } + return error; +} + +int ste_audio_io_power_down_fmtx(enum AUDIOIO_CH_INDEX channel_index, + struct device *dev) +{ + int error = 0; + unsigned char initialVal_AD = 0; + + if (!(channel_index & (e_CHANNEL_1 | e_CHANNEL_2))) { + dev_err(dev, "FMTX should have mono or stereo channels"); + return -EINVAL; + } + + if (channel_index & e_CHANNEL_1) { + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA7_REG, 0, + SLOT14_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to DA_IN7 from Slot 14 %d", + error); + return error; + } + /* DA_IN7 to AD_OUT8 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA5_REG, 0, + SEL_AD_OUT5_FROM_DAIN7); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to AD_OUT5 from DA_IN7 %d", + error); + return error; + } + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT16_17_REG, + SEL_IF6_FROM_AD_OUT5); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to IF16 from AD_OUT8 %d", + error); + return error; + } + } + + if (channel_index & e_CHANNEL_2) { + /* data sent to DA8 input of DA filter */ + initialVal_AD = HW_REG_READ(SLOT_SELECTION_TO_DA8_REG); + + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA8_REG, 0, + SLOT15_FOR_DA_PATH); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to DA_IN8 from Slot 15 %d", + error); + return error; + } + + /* DA_IN7 to AD_OUT8 path */ + error = HW_ACODEC_MODIFY_WRITE(SLOT_SELECTION_TO_DA6_REG, 0, + SEL_AD_OUT6_FROM_DAIN8); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to AD_OUT6 from DA_IN8 %d", + error); + return error; + } + error = HW_REG_WRITE(AD_ALLOCATION_TO_SLOT16_17_REG, + SEL_IF17_FROM_AD_OUT6); + if (0 != error) { + dev_err(dev, + "Clearing Data sent to IF17 from AD_OUT6 %d", + error); + return error; + } + } + return error; +} +int ste_audio_io_power_up_bluetooth(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev) +{ + int error = 0; + struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); + struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); + if (bluetooth_power_up_count++) + return error; + + if (pdata) { + if (pdata->audio) { + error = pdata->audio->ste_gpio_altf_init(); + if (error == 0) { + clk_ptr_msp0 = clk_get_sys("msp0", NULL); + if (!IS_ERR(clk_ptr_msp0)) { + error = clk_enable(clk_ptr_msp0); + return error; + } else + return -EFAULT; + } + } + } + return error; +} + +int ste_audio_io_power_down_bluetooth(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev) +{ + int error = 0; + struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); + struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); + + if (--bluetooth_power_up_count) + return error; + + if (pdata) { + if (pdata->audio) { + error = pdata->audio->ste_gpio_altf_exit(); + if (error == 0) { + clk_disable(clk_ptr_msp0); + clk_put(clk_ptr_msp0); + } + } + } + return error; +} + +int dump_acodec_registers(const char *str, struct device *dev) +{ + int reg_count = REVISION_REG & 0xff; + if (1 == acodec_reg_dump) { + u8 i = 0; + dev_info(dev, "\n func : %s\n", str); + for (i = 0; i <= reg_count; i++) + dev_info(dev, + "block = 0x0D, adr = %x = %x\n", + i, HW_REG_READ((AB8500_AUDIO << 8) | i)); + } + str = str; /* keep compiler happy */ + return 0; +} + +int debug_audioio(int x) +{ + + if (1 == x) + acodec_reg_dump = 1; + else + acodec_reg_dump = 0; + return 0; +} + + + + + diff --git a/drivers/misc/audio_io_dev/ste_audio_io_func.h b/drivers/misc/audio_io_dev/ste_audio_io_func.h new file mode 100644 index 00000000000..282b25751d6 --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_func.h @@ -0,0 +1,359 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#ifndef _AUDIOIO_FUNC_H_ +#define _AUDIOIO_FUNC_H_ + +#include +#include +#include +#include +#include + +#define AB8500_REV_10 0x10 +#define AB8500_REV_11 0x11 +#define AB8500_REV_20 0x20 + +#define AB8500_CTRL3_REG 0x00000200 +#define AB8500_SYSULPCLK_CTRL1_REG 0x0000020B +#define AB8500_GPIO_DIR4_REG 0x00001013 +#define AB8500_GPIO_DIR5_REG 0x00001014 +#define AB8500_GPIO_OUT5_REG 0x00001024 + +extern struct platform_device *ste_audio_io_device; +extern struct regulator *regulator_avsource; + +int dump_acodec_registers(const char *, struct device *dev); +int debug_audioio(int x); + +#define AB8500_BLOCK_ADDR(address) ((address >> 8) & 0xff) +#define AB8500_OFFSET_ADDR(address) (address & 0xff) + +static inline unsigned char HW_REG_READ(unsigned short reg) +{ + unsigned char ret; + int err; + + err = abx500_get_register_interruptible(&ste_audio_io_device->dev, + AB8500_BLOCK_ADDR(reg), + AB8500_OFFSET_ADDR(reg), + &ret); + if (err < 0) + return err; + else + return ret; +} + +static inline int HW_REG_WRITE(unsigned short reg, unsigned char data) +{ + return abx500_set_register_interruptible(&ste_audio_io_device->dev, + AB8500_BLOCK_ADDR(reg), + AB8500_OFFSET_ADDR(reg), + data); +} + +unsigned int ab8500_acodec_modify_write(unsigned int reg, u8 mask_set, + u8 mask_clear); + +#define HW_ACODEC_MODIFY_WRITE(reg, mask_set, mask_clear)\ + ab8500_acodec_modify_write(reg, mask_set, mask_clear) + +unsigned int ab8500_modify_write(unsigned int reg, u8 mask_set, u8 mask_clear); + +int ste_audio_io_power_up_headset(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_headset(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_headset_query(struct device *dev); +int ste_audio_io_set_headset_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_headset_gain(int *, int *, u16, + struct device *dev); +int ste_audio_io_mute_headset(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_headset(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_headset_state(struct device *dev); +int ste_audio_io_enable_fade_headset(struct device *dev); +int ste_audio_io_disable_fade_headset(struct device *dev); +int ste_audio_io_switch_to_burst_mode_headset(int burst_fifo_switch_frame, + struct device *dev); +int ste_audio_io_switch_to_normal_mode_headset( + struct device *dev); + +int ste_audio_io_power_up_earpiece(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_earpiece(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_earpiece_query(struct device *dev); +int ste_audio_io_set_earpiece_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_earpiece_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_earpiece(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_earpiece(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_earpiece_state(struct device *dev); +int ste_audio_io_enable_fade_earpiece(struct device *dev); +int ste_audio_io_disable_fade_earpiece(struct device *dev); + +int ste_audio_io_power_up_ihf(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_ihf(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_ihf_query(struct device *dev); +int ste_audio_io_set_ihf_gain(enum AUDIOIO_CH_INDEX chnl_index, u16 gain_index, + int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_ihf_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_ihf(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_ihf(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_ihf_state(struct device *dev); +int ste_audio_io_enable_fade_ihf(struct device *dev); +int ste_audio_io_disable_fade_ihf(struct device *dev); + +int ste_audio_io_power_up_vibl(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_vibl(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_vibl_query(struct device *dev); +int ste_audio_io_set_vibl_gain(enum AUDIOIO_CH_INDEX chnl_index, u16 gain_index, + int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_vibl_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_vibl(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_vibl(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_vibl_state(struct device *dev); +int ste_audio_io_enable_fade_vibl(struct device *dev); +int ste_audio_io_disable_fade_vibl(struct device *dev); + +int ste_audio_io_power_up_vibr(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_vibr(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_vibr_query(struct device *dev); +int ste_audio_io_set_vibr_gain(enum AUDIOIO_CH_INDEX chnl_index, u16 gain_index, + int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_vibr_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_vibr(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_vibr(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_vibr_state(struct device *dev); +int ste_audio_io_enable_fade_vibr(struct device *dev); +int ste_audio_io_disable_fade_vibr(struct device *dev); + +int ste_audio_io_power_up_mic1a(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_mic1a(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_mic1a_query(struct device *dev); +int ste_audio_io_set_mic1a_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, struct device *dev); +int ste_audio_io_get_mic1a_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_mic1a(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_mic1a(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_mic1a_state(struct device *dev); +int ste_audio_io_enable_fade_mic1a(struct device *dev); +int ste_audio_io_disable_fade_mic1a(struct device *dev); + +/* + *** Mic1b *** + */ +int ste_audio_io_power_up_mic1b(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_mic1b(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_mic1b_query(struct device *dev); +int ste_audio_io_set_mic1b_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, struct device *dev); +int ste_audio_io_get_mic1b_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_mic1b(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_mic1b(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_mic1b_state(struct device *dev); +int ste_audio_io_enable_fade_mic1b(struct device *dev); +int ste_audio_io_disable_fade_mic1b(struct device *dev); +int ste_audio_io_enable_loop_mic1b(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS, + int loop_gain, struct device *dev, + void *cookie); +int ste_audio_io_disable_loop_mic1b(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS hw_loop, + struct device *dev, void *cookie); +/* + *** Mic2 *** + */ +int ste_audio_io_power_up_mic2(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_mic2(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_mic2_query(struct device *dev); +int ste_audio_io_set_mic2_gain(enum AUDIOIO_CH_INDEX chnl_index, u16 gain_index, + int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_mic2_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_mic2(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_mic2(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_mic2_state(struct device *dev); +int ste_audio_io_enable_fade_mic2(struct device *dev); +int ste_audio_io_disable_fade_mic2(struct device *dev); + +int ste_audio_io_power_up_lin(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_lin(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_lin_query(struct device *dev); +int ste_audio_io_set_lin_gain(enum AUDIOIO_CH_INDEX chnl_index, u16 gain_index, + int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_lin_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_lin(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_lin(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_lin_state(struct device *dev); +int ste_audio_io_enable_fade_lin(struct device *dev); +int ste_audio_io_disable_fade_lin(struct device *dev); + +int ste_audio_io_power_up_dmic12(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_dmic12(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_dmic12_query(struct device *dev); +int ste_audio_io_set_dmic12_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_dmic12_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_dmic12(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_dmic12(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_dmic12_state(struct device *dev); +int ste_audio_io_enable_fade_dmic12(struct device *dev); +int ste_audio_io_disable_fade_dmic12(struct device *dev); +int ste_audio_io_enable_loop_dmic12(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS, + int loop_gain, struct device *dev, + void *cookie); +int ste_audio_io_disable_loop_dmic12(enum AUDIOIO_CH_INDEX chnl_index, + enum AUDIOIO_HAL_HW_LOOPS hw_loop, + struct device *dev, void *cookie); + +int ste_audio_io_power_up_dmic34(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_dmic34(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_dmic34_query(struct device *dev); +int ste_audio_io_set_dmic34_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_dmic34_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_dmic34(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_dmic34(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_dmic34_state(struct device *dev); +int ste_audio_io_enable_fade_dmic34(struct device *dev); +int ste_audio_io_disable_fade_dmic34(struct device *dev); + +int ste_audio_io_power_up_dmic56(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_dmic56(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_dmic56_query(struct device *dev); +int ste_audio_io_set_dmic56_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_dmic56_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_dmic56(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_dmic56(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_dmic56_state(struct device *dev); +int ste_audio_io_enable_fade_dmic56(struct device *dev); +int ste_audio_io_disable_fade_dmic56(struct device *dev); + +int ste_audio_io_power_up_fmrx(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_fmrx(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_fmrx_query(struct device *dev); +int ste_audio_io_set_fmrx_gain(enum AUDIOIO_CH_INDEX chnl_index, u16 gain_index, + int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_fmrx_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_fmrx(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_fmrx(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_fmrx_state(struct device *dev); +int ste_audio_io_enable_fade_fmrx(struct device *dev); +int ste_audio_io_disable_fade_fmrx(struct device *dev); + +int ste_audio_io_power_up_fmtx(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_fmtx(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_fmtx_query(struct device *dev); +int ste_audio_io_set_fmtx_gain(enum AUDIOIO_CH_INDEX chnl_index, u16 gain_index, + int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_fmtx_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_fmtx(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_fmtx(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_fmtx_state(struct device *dev); +int ste_audio_io_enable_fade_fmtx(struct device *dev); +int ste_audio_io_disable_fade_fmtx(struct device *dev); + +int ste_audio_io_power_up_bluetooth(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_down_bluetooth(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_power_state_bluetooth_query(struct device *dev); +int ste_audio_io_set_bluetooth_gain(enum AUDIOIO_CH_INDEX chnl_index, + u16 gain_index, int gain_value, u32 linear, + struct device *dev); +int ste_audio_io_get_bluetooth_gain(int*, int*, u16, + struct device *dev); +int ste_audio_io_mute_bluetooth(enum AUDIOIO_CH_INDEX chnl_index, + struct device *dev); +int ste_audio_io_unmute_bluetooth(enum AUDIOIO_CH_INDEX chnl_index, int *gain, + struct device *dev); +int ste_audio_io_mute_bluetooth_state(struct device *dev); +int ste_audio_io_enable_fade_bluetooth(struct device *dev); +int ste_audio_io_disable_fade_bluetooth(struct device *dev); + + +#endif + diff --git a/drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.c b/drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.c new file mode 100644 index 00000000000..c2409f849ae --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + + +#include +#include "ste_audio_io_hwctrl_common.h" + +/* Number of channels for each transducer */ +const uint transducer_no_of_channels[MAX_NO_TRANSDUCERS] = { + 1, /* Earpiece */ + 2, /* HS */ + 2, /* IHF */ + 1, /* VibL */ + 1, /* VibR */ + 1, /* Mic1A */ + 1, /* Mic1B */ + 1, /* Mic2 */ + 2, /* LinIn */ + 2, /* DMIC12 */ + 2, /* DMIC34 */ + 2, /* /DMIC56 */ + 4 /* MultiMic */ + }; + +/* Maximum number of gains in each transducer path + (all channels of a specific transducer have same max no of gains) */ +const uint transducer_no_of_gains[MAX_NO_TRANSDUCERS] = { + 2, /* Ear g3 and g4 */ + 3, /* HS g3 and g4 and analog */ + 1, /* IHF g3 */ + 1, /* VibL g3 */ + 1, /* VibR g3 */ + 2, /* Mic1A g1 and analog */ + 2, /* Mic1A g1 and analog */ + 2, /* Mic2 g1 and analog */ + 2, /* LinIn g1 and analog */ + 1, /* DMIC12 g1 */ + 1, /* DMIC34 g1 */ + 1, /* DMIC56 g1 */ + 1 /* MultiMic g1 */ + }; + +const uint transducer_no_Of_supported_loop_indexes[MAX_NO_TRANSDUCERS] = { + 0x09,/* Ear0x01|0x08*/ + 0x38770,/*{0x01|0x10|0x20|0x40|0x100*/ + /*|0x200|0x400|0x8000|0x10000|0x20000}, HS*/ + 0x86,/*IHF*/ + 0x0,/*VibL*/ + 0x0,/*VibR*/ + 0x0,/*Mic1A*/ + 0x01,/*Mic1B Sidetone is controlled*/ + 0x0,/*Mic2*/ + 0x0,/*LinIn*/ + 0x0,/*DMIC12*/ + 0x0,/*DMIC34*/ + 0x0,/*DMIC56*/ + 0x01,/*MultiMic Sidetone is controlled*/ + 0x0,/*FMRx*/ + 0x0/*FMTx*/ + }; + +const uint transducer_max_no_Of_supported_loops[MAX_NO_TRANSDUCERS] = { + 0,/*Ear Sidetone*/ + 2,/*HS SideTone LININ_HS LININR_HSR LININ_HSL*/ + 1,/*IHF TO BE DEFINED*/ + 0,/*VibL TO BE DEFINED*/ + 0,/*VibR TO BE DEFINED*/ + 1,/*Mic1A TO BE DEFINED*/ + 1,/*Mic1B SIDETONE TO BE DEFINED*/ + 1,/*Mic2 TO BE DEFINED*/ + 0, /* LinIn */ + 1,/*DMIC12-ANC*/ + 0,/*DMIC34-ANC*/ + 0, /* DMIC56 */ + 1,/*MultiMic-SIDETONE ANC*/ + 0,/*FMRx*/ + 0/*FMTx*/ + }; + +const uint max_no_of_loop_gains[MAX_NO_TRANSDUCERS] = { + 0,/*Earpiece*/ + 2,/*HS*/ + 0, + 0, + 0, + 0, + 2,/*Mic1B-Sidetone 2 gains*/ + 0, + 0, + 2,/*DMIC12*/ + 0, + 0, + 2,/*Multimic, Sidetone max no gains = 2*/ + 0, + 0 + }; + + +struct gain_descriptor_t gain_descriptor[MAX_NO_TRANSDUCERS]\ + [MAX_NO_CHANNELS][MAX_NO_GAINS] = { + /* gainIndex=0 1 2 + EDestinationEar */ + {{{-63, 0, 1}, {-1, 8, 1}, {0, 0, 0} } ,/* channelIndex=0 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* EDestinationHS */ + {{{-63, 0, 1}, {-1, 8, 1}, {-32, 4, 2} } , /* channelIndex=0 */ + {{-63, 0, 1}, {-1, 8, 1}, {-32, 4, 2} } , /* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } , /* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } , /* channelIndex=3 */ + + /* EDestinationIHF */ + {{{-63, 0, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=0 */ + {{-63, 0, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* EDestinationVibL */ + {{{-63, 0, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=0 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* EDestinationVibR */ + {{{-63, 0, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=0 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceMic1A */ + {{{-32, 31, 1}, {0, 31, 1}, {0, 0, 0} } ,/* channelIndex=0 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceMic1B */ + {{{-32, 31, 1}, {0, 31, 1}, {0, 0, 0} } ,/* channelIndex=0 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceMic2 */ + {{{-32, 31, 1}, {0, 31, 1}, {0, 0, 0} } ,/* channelIndex=0 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceLin */ + {{{-32, 31, 1}, {-10, 20, 2}, {0, 0, 0} } ,/* channelIndex=0 */ + {{-32, 31, 1}, {-10, 20, 2}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceDMic12 */ + {{{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=0 */ + {{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceDMic34 */ + {{{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=0 */ + {{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceDMic56 */ + {{{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=0 */ + {{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=2 */ + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0} } } ,/* channelIndex=3 */ + + /* ESourceMultiMic */ + {{{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=0 */ + {{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } ,/* channelIndex=1 */ + {{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} },/* channelIndex=2 */ + {{-32, 31, 1}, {0, 0, 0}, {0, 0, 0} } } /* channelIndex=3 */ +}; + + +const int hs_analog_gain_table[16] = {4, 2, 0, -2, -4, -6, -8, -10, + -12, -14, -16, -18, -20, -24, -28, -32}; + + + diff --git a/drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.h b/drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.h new file mode 100644 index 00000000000..cc2bfe21d81 --- /dev/null +++ b/drivers/misc/audio_io_dev/ste_audio_io_hwctrl_common.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2. + */ + +#ifndef __AUDIOIO_HWCTRL_COMMON_H__ +#define __AUDIOIO_HWCTRL_COMMON_H__ + +#include +#include +/* + * Defines + */ + +#define MAX_GAIN 100 +#define MIN_GAIN 0 +#define MAX_NO_CHANNELS 4 +#define MAX_NO_GAINS 3 +#define MAX_NO_LOOPS 1 +#define MAX_NO_LOOP_GAINS 1 + +struct gain_descriptor_t { + int min_gain; + int max_gain; + uint gain_step; +}; + + +/* Number of channels for each transducer */ +extern const uint transducer_no_of_channels[MAX_NO_TRANSDUCERS]; + +/* + * Maximum number of gains in each transducer path + * all channels of a specific transducer have same max no of gains + */ +extern const uint transducer_no_of_gains[MAX_NO_TRANSDUCERS]; + +/* Maximum number of supported loops for each transducer */ +extern const uint transducer_no_Of_supported_loop_indexes[MAX_NO_TRANSDUCERS]; +extern const uint transducer_max_no_Of_supported_loops[MAX_NO_TRANSDUCERS]; +extern const uint max_no_of_loop_gains[MAX_NO_TRANSDUCERS]; +extern const int hs_analog_gain_table[16] ; + +extern struct gain_descriptor_t gain_descriptor[MAX_NO_TRANSDUCERS]\ + [MAX_NO_CHANNELS][MAX_NO_GAINS]; + +#endif + +/* End of audio_io_hwctrl_common.h */ -- cgit v1.2.3 From 08142ec6f4f19a5e882c5650676c6d1c441abd92 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 20 Oct 2011 10:34:26 +0200 Subject: misc: Add i2s driver Signed-off-by: Robert Marklund Conflicts: drivers/misc/Makefile Conflicts: drivers/misc/Kconfig drivers/misc/Makefile --- Documentation/DocBook/i2s.tmpl | 97 ++ drivers/misc/i2s/Kconfig | 29 + drivers/misc/i2s/Makefile | 8 + drivers/misc/i2s/i2s.c | 597 ++++++++ drivers/misc/i2s/i2s_test_protocol_driver.c | 305 ++++ drivers/misc/i2s/msp_i2s.c | 2045 +++++++++++++++++++++++++++ drivers/misc/i2s/msp_i2s.h | 362 +++++ include/linux/i2s/i2s.h | 225 +++ include/linux/i2s/i2s_test_prot.h | 44 + 9 files changed, 3712 insertions(+) create mode 100644 Documentation/DocBook/i2s.tmpl create mode 100644 drivers/misc/i2s/Kconfig create mode 100644 drivers/misc/i2s/Makefile create mode 100644 drivers/misc/i2s/i2s.c create mode 100644 drivers/misc/i2s/i2s_test_protocol_driver.c create mode 100644 drivers/misc/i2s/msp_i2s.c create mode 100644 drivers/misc/i2s/msp_i2s.h create mode 100644 include/linux/i2s/i2s.h create mode 100644 include/linux/i2s/i2s_test_prot.h diff --git a/Documentation/DocBook/i2s.tmpl b/Documentation/DocBook/i2s.tmpl new file mode 100644 index 00000000000..6b6c50572e2 --- /dev/null +++ b/Documentation/DocBook/i2s.tmpl @@ -0,0 +1,97 @@ + + + + + + I2S + + + + Sandeep + Kaushik + +
+ sandeep.kaushik@st.com +
+
+
+
+ + + 2008-2009 + STMicroelectronics Pvt Ltd + + + + + Linux standard functions + + + + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + 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. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + Introduction + + This Documentation describes the APIs provided by the I2S Bus Driver. I2S bus supports different + protocols like I2S, PCM, SPI etc. + + + + + Known Bugs And Assumptions + + + + None + + + None. + + + + + + + + + Public Functions Provided + + This Section lists the functions exported by the I2S bus driver. These functions cater to all the protocols + supported namely: I2S, PCM, SPI. + +!Edrivers/misc/i2s/i2s.c + +
diff --git a/drivers/misc/i2s/Kconfig b/drivers/misc/i2s/Kconfig new file mode 100644 index 00000000000..a2652e9eab3 --- /dev/null +++ b/drivers/misc/i2s/Kconfig @@ -0,0 +1,29 @@ +# +# U8500 I2S HW kernel configuration +# +config STM_I2S + bool "U8500 I2S hardware driver" + depends on ARCH_U8500 && STE_DMA40 + default y + ---help--- + If you say Y here, you will enable the U8500 I2S hardware driver. + + If unsure, say N. +config STM_MSP_I2S + tristate "U8500 MSP_I2S hardware driver" + depends on ARCH_U8500 && STE_DMA40 && STM_I2S + default y + ---help--- + If you say Y here, you will enable the U8500 MSP_I2S hardware driver. + + If unsure, say N. + +config STM_I2S_TEST_PROTOCOL_DRIVER + tristate "U8500 I2S test protocol driver" + depends on STM_I2S && STE_DMA40 && STM_MSP_I2S + default n + ---help--- + If you say Y here, you will enable the test protocol driver used for testing I2S Rx and Tx controllers + + If unsure, say N. + diff --git a/drivers/misc/i2s/Makefile b/drivers/misc/i2s/Makefile new file mode 100644 index 00000000000..22cfdc07551 --- /dev/null +++ b/drivers/misc/i2s/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for I2S drivers +# + +nmdk_i2s-objs := i2s.o +obj-$(CONFIG_STM_I2S) += nmdk_i2s.o +obj-$(CONFIG_STM_MSP_I2S) += msp_i2s.o +obj-$(CONFIG_STM_I2S_TEST_PROTOCOL_DRIVER) += i2s_test_protocol_driver.o diff --git a/drivers/misc/i2s/i2s.c b/drivers/misc/i2s/i2s.c new file mode 100644 index 00000000000..a77711e3dd4 --- /dev/null +++ b/drivers/misc/i2s/i2s.c @@ -0,0 +1,597 @@ +/*----------------------------------------------------------------------------*/ +/* copyright STMicroelectronics, 2007. */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the Free */ +/* Software Foundation; either version 2.1 of the License, or (at your option)*/ +/* any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY */ +/* or FITNES */ +/* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more */ +/* details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see . */ +/*----------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*******************************************************************************/ +static DEFINE_MUTEX(core_lock); + +static void i2sdev_release(struct device *dev) +{ + struct i2s_device *i2s = to_i2s_device(dev); + + if (i2s->controller) + put_device(&(i2s->controller->dev)); + kfree(dev); +} +static ssize_t +modalias_show(struct device *dev, struct device_attribute *a, char *buf) +{ + const struct i2s_device *i2s = to_i2s_device(dev); + return sprintf(buf, "%s\n", i2s->modalias); +} + +static struct device_attribute i2s_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +/* modalias support makes "modprobe $MODALIAS" new-style hotplug work, + * and the sysfs version makes coldplug work too. + */ +static const struct i2s_device_id *i2s_match_id(const struct i2s_device_id *id, + const struct i2s_device *device) +{ + while (id->name[0]) { + if (strcmp(device->modalias, id->name) == 0) + return id; + id++; + } + return NULL; +} + +static int i2s_match_device(struct device *dev, struct device_driver *drv) +{ + const struct i2s_device *device = to_i2s_device(dev); + struct i2s_driver *driver = to_i2s_driver(drv); + if (driver->id_table) + return i2s_match_id(driver->id_table, device) != NULL; + return 0; +} + +static int i2s_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + const struct i2s_device *i2s = to_i2s_device(dev); + + add_uevent_var(env, "MODALIAS=%s", i2s->modalias); + return 0; +} + +#ifdef CONFIG_PM +static int i2s_suspend(struct device *dev, pm_message_t message) +{ + int value = 0; + struct i2s_driver *drv = to_i2s_driver(dev->driver); + + /* suspend will stop irqs and dma; no more i/o */ + if (drv) { + if (drv->suspend) + value = drv->suspend(to_i2s_device(dev), message); + else + dev_dbg(dev, "... can't suspend\n"); + } + return value; +} + +static int i2s_resume(struct device *dev) +{ + int value = 0; + struct i2s_driver *drv = to_i2s_driver(dev->driver); + + /* resume may restart the i/o queue */ + if (drv) { + if (drv->resume) + value = drv->resume(to_i2s_device(dev)); + else + dev_dbg(dev, "... can't resume\n"); + } + return value; +} + +#else +#define i2s_suspend NULL +#define i2s_resume NULL +#endif + +/*This bus is designed to handle various protocols supported by the MSP- ARM Primecell IP + * such as + * I2s, PCM, AC97, TDM .... (refer to the data sheet for the complete list. + * Current MSP driver has the above ones coded. + * */ +struct bus_type i2s_bus_type = { + .name = "i2s", + .dev_attrs = i2s_dev_attrs, + .match = i2s_match_device, + .uevent = i2s_uevent, + .suspend = i2s_suspend, + .resume = i2s_resume, +}; + +EXPORT_SYMBOL_GPL(i2s_bus_type); + +static int i2s_drv_probe(struct device *dev) +{ + const struct i2s_driver *sdrv = to_i2s_driver(dev->driver); + + return sdrv->probe(to_i2s_device(dev)); +} + +static int i2s_drv_remove(struct device *dev) +{ + const struct i2s_driver *sdrv = to_i2s_driver(dev->driver); + + return sdrv->remove(to_i2s_device(dev)); +} + +static void i2s_drv_shutdown(struct device *dev) +{ + const struct i2s_driver *sdrv = to_i2s_driver(dev->driver); + + sdrv->shutdown(to_i2s_device(dev)); +} + +/** + * i2s_register_driver - register a I2S driver + * @sdrv: the driver to register + * Context: can sleep + */ +int i2s_register_driver(struct i2s_driver *sdrv) +{ + sdrv->driver.bus = &i2s_bus_type; + if (sdrv->probe) + sdrv->driver.probe = i2s_drv_probe; + if (sdrv->remove) + sdrv->driver.remove = i2s_drv_remove; + if (sdrv->shutdown) + sdrv->driver.shutdown = i2s_drv_shutdown; + return driver_register(&sdrv->driver); +} + +EXPORT_SYMBOL_GPL(i2s_register_driver); + +/******************************************************************************/ +struct boardinfo { + struct list_head list; + unsigned n_board_info; + struct i2s_board_info board_info[0]; +}; + +static LIST_HEAD(board_list); +static DEFINE_MUTEX(board_lock); + +/* I2S devices should normally not be created by I2S device drivers; that + * would make them board-specific. Similarly with I2S master drivers. + * Device registration normally goes into like arch/.../mach.../board-YYY.c + * with other readonly (flashable) information about mainboard devices. + */ +struct i2s_device *i2s_alloc_device(struct device *device) +{ + struct i2s_device *i2s; + struct device *dev = device->parent; + + get_device(device); + i2s = kzalloc(sizeof *i2s, GFP_KERNEL); + if (!i2s) { + dev_err(dev, "cannot alloc i2s_device\n"); + return NULL; + } + + i2s->dev.parent = dev; + i2s->dev.bus = &i2s_bus_type; + i2s->dev.release = i2sdev_release; + device_initialize(&i2s->dev); + return i2s; +} + +EXPORT_SYMBOL_GPL(i2s_alloc_device); + +/** + * i2s_add_device - Add i2s_device allocated with i2s_alloc_device + * @i2s: i2s_device to register + * + * Companion function to i2s_alloc_device. Devices allocated with + * i2s_alloc_device can be added onto the i2s bus with this function. + * + * Returns 0 on success; negative errno on failure + */ +int i2s_add_device(struct i2s_device *i2s) +{ + static DEFINE_MUTEX(i2s_add_lock); + struct device *dev = i2s->dev.parent; + int status; + + dev_set_name(&i2s->dev, "%s.%u", "i2s", i2s->chip_select); + + mutex_lock(&i2s_add_lock); + + if (bus_find_device_by_name(&i2s_bus_type, NULL, dev_name(&i2s->dev)) + != NULL) { + dev_err(dev, "chipselect %d already in use\n", + i2s->chip_select); + status = -EBUSY; + goto done; + } + + /* Device may be bound to an active driver when this returns */ + status = device_add(&i2s->dev); + if (status < 0) + dev_err(dev, "can't %s %s, status %d\n", + "add", dev_name(&i2s->dev), status); + else + dev_dbg(dev, "registered child %s\n", dev_name(&i2s->dev)); + + done: + mutex_unlock(&i2s_add_lock); + return status; +} + +EXPORT_SYMBOL_GPL(i2s_add_device); + +/** + * i2s_new_device - instantiate one new I2S device + * @i2s_cont: Controller to which device is connected + * @chip: Describes the I2S device + * Context: can sleep + * + * On typical mainboards, this is purely internal; and it's not needed + * after board init creates the hard-wired devices. Some development + * platforms may not be able to use i2s_register_board_info though, and + * this is exported so that driver could add devices (which it would + * learn about out-of-band). + * + * Returns the new device, or NULL. + */ +struct i2s_device *i2s_new_device(struct i2s_controller *i2s_cont, + struct i2s_board_info *chip) +{ + struct i2s_device *proxy; + int status; + + /* NOTE: caller did any chip->bus_num checks necessary. + * + * Also, unless we change the return value convention to use + * error-or-pointer (not NULL-or-pointer), troubleshootability + * suggests syslogged diagnostics are best here (ugh). + */ + + proxy = i2s_alloc_device(&i2s_cont->dev); + if (!proxy) + return NULL; + + WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias)); + + proxy->chip_select = chip->chip_select; + strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias)); + proxy->dev.platform_data = (void *)chip->platform_data; + proxy->controller = i2s_cont; + + status = i2s_add_device(proxy); + if (status < 0) { + kfree(proxy); + return NULL; + } + + return proxy; +} + +EXPORT_SYMBOL_GPL(i2s_new_device); + +/** + * i2s_register_board_info - register I2S devices for a given board + * @info: array of chip descriptors + * @n: how many descriptors are provided + * Context: can sleep + * + * Board-specific early init code calls this (probably during arch_initcall) + * with segments of the I2S device table. Any device nodes are created later, + * after the relevant parent I2S controller (id) is defined. We keep + * this table of devices forever, so that reloading a controller driver will + * not make Linux forget about these hard-wired devices. + * + */ +int __init +i2s_register_board_info(struct i2s_board_info const *info, unsigned n) +{ + struct boardinfo *bi; + + bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL); + if (!bi) + return -ENOMEM; + bi->n_board_info = n; + memcpy(bi->board_info, info, n * sizeof *info); + + mutex_lock(&board_lock); + list_add_tail(&bi->list, &board_list); + mutex_unlock(&board_lock); + return 0; +} + +/** + * scan_boardinfo - Scan, creates and registered new i2s device structure. + * @i2s_cont: i2s controller structure + * Context: process + * + * It will scan the device list that may be registered statically using + * register_board_info func in arch specific directory and call + * i2s_new_device to create and registered i2s device over i2s bus. It is + * called by i2s_add_controller function. + * + * Returns void. + */ +static void scan_boardinfo(struct i2s_controller *i2s_cont) +{ + struct boardinfo *bi; + + mutex_lock(&board_lock); + list_for_each_entry(bi, &board_list, list) { + struct i2s_board_info *chip = bi->board_info; + unsigned n; + + for (n = bi->n_board_info; n > 0; n--, chip++) { + if (chip->id != i2s_cont->id) + continue; + /* NOTE: this relies on i2s_new_device to + * issue diagnostics when given bogus inputs + */ + (void)i2s_new_device(i2s_cont, chip); + } + } + mutex_unlock(&board_lock); +} + +/******************************************************************************/ +/**I2S Controller inittialization*/ +static void i2s_controller_dev_release(struct device *dev) +{ + struct i2s_controller *i2s_cont; + i2s_cont = container_of(dev, struct i2s_controller, dev); + kfree(i2s_cont); +} + +static ssize_t +show_controller_name(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2s_controller *cont = to_i2s_controller(dev); + return sprintf(buf, "%s\n", cont->name); +} + +static struct device_attribute i2s_controller_attrs[] = { + __ATTR(name, S_IRUGO, show_controller_name, NULL), + {}, +}; + +static struct class i2s_controller_class = { + .owner = THIS_MODULE, + .name = "i2s-controller", + .dev_attrs = i2s_controller_attrs, +}; + +static int i2s_register_controller(struct i2s_controller *cont) +{ + int res = 0; + mutex_init(&cont->bus_lock); + + mutex_lock(&core_lock); + + /* Add the controller to the driver core. + * If the parent pointer is not set up, + * we add this controller to the host bus. + */ + if (cont->dev.parent == NULL) { + cont->dev.parent = &platform_bus; + pr_debug("I2S controller driver [%s] forgot to specify " + "physical device\n", cont->name); + } + dev_set_name(&cont->dev, "I2Scrlr-%d", cont->id); + cont->dev.release = &i2s_controller_dev_release; + cont->dev.class = &i2s_controller_class; + res = device_register(&cont->dev); + if (res) + goto out_unlock; + + dev_dbg(&cont->dev, "controller [%s] registered\n", cont->name); + scan_boardinfo(cont); + out_unlock: + mutex_unlock(&core_lock); + return res; +} + +/** + * i2s_add_controller - declare i2s controller, use dynamic bus number + * @controller: the controller to add + * Context: can sleep + * + */ +int i2s_add_controller(struct i2s_controller *controller) +{ + return i2s_register_controller(controller); +} + +EXPORT_SYMBOL(i2s_add_controller); + +static int __unregister(struct device *dev, void *controller_dev) +{ + /* note: before about 2.6.14-rc1 this would corrupt memory: */ + if (dev != controller_dev) + i2s_unregister_device(to_i2s_device(dev)); + return 0; +} + +/** + * i2s_del_controller - unregister I2S controller + * @cont: the controller being unregistered + * Context: can sleep + * + * This unregisters an I2S controller which was previously registered + * by @i2s_add_controller. + */ +int i2s_del_controller(struct i2s_controller *cont) +{ + int res = 0; + int dummy; + mutex_lock(&core_lock); + + dummy = device_for_each_child(cont->dev.parent, &cont->dev, + __unregister); + device_unregister(&cont->dev); + mutex_unlock(&core_lock); + return res; +} + +EXPORT_SYMBOL(i2s_del_controller); + +/******************************************************************************/ +/*I2S interface apis*/ + +/** + * i2s_transfer - Main i2s transfer function. + * @i2s_cont: i2s controller structure passed by client driver. + * @message: i2s message structure contains transceive info. + * Context: process or interrupt. + * + * This API is called by client i2s driver as i2s_xfer funtion. It will handle + * main i2s transfer over i2s bus. The controller should registered its own + * functions using i2s algorithm structure. + * + * Returns error(-1) in case of failure or success(0). + */ +int i2s_transfer(struct i2s_controller *i2s_cont, struct i2s_message *message) +{ + return i2s_cont->algo->cont_transfer(i2s_cont, message); + +} + +EXPORT_SYMBOL(i2s_transfer); + +/** + * i2s_cleanup - Close the current i2s connection btw controller and client. + * @i2s_cont: i2s controller structure + * @flag: It indicates the functionality that needs to be disabled. + * Context: process + * + * This API will disable and reset the controller's configuration. Reset the + * controller so that i2s client driver can reconfigure with new configuration. + * Controller should release all the necessary resources which was acquired + * during setup. + * + * Returns error(-1) in case of failure or success(0). + */ +int i2s_cleanup(struct i2s_controller *i2s_cont, i2s_flag flag) +{ + int status = 0; + status = i2s_cont->algo->cont_cleanup(i2s_cont, flag); + if (status) + return -1; + else + return 0; +} + +EXPORT_SYMBOL(i2s_cleanup); + +/** + * i2s_setup - configures and enables the I2S controller. + * @i2s_cont: i2s controller sent by i2s device. + * @config: specifies the configuration parameters. + * + * This function configures the I2S controller with the client configuration. + * Controller was already registered on I2S bus by some master controller + * driver. + * + * Returns error(-1) in case of failure else success(0) + */ +int i2s_setup(struct i2s_controller *i2s_cont, void *config) +{ + return i2s_cont->algo->cont_setup(i2s_cont, config); +} + +EXPORT_SYMBOL(i2s_setup); + +/** + * i2s_hw_status - Get the current hw status for the i2s controller. + * @i2s_cont: i2s controller structure passed by client driver. + * Context: process or interrupt. + * + * This API is called by client i2s driver to find out current hw status. + * The controller should registered its own functions using i2s algorithm structure. + * + * Returns current hw status register. + */ +int i2s_hw_status(struct i2s_controller *i2s_cont) +{ + return i2s_cont->algo->cont_hw_status(i2s_cont); +} + +/** + * i2s_get_pointer - Get the current dma_addr_t for the i2s controller. + * @i2s_cont: i2s controller structure passed by client driver. + * @i2s_direction: Specifies TX or RX direction. + * Context: process or interrupt. + * + * This API is called by client i2s driver to return a dma_addr_t corresponding + * to the position of the DMA-controller. + * The controller should registered its own functions using i2s algorithm structure. + * + * Returns current hw status register. + */ +dma_addr_t i2s_get_pointer(struct i2s_controller *i2s_cont, + enum i2s_direction_t i2s_direction) +{ + return i2s_cont->algo->cont_get_pointer(i2s_cont, i2s_direction); +} + +/******************************************************************************/ + +static int __init i2s_init(void) +{ + int status; + + status = bus_register(&i2s_bus_type); + if (status < 0) + goto err0; + + status = class_register(&i2s_controller_class); + if (status < 0) + goto err1; + return 0; + + err1: + bus_unregister(&i2s_bus_type); + err0: + return status; +} + +static void __exit i2s_exit(void) +{ + class_unregister(&i2s_controller_class); + bus_unregister(&i2s_bus_type); +} + +subsys_initcall(i2s_init); +module_exit(i2s_exit); + +MODULE_AUTHOR("Sandeep Kaushik, "); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/i2s/i2s_test_protocol_driver.c b/drivers/misc/i2s/i2s_test_protocol_driver.c new file mode 100644 index 00000000000..639a28454f5 --- /dev/null +++ b/drivers/misc/i2s/i2s_test_protocol_driver.c @@ -0,0 +1,305 @@ +/* + * Copyright (C) ST-Ericsson SA 2009 + * Author: Sandeep Kaushik, + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int i2s_drv_offset = 1; + +module_param(i2s_drv_offset, int, 1); +MODULE_PARM_DESC(i2s_drv_offset, "i2s driver to be opened)=(0/1/2/3/4/5)"); + +#define MAX_I2S_CLIENTS 6 + +struct i2sdrv_data { + spinlock_t i2s_lock; + struct i2s_device *i2s; + /* flag to show the device is closed or not */ + bool device_closed; + u32 tx_status; + u32 rx_status; +}; + +static struct i2sdrv_data *i2sdrv[MAX_I2S_CLIENTS]; + +/*API Interface */ +int i2s_testprot_drv_open(int i2s_device_num) +{ + if (!i2sdrv[i2s_device_num]) + return -EINVAL; + + spin_lock_irq(&i2sdrv[i2s_device_num]->i2s_lock); + if (!i2sdrv[i2s_device_num]->device_closed) { + spin_unlock_irq(&i2sdrv[i2s_device_num]->i2s_lock); + return -EBUSY; + } + i2sdrv[i2s_device_num]->device_closed = false; + spin_unlock_irq(&i2sdrv[i2s_device_num]->i2s_lock); + + return 0; +} +EXPORT_SYMBOL(i2s_testprot_drv_open); + +int i2s_config_default_protocol(int i2s_device_num, + struct test_prot_config *config) +{ + return __i2s_testprot_drv_configure(i2s_device_num, config, true); +} +EXPORT_SYMBOL(i2s_config_default_protocol); + +int i2s_testprot_drv_configure(int i2s_device_num, + struct test_prot_config *config) +{ + return __i2s_testprot_drv_configure(i2s_device_num, config, false); +} +EXPORT_SYMBOL(i2s_testprot_drv_configure); + +int __i2s_testprot_drv_configure(int i2s_device_num, + struct test_prot_config *config, bool use_default) +{ + int error_status = 0; + struct i2s_device *i2s_dev; + struct msp_config msp_config = { + .tx_clock_sel = TX_CLK_SEL_SRG, + .rx_clock_sel = 0x0, + .tx_frame_sync_sel = TX_SYNC_SRG_AUTO, + .rx_frame_sync_sel = 0x0, + .input_clock_freq = MSP_INPUT_FREQ_48MHZ, + .srg_clock_sel = SRG_CLK_SEL_APB, + .rx_frame_sync_pol = RX_FIFO_SYNC_HI, + .tx_frame_sync_pol = TX_FIFO_SYNC_HI, + .rx_fifo_config = RX_FIFO_ENABLE, + .tx_fifo_config = TX_FIFO_ENABLE, + .spi_clk_mode = SPI_CLK_MODE_NORMAL, + .tx_data_enable = 0x8000, + .spi_burst_mode = 0, + .loopback_enable = 0x80, + }; + + msp_config.default_protocol_desc = use_default; + + if (!i2sdrv[i2s_device_num]) + return -EINVAL; + + i2s_dev = i2sdrv[i2s_device_num]->i2s; + + if (i2sdrv[i2s_device_num]->device_closed) + return -EINVAL; + + if (!config) + return -EINVAL; + + msp_config.handler = config->handler; + msp_config.tx_callback_data = config->tx_callback_data; + msp_config.rx_callback_data = config->rx_callback_data; + msp_config.frame_freq = config->frame_freq; + msp_config.frame_size = config->frame_size; + msp_config.data_size = config->data_size; + msp_config.direction = config->direction; + msp_config.protocol = config->protocol; + msp_config.work_mode = config->work_mode; + + msp_config.def_elem_len = use_default; + + msp_config.multichannel_configured = 0; + msp_config.protocol_desc = config->protocol_desc; + + msp_config.multichannel_configured = config->multichannel_configured; + msp_config.multichannel_config.tx_multichannel_enable = + config->multichannel_config.tx_multichannel_enable; + /* Channel 1 to 3 */ + msp_config.multichannel_config.tx_channel_0_enable = + config->multichannel_config.tx_channel_0_enable; + /* Channel 33 to 64 */ + msp_config.multichannel_config.tx_channel_1_enable = + config->multichannel_config.tx_channel_1_enable; + /* Channel 65 to 96 */ + msp_config.multichannel_config.tx_channel_2_enable = + config->multichannel_config.tx_channel_2_enable; + /* Channel 97 to 128 */ + msp_config.multichannel_config.tx_channel_3_enable = + config->multichannel_config.tx_channel_3_enable; + msp_config.multichannel_config.rx_multichannel_enable = + config->multichannel_config.rx_multichannel_enable; + /* Channel 1 to 32 */ + msp_config.multichannel_config.rx_channel_0_enable = + config->multichannel_config.rx_channel_0_enable; + /* Channel 33 to 64 */ + msp_config.multichannel_config.rx_channel_1_enable = + config->multichannel_config.rx_channel_1_enable; + /* Channel 65 to 96 */ + msp_config.multichannel_config.rx_channel_2_enable = + config->multichannel_config.rx_channel_2_enable; + /* Channel 97 to 128 */ + msp_config.multichannel_config.rx_channel_3_enable = + config->multichannel_config.rx_channel_3_enable; + msp_config.multichannel_config.rx_comparison_enable_mode = + config->multichannel_config.rx_comparison_enable_mode; + msp_config.multichannel_config.comparison_value = + config->multichannel_config.comparison_value; + msp_config.multichannel_config.comparison_mask = + config->multichannel_config.comparison_mask; + + error_status = + i2s_setup(i2s_dev->controller, &msp_config); + if (error_status < 0) + dev_err(&i2s_dev->dev, "error in msp enable, error_status is %d\n", + error_status); + + return error_status; + +} + +int i2s_testprot_drv_transfer(int i2s_device_num, + void *txdata, size_t txbytes, void *rxdata, size_t rxbytes, + enum i2s_transfer_mode_t transfer_mode) +{ + int bytes_transreceive; + struct i2s_device *i2s_dev; + struct i2s_message message = {}; + + if (!i2sdrv[i2s_device_num]) + return -EINVAL; + + i2s_dev = i2sdrv[i2s_device_num]->i2s; + + if (i2sdrv[i2s_device_num]->device_closed) { + dev_info(&i2s_dev->dev, "msp device not opened yet\n"); + return -EINVAL; + } + + message.i2s_transfer_mode = transfer_mode; + message.i2s_direction = I2S_DIRECTION_BOTH; + message.txbytes = txbytes; + message.txdata = txdata; + message.rxbytes = rxbytes; + message.rxdata = rxdata; + message.dma_flag = 1; + bytes_transreceive = i2s_transfer(i2s_dev->controller, &message); + dev_dbg(&i2s_dev->dev, "bytes transreceived %d\n", bytes_transreceive); + + return bytes_transreceive; +} +EXPORT_SYMBOL(i2s_testprot_drv_transfer); + +int i2s_testprot_drv_close(int i2s_device_num) +{ + int status; + struct i2s_device *i2s_dev; + + if (!i2sdrv[i2s_device_num]) + return -EINVAL; + + i2s_dev = i2sdrv[i2s_device_num]->i2s; + + if (i2sdrv[i2s_device_num]->device_closed) + return -EINVAL; + + status = i2s_cleanup(i2s_dev->controller, DISABLE_ALL); + if (status) + return status; + + /* Mark the device as closed */ + i2sdrv[i2s_device_num]->device_closed = true; + + return 0; +} +EXPORT_SYMBOL(i2s_testprot_drv_close); + +static int i2sdrv_probe(struct i2s_device *i2s) +{ + int status = 0; + + /* Allocate driver data */ + if (!try_module_get(i2s->controller->dev.parent->driver->owner)) + return -ENOENT; + + i2sdrv[i2s->chip_select] = kzalloc(sizeof(*i2sdrv[i2s->chip_select]), + GFP_KERNEL); + + if (!i2sdrv[i2s->chip_select]) + return -ENOMEM; + + /* Initialize the driver data */ + i2sdrv[i2s->chip_select]->i2s = i2s; + i2sdrv[i2s->chip_select]->device_closed = true; + i2sdrv[i2s->chip_select]->tx_status = 0; + i2sdrv[i2s->chip_select]->rx_status = 0; + spin_lock_init(&i2sdrv[i2s->chip_select]->i2s_lock); + + i2s_set_drvdata(i2s, (void *)i2sdrv[i2s->chip_select]); + return status; +} + +static int i2sdrv_remove(struct i2s_device *i2s) +{ + spin_lock_irq(&i2sdrv[i2s->chip_select]->i2s_lock); + i2sdrv[i2s->chip_select]->i2s = NULL; + i2s_set_drvdata(i2s, NULL); + module_put(i2s->controller->dev.parent->driver->owner); + spin_unlock_irq(&i2sdrv[i2s->chip_select]->i2s_lock); + + kfree(i2sdrv[i2s->chip_select]); + + return 0; +} + +static const struct i2s_device_id i2s_test_prot_id_table[] = { + { "i2s_device.0", 0, 0 }, + { "i2s_device.1", 0, 0 }, + { "i2s_device.2", 0, 0 }, + { "i2s_device.3", 0, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2s, i2s_test_prot_id_table); + +static struct i2s_driver i2sdrv_i2s = { + .driver = { + .name = "i2s_test_protocol_driver", + .owner = THIS_MODULE, + }, + .probe = i2sdrv_probe, + .remove = __devexit_p(i2sdrv_remove), + .id_table = i2s_test_prot_id_table, + + /* + * NOTE: suspend/resume methods are not necessary here. + */ +}; + +static int __init i2sdrv_init(void) +{ + int status; + + status = i2s_register_driver(&i2sdrv_i2s); + if (status < 0) + printk(KERN_ERR "Unable to register i2s driver\n"); + + return status; +} +module_init(i2sdrv_init); + +static void __exit i2sdrv_exit(void) +{ + i2s_unregister_driver(&i2sdrv_i2s); +} +module_exit(i2sdrv_exit); + +MODULE_AUTHOR("Sandeep Kaushik, "); +MODULE_DESCRIPTION("Test Driver module I2S device interface"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/i2s/msp_i2s.c b/drivers/misc/i2s/msp_i2s.c new file mode 100644 index 00000000000..e8455e651b7 --- /dev/null +++ b/drivers/misc/i2s/msp_i2s.c @@ -0,0 +1,2045 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#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 + +struct regulator *msp_vape_supply; + +#define STM_MSP_NAME "STM_MSP" +#define MSP_NAME "msp" +#define DRIVER_DEBUG_PFX "MSP" +#define DRIVER_DEBUG CONFIG_STM_MSP_DEBUG +#define DRIVER_DBG "MSP" +#define NMDK_DBG /* message level */ + +extern struct driver_debug_st DBG_ST; + /* Protocol desciptors */ +static const struct msp_protocol_desc protocol_desc_tab[] = { + I2S_PROTOCOL_DESC, + PCM_PROTOCOL_DESC, + PCM_COMPAND_PROTOCOL_DESC, + AC97_PROTOCOL_DESC, + SPI_MASTER_PROTOCOL_DESC, + SPI_SLAVE_PROTOCOL_DESC, +}; + +/* Local static functions */ +static int msp_dma_xfer(struct msp *msp, struct i2s_message *msg); +static int msp_polling_xfer(struct msp *msp, struct i2s_message *msg); +static int msp_interrupt_xfer(struct msp *msp, struct i2s_message *msg); +static int msp_start_dma(struct msp *msp, int transmit, dma_addr_t data, + size_t bytes); +static int configure_protocol(struct msp *msp, + struct msp_config *config); +static int configure_clock(struct msp *msp, + struct msp_config *config); +static int configure_multichannel(struct msp *msp, + struct msp_config *config); +static int stm_msp_configure_enable(struct i2s_controller *i2s_cont, + void *configuration); +static int stm_msp_transceive_data(struct i2s_controller *i2s_cont, + struct i2s_message *message); + +static int stm_msp_disable(struct msp *msp, int direction, + i2s_flag flag); +static int stm_msp_close(struct i2s_controller *i2s_cont, i2s_flag flag); +static int stm_msp_hw_status(struct i2s_controller *i2s_cont); +static dma_addr_t stm_msp_get_pointer(struct i2s_controller *i2s_cont, + enum i2s_direction_t i2s_direction); + +#define I2S_DEVICE "i2s_device" +static struct i2s_algorithm i2s_algo = { + .cont_setup = stm_msp_configure_enable, + .cont_transfer = stm_msp_transceive_data, + .cont_cleanup = stm_msp_close, + .cont_hw_status = stm_msp_hw_status, + .cont_get_pointer = stm_msp_get_pointer, +}; + +/** + * stm_msp_write - writel a value to specified register + * @value: value + * @reg: pointer to register' address + * Context: atomic(can be both process and interrupt) + * Returns void. + */ +static inline void stm_msp_write(u32 value, void __iomem *reg) +{ + writel(value, reg); +} + +/** + * stm_msp_read - readl a value to specified register + * @reg: pointer to register' address + * Context: atomic(can be both process and interrupt) + * Returns u32 register's value. + */ +static inline u32 stm_msp_read(void __iomem *reg) +{ + return readl(reg); +} + +static void u8_msp_read(struct trans_data *xfer_data) +{ + struct i2s_message *message = &xfer_data->message; + while ((message->rx_offset < message->rxbytes) && + !((stm_msp_read(xfer_data->msp->registers + MSP_FLR)) & + RX_FIFO_EMPTY)) { + message->rx_offset += 1; + *(u8 *) message->rxdata = + (u8) stm_msp_read(xfer_data->msp->registers + MSP_DR); + message->rxdata += 1; + } +} + +static void u16_msp_read(struct trans_data *xfer_data) +{ + struct i2s_message *message = &xfer_data->message; + while ((message->rx_offset < message->rxbytes) && + !((stm_msp_read(xfer_data->msp->registers + MSP_FLR)) & + RX_FIFO_EMPTY)) { + message->rx_offset += 2; + *(u16 *) message->rxdata = + (u16) stm_msp_read(xfer_data->msp->registers + MSP_DR); + message->rxdata += 2; + } +} + +/** + * u32_msp_read - Msp 32bit read function. + * @xfer_data: transfer data structure. + * + * It reads 32bit data from msp receive fifo until it gets empty. + * + * Returns void. + */ +static void u32_msp_read(struct trans_data *xfer_data) +{ + struct i2s_message *message = &xfer_data->message; + while ((message->rx_offset < message->rxbytes) && + !((stm_msp_read(xfer_data->msp->registers + MSP_FLR)) & + RX_FIFO_EMPTY)) { + *(u32 *) message->rxdata = + (u32) stm_msp_read(xfer_data->msp->registers + MSP_DR); + message->rx_offset += 4; + message->rxdata += 4; + } +} +static void u8_msp_write(struct trans_data *xfer_data) +{ + struct i2s_message *message = &xfer_data->message; + while ((message->tx_offset < message->txbytes) && + !((stm_msp_read(xfer_data->msp->registers + MSP_FLR)) & + TX_FIFO_FULL)) { + message->tx_offset += 1; + stm_msp_write(*(u8 *) message->txdata, + xfer_data->msp->registers + MSP_DR); + message->txdata += 1; + } +} + +static void u16_msp_write(struct trans_data *xfer_data) +{ + struct i2s_message *message = &xfer_data->message; + while ((message->tx_offset < message->txbytes) && + !((stm_msp_read(xfer_data->msp->registers + MSP_FLR)) & + TX_FIFO_FULL)) { + message->tx_offset += 2; + stm_msp_write(*(u16 *) message->txdata, + xfer_data->msp->registers + MSP_DR); + message->txdata += 2; + } +} + +/** + * u32_msp_write - Msp 32bit write function. + * @xfer_data: transfer data structure. + * + * It writes 32bit data to msp transmit fifo until it gets full. + * + * Returns void. + */ +static void u32_msp_write(struct trans_data *xfer_data) +{ + struct i2s_message *message = &xfer_data->message; + while ((message->tx_offset < message->txbytes) && + !((stm_msp_read(xfer_data->msp->registers + MSP_FLR)) & + TX_FIFO_FULL)) { + message->tx_offset += 4; + stm_msp_write(*(u32 *) message->txdata, + xfer_data->msp->registers + MSP_DR); + message->txdata += 4; + } +} + +/** + * set_transmit_protocol_descriptor - Set the Transmit Configuration register. + * @msp: main msp controller structure. + * @protocol_desc: pointer to protocol descriptor structure. + * @data_size: Run time configurable element length. + * + * It will setup transmit configuration register of msp. + * Various values related to a particular protocol can be set like, elemnet + * length, frame length, endianess etc. + * + * Returns void. + */ +static void set_transmit_protocol_descriptor(struct msp *msp, + struct msp_protocol_desc + *protocol_desc, + enum msp_data_size data_size) +{ + u32 temp_reg = 0; + + temp_reg |= MSP_P2_ENABLE_BIT(protocol_desc->tx_phase_mode); + temp_reg |= MSP_P2_START_MODE_BIT(protocol_desc->tx_phase2_start_mode); + temp_reg |= MSP_P1_FRAME_LEN_BITS(protocol_desc->tx_frame_length_1); + temp_reg |= MSP_P2_FRAME_LEN_BITS(protocol_desc->tx_frame_length_2); + if (msp->def_elem_len) { + temp_reg |= + MSP_P1_ELEM_LEN_BITS(protocol_desc->tx_element_length_1); + temp_reg |= + MSP_P2_ELEM_LEN_BITS(protocol_desc->tx_element_length_2); + if (protocol_desc->tx_element_length_1 == + protocol_desc->tx_element_length_2) { + msp->actual_data_size = + protocol_desc->tx_element_length_1; + } else { + msp->actual_data_size = data_size; + } + } else { + temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size); + temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size); + msp->actual_data_size = data_size; + } + temp_reg |= MSP_DATA_DELAY_BITS(protocol_desc->tx_data_delay); + temp_reg |= + MSP_SET_ENDIANNES_BIT(protocol_desc->tx_bit_transfer_format); + temp_reg |= MSP_FRAME_SYNC_POL(protocol_desc->tx_frame_sync_pol); + temp_reg |= MSP_DATA_WORD_SWAP(protocol_desc->tx_half_word_swap); + temp_reg |= MSP_SET_COMPANDING_MODE(protocol_desc->compression_mode); + temp_reg |= MSP_SET_FRAME_SYNC_IGNORE(protocol_desc->frame_sync_ignore); + + stm_msp_write(temp_reg, msp->registers + MSP_TCF); +} + +/** + * set_receive_protocol_descriptor - Set the Receive Configuration register. + * @msp: main msp controller structure. + * @protocol_desc: pointer to protocol descriptor structure. + * @data_size: Run time configurable element length. + * + * It will setup receive configuration register of msp. + * Various values related to a particular protocol can be set like, elemnet + * length, frame length, endianess etc. + * + * Returns void. + */ +static void set_receive_protocol_descriptor(struct msp *msp, + struct msp_protocol_desc + *protocol_desc, + enum msp_data_size + data_size) +{ + u32 temp_reg = 0; + + temp_reg |= MSP_P2_ENABLE_BIT(protocol_desc->rx_phase_mode); + temp_reg |= MSP_P2_START_MODE_BIT(protocol_desc->rx_phase2_start_mode); + temp_reg |= MSP_P1_FRAME_LEN_BITS(protocol_desc->rx_frame_length_1); + temp_reg |= MSP_P2_FRAME_LEN_BITS(protocol_desc->rx_frame_length_2); + if (msp->def_elem_len) { + temp_reg |= + MSP_P1_ELEM_LEN_BITS(protocol_desc->rx_element_length_1); + temp_reg |= + MSP_P2_ELEM_LEN_BITS(protocol_desc->rx_element_length_2); + if (protocol_desc->rx_element_length_1 == + protocol_desc->rx_element_length_2) { + msp->actual_data_size = + protocol_desc->rx_element_length_1; + } else { + msp->actual_data_size = data_size; + } + } else { + temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size); + temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size); + msp->actual_data_size = data_size; + } + + temp_reg |= MSP_DATA_DELAY_BITS(protocol_desc->rx_data_delay); + temp_reg |= + MSP_SET_ENDIANNES_BIT(protocol_desc->rx_bit_transfer_format); + temp_reg |= MSP_FRAME_SYNC_POL(protocol_desc->rx_frame_sync_pol); + temp_reg |= MSP_DATA_WORD_SWAP(protocol_desc->rx_half_word_swap); + temp_reg |= MSP_SET_COMPANDING_MODE(protocol_desc->expansion_mode); + temp_reg |= MSP_SET_FRAME_SYNC_IGNORE(protocol_desc->frame_sync_ignore); + + stm_msp_write(temp_reg, msp->registers + MSP_RCF); + +} + +/** + * configure_protocol - Configures transmit and receive protocol. + * @msp: main msp controller structure. + * @config: configuration structure passed by client driver + * + * This will configure transmit and receive protocol decriptors. + * + * Returns error(-1) on failure else success(0). + */ +static int configure_protocol(struct msp *msp, + struct msp_config *config) +{ + int direction; + struct msp_protocol_desc *protocol_desc; + enum msp_data_size data_size; + u32 temp_reg = 0; + + data_size = config->data_size; + msp->def_elem_len = config->def_elem_len; + direction = config->direction; + if (config->default_protocol_desc == 1) { + if (config->protocol >= MSP_INVALID_PROTOCOL) { + printk(KERN_ERR + "invalid protocol in configure_protocol()\n"); + return -EINVAL; + } + protocol_desc = + (struct msp_protocol_desc *)&protocol_desc_tab[config-> + protocol]; + } else { + protocol_desc = + (struct msp_protocol_desc *)&config->protocol_desc; + } + + if (data_size < MSP_DATA_BITS_DEFAULT + || data_size > MSP_DATA_BITS_32) { + printk(KERN_ERR + "invalid data size requested in configure_protocol()\n"); + return -EINVAL; + } + + switch (direction) { + case MSP_TRANSMIT_MODE: + set_transmit_protocol_descriptor(msp, protocol_desc, data_size); + break; + case MSP_RECEIVE_MODE: + set_receive_protocol_descriptor(msp, protocol_desc, data_size); + break; + case MSP_BOTH_T_R_MODE: + set_transmit_protocol_descriptor(msp, protocol_desc, data_size); + set_receive_protocol_descriptor(msp, protocol_desc, data_size); + break; + default: + printk(KERN_ERR "Invalid direction given\n"); + return -EINVAL; + } + /* The below code is needed for both Rx and Tx path can't separate + * them. + */ + temp_reg = stm_msp_read(msp->registers + MSP_GCR) & ~TX_CLK_POL_RISING; + temp_reg |= MSP_TX_CLKPOL_BIT(protocol_desc->tx_clock_pol); + stm_msp_write(temp_reg, msp->registers + MSP_GCR); + temp_reg = stm_msp_read(msp->registers + MSP_GCR) & ~RX_CLK_POL_RISING; + temp_reg |= MSP_RX_CLKPOL_BIT(protocol_desc->rx_clock_pol); + stm_msp_write(temp_reg, msp->registers + MSP_GCR); + + return 0; +} + +/** + * configure_clock - Set clock in sample rate generator. + * @msp: main msp controller structure. + * @config: configuration structure passed by client driver + * + * This will set the frame width and period. Also enable sample rate generator + * + * Returns error(-1) on failure else success(0). + */ +static int configure_clock(struct msp *msp, + struct msp_config *config) +{ + + u32 dummy; + u32 frame_per = 0; + u32 sck_div = 0; + u32 frame_width = 0; + u32 temp_reg = 0; + u32 bit_clock = 0; + struct msp_protocol_desc *protocol_desc = NULL; + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) & + (~(SRG_ENABLE))), msp->registers + MSP_GCR); + + if (config->default_protocol_desc) { + protocol_desc = + (struct msp_protocol_desc *)&protocol_desc_tab[config-> + protocol]; + } else { + protocol_desc = + (struct msp_protocol_desc *)&config->protocol_desc; + } + + switch (config->protocol) { + case MSP_PCM_PROTOCOL: + case MSP_PCM_COMPAND_PROTOCOL: + frame_width = protocol_desc->frame_width; + sck_div = + config->input_clock_freq / (config->frame_freq * + (protocol_desc-> + total_clocks_for_one_frame)); + frame_per = protocol_desc->frame_period; + break; + case MSP_I2S_PROTOCOL: + frame_width = protocol_desc->frame_width; + sck_div = + config->input_clock_freq / (config->frame_freq * + (protocol_desc-> + total_clocks_for_one_frame)); + frame_per = protocol_desc->frame_period; + + break; + case MSP_AC97_PROTOCOL: + /* Not supported */ + printk(KERN_WARNING "AC97 protocol not supported\n"); + return -ENOSYS; + default: + printk(KERN_ERR "Invalid mode attempted for setting clocks\n"); + return -EINVAL; + } + + temp_reg = (sck_div - 1) & SCK_DIV_MASK; + temp_reg |= FRAME_WIDTH_BITS(frame_width); + temp_reg |= FRAME_PERIOD_BITS(frame_per); + stm_msp_write(temp_reg, msp->registers + MSP_SRG); + + /* Input clock frequency value configured is in MHz/1000 */ + bit_clock = (config->input_clock_freq * 1000)/(sck_div + 1); + + /* If the bit clock is higher than 19.2MHz, Vape should be run in 100% OPP */ + if (bit_clock > 19200000) { + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "msp_i2s", 100); + msp->vape_opp_constraint = 1; + } else { + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "msp_i2s", 50); + msp->vape_opp_constraint = 0; + } + + /* Wait a bit */ + dummy = ((stm_msp_read(msp->registers + MSP_SRG)) >> FRWID_SHIFT) & 0x0000003F; + + /* Enable clock */ + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | ((SRG_ENABLE))), + msp->registers + MSP_GCR); + + /* Another wait */ + dummy = + ((stm_msp_read(msp->registers + MSP_SRG)) >> FRWID_SHIFT) & + 0x0000003F; + return 0; +} + +/** + * configure_multichannel - Enable multichannel support for transmit & receive. + * @msp: main msp controller structure. + * @config: configuration structure passed by client driver + * + * This will enable multichannel support for transmit and receive. + * It will set Receive comparator also if configured. + * + * Returns error(-1) on failure else success(0). + */ +static int configure_multichannel(struct msp *msp, + struct msp_config *config) +{ + struct msp_protocol_desc *protocol_desc; + struct msp_multichannel_config *mult_config; + if (config->default_protocol_desc == 1) { + if (config->protocol >= MSP_INVALID_PROTOCOL) { + printk(KERN_ERR + "invalid protocol in configure_protocol()\n"); + return -EINVAL; + } + protocol_desc = + (struct msp_protocol_desc *)&protocol_desc_tab[config-> + protocol]; + } else { + protocol_desc = + (struct msp_protocol_desc *)&config->protocol_desc; + } + mult_config = &config->multichannel_config; + if (true == mult_config->tx_multichannel_enable) { + if (MSP_SINGLE_PHASE == protocol_desc->tx_phase_mode) { + stm_msp_write((stm_msp_read(msp->registers + MSP_MCR) | + ((mult_config-> + tx_multichannel_enable << TMCEN_BIT) & + (0x0000020))), + msp->registers + MSP_MCR); + stm_msp_write(mult_config->tx_channel_0_enable, + msp->registers + MSP_TCE0); + stm_msp_write(mult_config->tx_channel_1_enable, + msp->registers + MSP_TCE1); + stm_msp_write(mult_config->tx_channel_2_enable, + msp->registers + MSP_TCE2); + stm_msp_write(mult_config->tx_channel_3_enable, + msp->registers + MSP_TCE3); + } else { + printk(KERN_ERR "Not in authorised mode\n"); + return -1; + } + } + if (true == mult_config->rx_multichannel_enable) { + if (MSP_SINGLE_PHASE == protocol_desc->rx_phase_mode) { + stm_msp_write((stm_msp_read(msp->registers + MSP_MCR) | + ((mult_config-> + rx_multichannel_enable << RMCEN_BIT) & + (0x0000001))), + msp->registers + MSP_MCR); + stm_msp_write(mult_config->rx_channel_0_enable, + msp->registers + MSP_RCE0); + stm_msp_write(mult_config->rx_channel_1_enable, + msp->registers + MSP_RCE1); + stm_msp_write(mult_config->rx_channel_2_enable, + msp->registers + MSP_RCE2); + stm_msp_write(mult_config->rx_channel_3_enable, + msp->registers + MSP_RCE3); + } else { + printk(KERN_ERR "Not in authorised mode\n"); + return -1; + } + if (mult_config->rx_comparison_enable_mode) { + stm_msp_write((stm_msp_read(msp->registers + MSP_MCR) | + ((mult_config-> + rx_comparison_enable_mode << RCMPM_BIT) + & (0x0000018))), + msp->registers + MSP_MCR); + + stm_msp_write(mult_config->comparison_mask, + msp->registers + MSP_RCM); + stm_msp_write(mult_config->comparison_value, + msp->registers + MSP_RCV); + + } + } + return 0; + +} + +/** + * configure_dma - configure dma channel for transmit or receive. + * @msp: msp structure + * @config: configuration structure. + * Context: process + * + * It will configure dma channels and request them in Logical mode for both + * transmit and recevie modes.It also register the respective callback handlers + * for DMA. + * + * Returns void. + */ +void configure_dma(struct msp *msp, struct msp_config *config) +{ + struct stedma40_chan_cfg *rx_dma_info = msp->dma_cfg_rx; + struct stedma40_chan_cfg *tx_dma_info = msp->dma_cfg_tx; + dma_cap_mask_t mask; + + if (config->direction == MSP_TRANSMIT_MODE + || config->direction == MSP_BOTH_T_R_MODE) { + + if (msp->tx_pipeid != NULL) { + dma_release_channel(msp->tx_pipeid); + msp->tx_pipeid = NULL; + } + + if (config->data_size == MSP_DATA_BITS_32) + tx_dma_info->src_info.data_width = STEDMA40_WORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_16) + tx_dma_info->src_info.data_width + = STEDMA40_HALFWORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_8) + tx_dma_info->src_info.data_width + = STEDMA40_BYTE_WIDTH; + else + printk(KERN_ERR "Wrong data size\n"); + + if (config->data_size == MSP_DATA_BITS_32) + tx_dma_info->dst_info.data_width = STEDMA40_WORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_16) + tx_dma_info->dst_info.data_width + = STEDMA40_HALFWORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_8) + tx_dma_info->dst_info.data_width + = STEDMA40_BYTE_WIDTH; + else + printk(KERN_ERR "Wrong data size\n"); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + msp->tx_pipeid = dma_request_channel(mask, stedma40_filter, + tx_dma_info); + } + if (config->direction == MSP_RECEIVE_MODE + || config->direction == MSP_BOTH_T_R_MODE) { + + if (msp->rx_pipeid != NULL) { + dma_release_channel(msp->rx_pipeid); + msp->rx_pipeid = NULL; + } + + if (config->data_size == MSP_DATA_BITS_32) + rx_dma_info->src_info.data_width = STEDMA40_WORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_16) + rx_dma_info->src_info.data_width + = STEDMA40_HALFWORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_8) + rx_dma_info->src_info.data_width = STEDMA40_BYTE_WIDTH; + else + printk(KERN_ERR "Wrong data size\n"); + + if (config->data_size == MSP_DATA_BITS_32) + rx_dma_info->dst_info.data_width = STEDMA40_WORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_16) + rx_dma_info->dst_info.data_width + = STEDMA40_HALFWORD_WIDTH; + else if (config->data_size == MSP_DATA_BITS_8) + rx_dma_info->dst_info.data_width = STEDMA40_BYTE_WIDTH; + else + printk(KERN_ERR "Wrong data size\n"); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + msp->rx_pipeid = dma_request_channel(mask, stedma40_filter, + rx_dma_info); + } + +} + +/** + * msp_enable - Setup the msp configuration. + * @msp: msp data contains main msp structure. + * @config: configuration structure sent by i2s client driver. + * Context: process + * + * Main msp configuring functions to configure msp in accordance with msp + * protocol descriptor, configuring msp clock,setup transfer mode selected by + * user like DMA, interrupt or polling and in the end enable RX and Tx path. + * + * Returns error(-1) in case of failure or success(0). + */ +static int msp_enable(struct msp *msp, struct msp_config *config) +{ + int status = 0; + int state; + + /* Check msp state whether in RUN or CONFIGURED Mode */ + state = msp->msp_state; + if (state == MSP_STATE_IDLE) { + if (msp->plat_init) { + status = msp->plat_init(); + if (status) { + printk(KERN_ERR "Error in msp_i2s_init," + " status is %d\n", status); + return status; + } + } + } + + /* Configure msp with protocol dependent settings */ + configure_protocol(msp, config); + configure_clock(msp, config); + if (config->multichannel_configured == 1) { + status = configure_multichannel(msp, config); + if (status) + printk(KERN_ERR "multichannel can't be configured\n"); + } + msp->work_mode = config->work_mode; + + if (msp->work_mode == MSP_DMA_MODE && !msp->dma_cfg_rx) { + switch (config->direction) { + case MSP_RECEIVE_MODE: + case MSP_BOTH_T_R_MODE: + dev_err(&msp->i2s_cont->dev, "RX DMA not available"); + return -EINVAL; + } + } + + if (msp->work_mode == MSP_DMA_MODE && !msp->dma_cfg_tx) { + switch (config->direction) { + case MSP_TRANSMIT_MODE: + case MSP_BOTH_T_R_MODE: + dev_err(&msp->i2s_cont->dev, "TX DMA not available"); + return -EINVAL; + } + } + + switch (config->direction) { + case MSP_TRANSMIT_MODE: + /*Currently they are ignored + stm_msp_write((stm_msp_read(msp->registers + MSP_IMSC) | + TRANSMIT_UNDERRUN_ERR_INT | + TRANSMIT_FRAME_SYNC_ERR_INT), + msp->registers + MSP_IMSC); */ + if (config->work_mode == MSP_DMA_MODE) { + stm_msp_write(stm_msp_read(msp->registers + MSP_DMACR) | + TX_DMA_ENABLE, + msp->registers + MSP_DMACR); + + msp->xfer_data.tx_handler = config->handler; + msp->xfer_data.tx_callback_data = + config->tx_callback_data; + configure_dma(msp, config); + } + if (config->work_mode == MSP_POLLING_MODE) { + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (TX_ENABLE)), msp->registers + MSP_GCR); + } + if (msp->work_mode != MSP_DMA_MODE) { + switch (msp->actual_data_size) { + case MSP_DATA_BITS_8: + msp->write = u8_msp_write; + break; + case MSP_DATA_BITS_10: + case MSP_DATA_BITS_12: + case MSP_DATA_BITS_14: + case MSP_DATA_BITS_16: + msp->write = u16_msp_write; + break; + case MSP_DATA_BITS_20: + case MSP_DATA_BITS_24: + case MSP_DATA_BITS_32: + default: + msp->write = u32_msp_write; + break; + } + msp->xfer_data.tx_handler = config->handler; + msp->xfer_data.tx_callback_data = + config->tx_callback_data; + msp->xfer_data.rx_callback_data = + config->rx_callback_data; + msp->xfer_data.msp = msp; + } + break; + case MSP_RECEIVE_MODE: + /*Currently they are ignored + stm_msp_write(stm_msp_read(msp->registers + MSP_IMSC) | + RECEIVE_OVERRUN_ERROR_INT | RECEIVE_FRAME_SYNC_ERR_INT, + msp->registers + MSP_IMSC); */ + if (config->work_mode == MSP_DMA_MODE) { + stm_msp_write(stm_msp_read(msp->registers + MSP_DMACR) | + RX_DMA_ENABLE, + msp->registers + MSP_DMACR); + + msp->xfer_data.rx_handler = config->handler; + msp->xfer_data.rx_callback_data = + config->rx_callback_data; + + configure_dma(msp, config); + } + if (config->work_mode == MSP_POLLING_MODE) { + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (RX_ENABLE)), msp->registers + MSP_GCR); + } + if (msp->work_mode != MSP_DMA_MODE) { + switch (msp->actual_data_size) { + case MSP_DATA_BITS_8: + msp->read = u8_msp_read; + break; + case MSP_DATA_BITS_10: + case MSP_DATA_BITS_12: + case MSP_DATA_BITS_14: + case MSP_DATA_BITS_16: + msp->read = u16_msp_read; + break; + case MSP_DATA_BITS_20: + case MSP_DATA_BITS_24: + case MSP_DATA_BITS_32: + default: + msp->read = u32_msp_read; + break; + } + msp->xfer_data.rx_handler = config->handler; + msp->xfer_data.tx_callback_data = + config->tx_callback_data; + msp->xfer_data.rx_callback_data = + config->rx_callback_data; + msp->xfer_data.msp = msp; + } + + break; + case MSP_BOTH_T_R_MODE: + /*Currently they are ignored + stm_msp_write(stm_msp_read(msp->registers + MSP_IMSC) | + RECEIVE_OVERRUN_ERROR_INT | RECEIVE_FRAME_SYNC_ERR_INT | + TRANSMIT_UNDERRUN_ERR_INT | TRANSMIT_FRAME_SYNC_ERR_INT , + msp->registers + MSP_IMSC); */ + if (config->work_mode == MSP_DMA_MODE) { + stm_msp_write(stm_msp_read(msp->registers + MSP_DMACR) | + RX_DMA_ENABLE | TX_DMA_ENABLE, + msp->registers + MSP_DMACR); + + msp->xfer_data.tx_handler = config->handler; + msp->xfer_data.rx_handler = config->handler; + msp->xfer_data.tx_callback_data = + config->tx_callback_data; + msp->xfer_data.rx_callback_data = + config->rx_callback_data; + + configure_dma(msp, config); + } + if (config->work_mode == MSP_POLLING_MODE) { + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (TX_ENABLE)), msp->registers + MSP_GCR); + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (RX_ENABLE)), msp->registers + MSP_GCR); + } + if (msp->work_mode != MSP_DMA_MODE) { + switch (msp->actual_data_size) { + case MSP_DATA_BITS_8: + msp->read = u8_msp_read; + msp->write = u8_msp_write; + break; + case MSP_DATA_BITS_10: + case MSP_DATA_BITS_12: + case MSP_DATA_BITS_14: + case MSP_DATA_BITS_16: + msp->read = u16_msp_read; + msp->write = u16_msp_write; + break; + case MSP_DATA_BITS_20: + case MSP_DATA_BITS_24: + case MSP_DATA_BITS_32: + default: + msp->read = u32_msp_read; + msp->write = u32_msp_write; + break; + } + msp->xfer_data.tx_handler = config->handler; + msp->xfer_data.rx_handler = config->handler; + msp->xfer_data.tx_callback_data = + config->tx_callback_data; + msp->xfer_data.rx_callback_data = + config->rx_callback_data; + msp->xfer_data.msp = msp; + } + + break; + default: + printk(KERN_ERR "Invalid direction parameter\n"); + if (msp->plat_exit) + msp->plat_exit(); + status = -EINVAL; + return status; + } + + switch (config->work_mode) { + case MSP_DMA_MODE: + msp->transfer = msp_dma_xfer; + break; + case MSP_POLLING_MODE: + msp->transfer = msp_polling_xfer; + break; + case MSP_INTERRUPT_MODE: + msp->transfer = msp_interrupt_xfer; + break; + default: + msp->transfer = NULL; + } + + stm_msp_write(config->iodelay, msp->registers + MSP_IODLY); + + /* enable frame generation logic */ + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (FRAME_GEN_ENABLE)), msp->registers + MSP_GCR); + + return status; +} + +/** + * flush_rx_fifo - Flush Rx fifo MSP controller. + * @msp: msp structure. + * + * This function flush the rx fifo of msp controller. + * + * Returns error(-1) in case of failure else success(0) + */ +static void flush_rx_fifo(struct msp *msp) +{ + u32 dummy = 0; + u32 limit = 32; + u32 cur = stm_msp_read(msp->registers + MSP_GCR); + stm_msp_write(cur | RX_ENABLE, msp->registers + MSP_GCR); + while (!(stm_msp_read(msp->registers + MSP_FLR) & RX_FIFO_EMPTY) + && limit--) { + dummy = stm_msp_read(msp->registers + MSP_DR); + } + stm_msp_write(cur, msp->registers + MSP_GCR); +} + +/** + * flush_tx_fifo - Flush Tx fifo MSP controller. + * @msp: msp structure. + * + * This function flush the tx fifo using test intergration register to read data + * from tx fifo directly. + * + * Returns error(-1) in case of failure else success(0) + */ +static void flush_tx_fifo(struct msp *msp) +{ + u32 dummy = 0; + u32 limit = 32; + u32 cur = stm_msp_read(msp->registers + MSP_GCR); + stm_msp_write(cur | TX_ENABLE, msp->registers + MSP_GCR); + stm_msp_write(0x3, msp->registers + MSP_ITCR); + while (!(stm_msp_read(msp->registers + MSP_FLR) & TX_FIFO_EMPTY) + && limit--) { + dummy = stm_msp_read(msp->registers + MSP_TSTDR); + } + stm_msp_write(0x0, msp->registers + MSP_ITCR); + stm_msp_write(cur, msp->registers + MSP_GCR); +} + +/** + * stm_msp_configure_enable - configures and enables the MSP controller. + * @i2s_cont: i2s controller sent by i2s device. + * @configuration: specifies the configuration parameters. + * + * This function configures the msp controller with the client configuration. + * + * Returns error(-1) in case of failure else success(0) + */ +static int stm_msp_configure_enable(struct i2s_controller *i2s_cont, + void *configuration) +{ + u32 old_reg; + u32 new_reg; + u32 mask; + int res; + struct msp_config *config = + (struct msp_config *)configuration; + struct msp *msp = (struct msp *)i2s_cont->data; + + if (in_interrupt()) { + printk(KERN_ERR + "can't call configure_enable in interrupt context\n"); + return -1; + } + + /* Two simultanous configuring msp is avoidable */ + down(&msp->lock); + switch (msp->users) { + case 0: + res = regulator_enable(msp_vape_supply); + if (res != 0) { + dev_err(&msp->i2s_cont->dev, + "Failed to enable regulator\n"); + up(&msp->lock); + return res; + } + + clk_enable(msp->clk); + msp->direction = config->direction; + break; + case 1: + if (msp->direction == MSP_BOTH_T_R_MODE || + config->direction == msp->direction || + config->direction == MSP_BOTH_T_R_MODE) { + dev_notice(&i2s_cont->dev, "%s: MSP in use in the " + "desired direction.\n", __func__); + up(&msp->lock); + return -EBUSY; + } + msp->direction = MSP_BOTH_T_R_MODE; + break; + default: + dev_notice(&i2s_cont->dev, "%s: MSP in use in both " + "directions.\n", __func__); + up(&msp->lock); + return -EBUSY; + } + msp->users++; + + /* First do the global config register */ + mask = + RX_CLK_SEL_MASK | TX_CLK_SEL_MASK | RX_FRAME_SYNC_MASK | + TX_FRAME_SYNC_MASK | RX_SYNC_SEL_MASK | TX_SYNC_SEL_MASK | + RX_FIFO_ENABLE_MASK | TX_FIFO_ENABLE_MASK | SRG_CLK_SEL_MASK | + LOOPBACK_MASK | TX_EXTRA_DELAY_MASK; + + new_reg = + (config->tx_clock_sel | config->rx_clock_sel | config-> + rx_frame_sync_pol | config->tx_frame_sync_pol | config-> + rx_frame_sync_sel | config->tx_frame_sync_sel | config-> + rx_fifo_config | config->tx_fifo_config | config-> + srg_clock_sel | config->loopback_enable | config->tx_data_enable); + + old_reg = stm_msp_read(msp->registers + MSP_GCR); + old_reg &= ~mask; + new_reg |= old_reg; + stm_msp_write(new_reg, msp->registers + MSP_GCR); + + if (msp_enable(msp, config) != 0) { + printk(KERN_ERR "error enabling MSP\n"); + return -EBUSY; + } + if (config->loopback_enable & 0x80) + msp->loopback_enable = 1; + /*Sometimes FIFO doesn't gets empty hence limit is provided */ + flush_tx_fifo(msp); + /*This has been added in order to fix fifo flush problem + When last xfer occurs some data remains in fifo. In order to + flush that data delay is needed */ + msleep(10); + /* wait for fifo to flush */ + flush_rx_fifo(msp); + + /* RX_BUSY take a while to clear */ + msleep(10); + + msp->msp_state = MSP_STATE_CONFIGURED; + up(&msp->lock); + return 0; +} + +static int msp_start_dma(struct msp *msp, int transmit, dma_addr_t data, + size_t bytes) +{ + struct dma_async_tx_descriptor *desc; + struct scatterlist sg; + + sg_init_table(&sg, 1); + sg_set_page(&sg, pfn_to_page(PFN_DOWN(data)), bytes, + offset_in_page(data)); + sg_dma_address(&sg) = data; + sg_dma_len(&sg) = bytes; + + if (transmit) { + if (!msp->tx_pipeid) + return -EINVAL; + + desc = msp->tx_pipeid->device-> + device_prep_slave_sg(msp->tx_pipeid, + &sg, 1, DMA_TO_DEVICE, + DMA_PREP_INTERRUPT + | DMA_CTRL_ACK); + if (!desc) + return -ENOMEM; + + desc->callback = msp->xfer_data.tx_handler; + desc->callback_param = msp->xfer_data.tx_callback_data; + desc->tx_submit(desc); + dma_async_issue_pending(msp->tx_pipeid); + } else { + if (!msp->rx_pipeid) + return -EINVAL; + + desc = msp->rx_pipeid->device-> + device_prep_slave_sg(msp->rx_pipeid, + &sg, 1, DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT + | DMA_CTRL_ACK); + if (!desc) + return -EBUSY; + + desc->callback = msp->xfer_data.rx_handler; + desc->callback_param = msp->xfer_data.rx_callback_data; + desc->tx_submit(desc); + dma_async_issue_pending(msp->rx_pipeid); + } + + return 0; +} + +static int msp_single_dma_tx(struct msp *msp, dma_addr_t data, size_t bytes) +{ + int status; + status = msp_start_dma(msp, 1, data, bytes); + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | (TX_ENABLE)), + msp->registers + MSP_GCR); + return status; +} + +static int msp_single_dma_rx(struct msp *msp, dma_addr_t data, size_t bytes) +{ + int status; + status = msp_start_dma(msp, 0, data, bytes); + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | (RX_ENABLE)), + msp->registers + MSP_GCR); + return status; +} + +static void msp_cyclic_dma_start(struct msp *msp, + struct scatterlist *sg, + int sg_len, + enum dma_data_direction direction) +{ + struct stedma40_cyclic_desc *cdesc; + int ret; + struct dma_chan *pipeid = (direction == DMA_TO_DEVICE) ? + msp->tx_pipeid : + msp->rx_pipeid; + + cdesc = stedma40_cyclic_prep_sg(pipeid, + sg, + sg_len, + direction, + DMA_PREP_INTERRUPT); + if (IS_ERR(cdesc)) { + pr_err("%s: Error: stedma40_cyclic_prep_sg failed (%ld)!\n", + __func__, + PTR_ERR(cdesc)); + return; + } + + cdesc->period_callback = (direction == DMA_TO_DEVICE) ? + msp->xfer_data.tx_handler : + msp->xfer_data.rx_handler; + cdesc->period_callback_param = (direction == DMA_TO_DEVICE) ? + msp->xfer_data.tx_callback_data : + msp->xfer_data.rx_callback_data; + + ret = stedma40_cyclic_start(pipeid); + if (ret) { + pr_err("%s: stedma40_cyclic_start failed (%d)!\n", __func__, ret); + goto free; + } + + msp->infinite = true; + + return; + +free: + stedma40_cyclic_free(pipeid); +} + +/* Legacy function. Used by HATS driver. */ +static void msp_loopback_inf_start_dma(struct msp *msp, + dma_addr_t data, + size_t bytes) +{ + struct stedma40_cyclic_desc *rxcdesc; + struct stedma40_cyclic_desc *txcdesc; + struct scatterlist rxsg[2]; + struct scatterlist txsg[2]; + size_t len = bytes >> 1; + int ret; + + sg_init_table(rxsg, ARRAY_SIZE(rxsg)); + sg_init_table(txsg, ARRAY_SIZE(txsg)); + + sg_dma_len(&rxsg[0]) = len; + sg_dma_len(&rxsg[1]) = len; + sg_dma_len(&txsg[0]) = len; + sg_dma_len(&txsg[1]) = len; + + sg_dma_address(&rxsg[0]) = data; + sg_dma_address(&rxsg[1]) = data + len; + + sg_dma_address(&txsg[0]) = data + len; + sg_dma_address(&txsg[1]) = data; + + rxcdesc = stedma40_cyclic_prep_sg(msp->rx_pipeid, + rxsg, ARRAY_SIZE(rxsg), + DMA_FROM_DEVICE, 0); + if (IS_ERR(rxcdesc)) + return; + + txcdesc = stedma40_cyclic_prep_sg(msp->tx_pipeid, + txsg, ARRAY_SIZE(txsg), + DMA_TO_DEVICE, 0); + if (IS_ERR(txcdesc)) + goto free_rx; + + ret = stedma40_cyclic_start(msp->rx_pipeid); + if (ret) + goto free_tx; + + ret = stedma40_cyclic_start(msp->tx_pipeid); + if (ret) + goto stop_rx; + + msp->infinite = true; + + return; + +stop_rx: + stedma40_cyclic_stop(msp->rx_pipeid); +free_tx: + stedma40_cyclic_free(msp->tx_pipeid); +free_rx: + stedma40_cyclic_free(msp->rx_pipeid); +} + +/** + * msp_dma_xfer - Handles DMA transfers over i2s bus. + * @msp: main msp structure. + * @msg: i2s_message contains info about transmit and receive data. + * Context: process + * + * This will first check whether data buffer is dmaable or not. + * Call dma_map_single apis etc to make it dmaable dma. Starts the dma transfer + * for TX and RX parallely and wait for it to get completed. + * + * Returns error(-1) in case of failure or success(0). + */ +static int msp_dma_xfer(struct msp *msp, struct i2s_message *msg) +{ + int status = 0; + + switch (msg->i2s_transfer_mode) { + default: + case I2S_TRANSFER_MODE_SINGLE_DMA: + if (msg->i2s_direction == I2S_DIRECTION_TX || + msg->i2s_direction == I2S_DIRECTION_BOTH) + if (msg->txdata && (msg->txbytes > 0)) { + if (!msg->dma_flag) + msg->txdata = + (void *)dma_map_single(NULL, + msg->txdata, + msg->txbytes, + DMA_TO_DEVICE); + status = msp_single_dma_tx(msp, + (dma_addr_t)msg->txdata, + msg->txbytes); + } + if (msg->i2s_direction == I2S_DIRECTION_RX || + msg->i2s_direction == I2S_DIRECTION_BOTH) + if (msg->rxdata && (msg->rxbytes > 0)) { + if (!msg->dma_flag) + msg->rxdata = + (void *)dma_map_single(NULL, + msg->rxdata, + msg->rxbytes, + DMA_FROM_DEVICE + ); + status = msp_single_dma_rx(msp, + (dma_addr_t)msg->rxdata, + msg->rxbytes); + } + break; + + case I2S_TRANSFER_MODE_CYCLIC_DMA: + if (msg->i2s_direction == I2S_DIRECTION_TX) { + msp_cyclic_dma_start(msp, + msg->sg, + msg->sg_len, + DMA_TO_DEVICE); + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (TX_ENABLE)), + msp->registers + MSP_GCR); + } else { + msp_cyclic_dma_start(msp, + msg->sg, + msg->sg_len, + DMA_FROM_DEVICE); + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (RX_ENABLE)), + msp->registers + MSP_GCR); + } + break; + + case I2S_TRANSFER_MODE_INF_LOOPBACK: + msp_loopback_inf_start_dma(msp, + (dma_addr_t)msg->rxdata, + msg->rxbytes); + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (RX_ENABLE)), + msp->registers + MSP_GCR); + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (TX_ENABLE)), + msp->registers + MSP_GCR); + break; + } + + return status; +} + +#if 0 +/** + * msp_handle_irq - Interrupt handler routine. + * @irq: irq no. + * @dev_id: device structure registered in request irq. + * + * Returns error(-1) on failure else success(0). + */ +static irqreturn_t msp_handle_irq(int irq, void *dev_id) +{ + u32 irq_status; + struct msp *msp = (struct msp *)dev_id; + struct i2s_message *message = &msp->xfer_data.message; + u32 irq_mask = 0; + irq_status = stm_msp_read(msp->registers + MSP_MIS); + irq_mask = stm_msp_read(msp->registers + MSP_IMSC); +/* Disable the interrupt to prevent immediate recurrence */ + stm_msp_write(stm_msp_read(msp->registers + MSP_IMSC) & ~irq_status, + msp->registers + MSP_IMSC); + +/* Clear the interrupt */ + stm_msp_write(irq_status, msp->registers + MSP_ICR); +/* Check for an error condition */ + msp->msp_io_error = irq_status & (RECEIVE_OVERRUN_ERROR_INT | + RECEIVE_FRAME_SYNC_ERR_INT | + TRANSMIT_UNDERRUN_ERR_INT | + TRANSMIT_FRAME_SYNC_ERR_INT); + + /*Currently they are ignored */ + if (irq_status & RECEIVE_OVERRUN_ERROR_INT) + ; + if (irq_status & TRANSMIT_UNDERRUN_ERR_INT) + ; + + /* This code has been added basically to support loopback mode + * Basically Transmit interrupt is not disabled even after its + * completion so that receive fifo gets an additional interrupt + */ + if (irq_mask & (RECEIVE_SERVICE_INT) + && (irq_mask & (TRANSMIT_SERVICE_INT)) && (msp->loopback_enable)) { + if (msp->read) + msp->read(&msp->xfer_data); + if (msp->write) + msp->write(&msp->xfer_data); + if (message->rx_offset >= message->rxbytes) { + if (msp->xfer_data.rx_handler) + msp->xfer_data.rx_handler(msp-> + xfer_data. + rx_callback_data, + message->rx_offset); + msp->xfer_data.rx_handler = NULL; + return IRQ_HANDLED; + } + + if (message->tx_offset >= message->txbytes) { + if (msp->xfer_data.tx_handler) + msp->xfer_data.tx_handler(msp->xfer_data. + tx_callback_data, + message->tx_offset); + msp->xfer_data.tx_handler = NULL; + } + stm_msp_write(irq_mask, msp->registers + MSP_IMSC); + return IRQ_HANDLED; + } + + if (irq_status & RECEIVE_SERVICE_INT) { + if (msp->read) + msp->read(&msp->xfer_data); + if (message->rx_offset >= message->rxbytes) { + irq_mask &= ~RECEIVE_SERVICE_INT; + stm_msp_write(irq_mask, msp->registers + MSP_IMSC); + if (msp->xfer_data.rx_handler) + msp->xfer_data.rx_handler(msp-> + xfer_data. + rx_callback_data, + message->rx_offset); + if (!(irq_status & TRANSMIT_SERVICE_INT)) + return IRQ_HANDLED; + } + } + if (irq_status & TRANSMIT_SERVICE_INT) { + if (msp->write) + msp->write(&msp->xfer_data); + if (message->tx_offset >= message->txbytes) { + irq_mask &= ~TRANSMIT_SERVICE_INT; + stm_msp_write(irq_mask, msp->registers + MSP_IMSC); + if (msp->xfer_data.tx_handler) + msp->xfer_data.tx_handler(msp->xfer_data. + tx_callback_data, + message->tx_offset); + return IRQ_HANDLED; + } + } + stm_msp_write(irq_mask, msp->registers + MSP_IMSC); + return IRQ_HANDLED; + +} +#endif + +/** + * msp_interrupt_xfer - Handles Interrupt transfers over i2s bus. + * @msp: main msp structure. + * @msg: i2s_message contains info about transmit and receive data. + * Context: Process or interrupt. + * + * This implements transfer and receive functions used in interrupt mode. + * This can be used in interrupt context if a callback handler is registered + * by client driver. This has been to improve performance in interrupt mode. + * Hence can't use sleep in this function. + * + * Returns error(-1) in case of failure or success(0). + */ +static int msp_interrupt_xfer(struct msp *msp, struct i2s_message *msg) +{ + struct i2s_message *message; + u32 irq_mask = 0; + + if (msg->i2s_transfer_mode != I2S_TRANSFER_MODE_NON_DMA) + return -EINVAL; + + if (msg->txbytes) { + msp->xfer_data.message.txbytes = msg->txbytes; + msp->xfer_data.message.txdata = msg->txdata; + msp->xfer_data.message.tx_offset = 0; + } + if (msg->rxbytes) { + msp->xfer_data.message.rxbytes = msg->rxbytes; + msp->xfer_data.message.rxdata = msg->rxdata; + msp->xfer_data.message.rx_offset = 0; + } + message = &msp->xfer_data.message; + if ((message->txdata == NULL || message->txbytes == 0) + && (message->rxdata == NULL || message->rxbytes == 0)) { + printk(KERN_ERR + "transmit_receive_data is NULL with bytes > 0\n"); + return -EINVAL; + } + + msp->msp_io_error = 0; + + if (message->tx_offset < message->txbytes) { + irq_mask |= TRANSMIT_SERVICE_INT; + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (TX_ENABLE)), msp->registers + MSP_GCR); + } + if (message->rx_offset < message->rxbytes) { + irq_mask |= RECEIVE_SERVICE_INT; + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (RX_ENABLE)), msp->registers + MSP_GCR); + } + stm_msp_write((stm_msp_read(msp->registers + MSP_IMSC) | + irq_mask), msp->registers + MSP_IMSC); + return 0; +} + +/** + * func_notify_timer - Handles Polling hang issue over i2s bus. + * @data: main msp data address + * Context: Interrupt. + * + * This is used to handle error condition in transfer and receive function used + * in polling mode. + * Sometimes due to passing wrong protocol desc , polling transfer may hang. + * To prevent this, timer is added. + * + * Returns void. + */ +static void func_notify_timer(unsigned long data) +{ + struct msp *msp = (struct msp *)data; + if (msp->polling_flag) { + msp->msp_io_error = 1; + printk(KERN_ERR + "Polling is taking two much time, may be it got hang\n"); + del_timer(&msp->notify_timer); + } +} + +/** + * msp_polling_xfer - Handles Polling transfers over i2s bus. + * @msp: main msp structure. + * @msg: i2s_message contains info about transmit and receive data. + * Context: Process. + * + * This implements transfer and receive functions used in polling mode. This is + * blocking fucntion. + * It is recommended to use interrupt or dma mode for better performance rather + * than the polling mode. + * + * Returns error(-1) in case of failure or success(0). + */ +static int msp_polling_xfer(struct msp *msp, struct i2s_message *msg) +{ + struct i2s_message *message; + u32 time_expire = 0; + u32 tr_ex = 0, rr_ex = 0; + u32 msec_jiffies = 0; + + if (msg->i2s_transfer_mode != I2S_TRANSFER_MODE_NON_DMA) + return -EINVAL; + + if (msg->txbytes) { + msp->xfer_data.message.txbytes = msg->txbytes; + msp->xfer_data.message.txdata = msg->txdata; + msp->xfer_data.message.tx_offset = 0; + tr_ex = msg->txbytes; + } + if (msg->rxbytes) { + msp->xfer_data.message.rxbytes = msg->rxbytes; + msp->xfer_data.message.rxdata = msg->rxdata; + msp->xfer_data.message.rx_offset = 0; + rr_ex = msg->rxbytes; + } + message = &msp->xfer_data.message; + time_expire = (tr_ex + rr_ex) / 1024; + if (!time_expire) + msec_jiffies = 500; + else + msec_jiffies = time_expire * 500; + msp->notify_timer.expires = jiffies + msecs_to_jiffies(msec_jiffies); + down(&msp->lock); + if (message->txdata == NULL && message->txbytes > 0) { + printk(KERN_ERR + "transmit_receive_data is NULL with bytes > 0\n"); + return -EINVAL; + } + + if (message->rxdata == NULL && message->rxbytes > 0) { + printk(KERN_ERR + "transmit_receive_data is NULL with bytes > 0\n"); + return -EINVAL; + } + msp->msp_io_error = 0; + msp->polling_flag = 1; + add_timer(&msp->notify_timer); + while (message->tx_offset < message->txbytes + || message->rx_offset < message->rxbytes) { + if (msp->msp_io_error) + break; + if (msp->read) + msp->read(&msp->xfer_data); + if (msp->write) + msp->write(&msp->xfer_data); + } + msp->polling_flag = 0; + del_timer(&msp->notify_timer); + up(&msp->lock); + return message->txbytes + message->rxbytes; +} + +/** + * stm_msp_transceive_data - Main i2s transfer function. + * @i2s_cont: i2s controller structure passed by client driver. + * @message: i2s message structure contains transceive info. + * Context: process or interrupt. + * + * This function is registered over i2s_xfer funtions. It will handle main i2s + * transfer over i2s bus in various modes.It call msp transfer function on which + * suitable transfer function is already registered i.e dma ,interrupt or + * polling function. + * + * Returns error(-1) in case of failure or success(0). + */ +static int stm_msp_transceive_data(struct i2s_controller *i2s_cont, + struct i2s_message *message) +{ + int status = 0; + struct msp *msp = (struct msp *)i2s_cont->data; + + if (!message || (msp->msp_state == MSP_STATE_IDLE)) { + printk(KERN_ERR "Message is NULL\n"); + return -EPERM; + } + + msp->msp_state = MSP_STATE_RUN; + if (msp->transfer) + status = msp->transfer(msp, message); + + if (msp->msp_state == MSP_STATE_RUN) + msp->msp_state = MSP_STATE_CONFIGURED; + + return status; +} + +/** + * msp_disable_receive - Disable receive functionality. + * @msp: main msp structure. + * Context: process. + * + * This function will disable msp controller's receive functionality like dma, + * interrupt receive data buffer all are disabled. + * + * Returns void. + */ +static void msp_disable_receive(struct msp *msp) +{ + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) & + (~RX_ENABLE)), msp->registers + MSP_GCR); + stm_msp_write((stm_msp_read(msp->registers + MSP_DMACR) & + (~RX_DMA_ENABLE)), msp->registers + MSP_DMACR); + stm_msp_write((stm_msp_read(msp->registers + MSP_IMSC) & + (~ + (RECEIVE_SERVICE_INT | + RECEIVE_OVERRUN_ERROR_INT))), + msp->registers + MSP_IMSC); + msp->xfer_data.message.rxbytes = 0; + msp->xfer_data.message.rx_offset = 0; + msp->xfer_data.message.rxdata = NULL; + msp->read = NULL; + +} + +/** + * msp_disable_transmit - Disable transmit functionality. + * @msp: main msp structure. + * Context: process. + * + * This function will disable msp controller's transmit functionality like dma, + * interrupt transmit data buffer all are disabled. + * + * Returns void. + */ +static void msp_disable_transmit(struct msp *msp) +{ + + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) & + (~TX_ENABLE)), msp->registers + MSP_GCR); + stm_msp_write((stm_msp_read(msp->registers + MSP_DMACR) & + (~TX_DMA_ENABLE)), msp->registers + MSP_DMACR); + stm_msp_write((stm_msp_read(msp->registers + MSP_IMSC) & + (~ + (TRANSMIT_SERVICE_INT | + TRANSMIT_UNDERRUN_ERR_INT))), + msp->registers + MSP_IMSC); + msp->xfer_data.message.txbytes = 0; + msp->xfer_data.message.tx_offset = 0; + msp->xfer_data.message.txdata = NULL; + msp->write = NULL; + +} + +/** + * stm_msp_disable - disable the given msp controller + * @msp: specifies the msp contoller data + * @direction: specifies the transmit/receive direction + * @flag: It indicates the functionality that needs to be disabled. + * + * Returns error(-1) in case of failure else success(0) + */ +static int stm_msp_disable(struct msp *msp, int direction, i2s_flag flag) +{ + int limit = 32; + u32 dummy = 0; + int status = 0; + if (! + (stm_msp_read(msp->registers + MSP_GCR) & + ((TX_ENABLE | RX_ENABLE)))) { + return 0; + } + if (msp->work_mode == MSP_DMA_MODE) { + if (flag == DISABLE_ALL || flag == DISABLE_TRANSMIT) { + if (msp->tx_pipeid != NULL) { + if (msp->infinite) { + stedma40_cyclic_stop(msp->tx_pipeid); + stedma40_cyclic_free(msp->tx_pipeid); + } + msp->tx_pipeid->device-> + device_control(msp->tx_pipeid, + DMA_TERMINATE_ALL, 0); + dma_release_channel(msp->tx_pipeid); + msp->tx_pipeid = NULL; + } + } + if ((flag == DISABLE_ALL || flag == DISABLE_RECEIVE)) { + if (msp->rx_pipeid != NULL) { + if (msp->infinite) { + stedma40_cyclic_stop(msp->rx_pipeid); + stedma40_cyclic_free(msp->rx_pipeid); + } + + msp->rx_pipeid->device-> + device_control(msp->rx_pipeid, + DMA_TERMINATE_ALL, 0); + dma_release_channel(msp->rx_pipeid); + msp->rx_pipeid = NULL; + } + } + + msp->infinite = false; + } + if (flag == DISABLE_TRANSMIT) + msp_disable_transmit(msp); + else if (flag == DISABLE_RECEIVE) + msp_disable_receive(msp); + else { + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) | + (LOOPBACK_MASK)), msp->registers + MSP_GCR); + /* Flush Tx fifo */ + while ((! + (stm_msp_read(msp->registers + MSP_FLR) & + TX_FIFO_EMPTY)) && limit--) + dummy = stm_msp_read(msp->registers + MSP_DR); + + /* Disable Transmit channel */ + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) & + (~TX_ENABLE)), msp->registers + MSP_GCR); + limit = 32; + /* Flush Rx Fifo */ + while ((! + (stm_msp_read(msp->registers + MSP_FLR) & + RX_FIFO_EMPTY)) && limit--) + dummy = stm_msp_read(msp->registers + MSP_DR); + /* Disable Loopback and Receive channel */ + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) & + (~(RX_ENABLE | LOOPBACK_MASK))), + msp->registers + MSP_GCR); + /*This has been added in order to fix fifo flush problem + When last xfer occurs some data remains in fifo. In order to + flush that data delay is needed */ + msleep(10); + msp_disable_transmit(msp); + msp_disable_receive(msp); + + } + + /* disable sample rate and frame generators */ + if (flag == DISABLE_ALL) { + msp->msp_state = MSP_STATE_IDLE; + stm_msp_write((stm_msp_read(msp->registers + MSP_GCR) & + (~(FRAME_GEN_ENABLE | SRG_ENABLE))), + msp->registers + MSP_GCR); + memset(&msp->xfer_data, 0, sizeof(struct trans_data)); + if (msp->plat_exit) + status = msp->plat_exit(); + if (status) + printk(KERN_ERR "Error in msp_i2s_exit\n"); + if (msp->work_mode == MSP_POLLING_MODE + && msp->msp_state == MSP_STATE_RUN) { + up(&msp->lock); + } + msp->transfer = NULL; + stm_msp_write(0, msp->registers + MSP_GCR); + stm_msp_write(0, msp->registers + MSP_TCF); + stm_msp_write(0, msp->registers + MSP_RCF); + stm_msp_write(0, msp->registers + MSP_DMACR); + stm_msp_write(0, msp->registers + MSP_SRG); + stm_msp_write(0, msp->registers + MSP_MCR); + stm_msp_write(0, msp->registers + MSP_RCM); + stm_msp_write(0, msp->registers + MSP_RCV); + stm_msp_write(0, msp->registers + MSP_TCE0); + stm_msp_write(0, msp->registers + MSP_TCE1); + stm_msp_write(0, msp->registers + MSP_TCE2); + stm_msp_write(0, msp->registers + MSP_TCE3); + stm_msp_write(0, msp->registers + MSP_RCE0); + stm_msp_write(0, msp->registers + MSP_RCE1); + stm_msp_write(0, msp->registers + MSP_RCE2); + stm_msp_write(0, msp->registers + MSP_RCE3); + } + return status; +} + +/** + * stm_msp_close - Close the current i2s connection btw controller and client. + * @i2s_cont: i2s controller structure + * @flag: It indicates the functionality that needs to be disabled. + * Context: process + * + * It will call msp_disable and reset the msp configuration. Disables Rx and Tx + * channels, free gpio irqs and interrupt pins. + * Called by i2s client driver to indicate the completion of use of i2s bus. + * It is registered on i2s_close function. + * + * Returns error(-1) in case of failure or success(0). + */ +static int stm_msp_close(struct i2s_controller *i2s_cont, i2s_flag flag) +{ + int status = 0; + struct msp *msp = (struct msp *)i2s_cont->data; + down(&msp->lock); + if (msp->users == 0) { + pr_err("MSP already closed!\n"); + status = -EINVAL; + goto end; + } + dev_dbg(&i2s_cont->dev, "%s: users = %d, flag = %d.\n", + __func__, msp->users, flag); + /* We need to call it twice for DISABLE_ALL*/ + msp->users = flag == DISABLE_ALL ? 0 : msp->users - 1; + if (msp->users) + status = stm_msp_disable(msp, MSP_BOTH_T_R_MODE, flag); + else { + status = stm_msp_disable(msp, MSP_BOTH_T_R_MODE, DISABLE_ALL); + clk_disable(msp->clk); + status = regulator_disable(msp_vape_supply); + if (status != 0) { + dev_err(&msp->i2s_cont->dev, + "Failed to disable regulator\n"); + clk_enable(msp->clk); + goto end; + } + } + if (status) + goto end; + if (msp->users) + msp->direction = flag == DISABLE_TRANSMIT ? + MSP_RECEIVE_MODE : MSP_TRANSMIT_MODE; + + if (msp->vape_opp_constraint == 1) { + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "msp_i2s", 50); + msp->vape_opp_constraint = 0; + } +end: + up(&msp->lock); + return status; + +} + +static int stm_msp_hw_status(struct i2s_controller *i2s_cont) +{ + struct msp *msp = (struct msp *)i2s_cont->data; + + int status = stm_msp_read(msp->registers + MSP_RIS) & 0xee; + if (status) + stm_msp_write(status, msp->registers + MSP_ICR); + + return status; +} + +static dma_addr_t stm_msp_get_pointer(struct i2s_controller *i2s_cont, + enum i2s_direction_t i2s_direction) +{ + struct msp *msp = (struct msp *)i2s_cont->data; + return (i2s_direction == I2S_DIRECTION_TX) ? + stedma40_get_src_addr(msp->tx_pipeid) : + stedma40_get_dst_addr(msp->rx_pipeid); +} + + /*Platform driver's functions */ +/** + * msp_probe - Probe function + * @pdev: platform device structure. + * Context: process + * + * Probe function of msp platform driver.Handles allocation of memory and irq + * resource. It creates i2s_controller and one i2s_device per msp controller. + * + * Returns error(-1) in case of failure or success(0). + */ +int msp_probe(struct platform_device *pdev) +{ + int status = 0; + struct device *dev; + s16 platform_num = 0; + struct resource *res = NULL; + int irq; + struct i2s_controller *i2s_cont; + struct msp_i2s_platform_data *platform_data; + struct msp *msp; + + if (!pdev) + return -EPERM; + msp = kzalloc(sizeof(*msp), GFP_KERNEL); + + platform_data = (struct msp_i2s_platform_data *)pdev->dev.platform_data; + + msp->id = platform_data->id; + msp->plat_init = platform_data->msp_i2s_init; + msp->plat_exit = platform_data->msp_i2s_exit; + + msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; + msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; + + dev = &pdev->dev; + platform_num = msp->id - 1; + + sema_init(&msp->lock, 1); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "probe - MEM resources not defined\n"); + status = -EINVAL; + goto free_msp; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + status = -EINVAL; + goto free_msp; + } + msp->irq = irq; + + msp->registers = ioremap(res->start, (res->end - res->start + 1)); + if (msp->registers == NULL) { + status = -EINVAL; + goto free_msp; + } + + msp_vape_supply = regulator_get(NULL, "v-ape"); + if (IS_ERR(msp_vape_supply)) { + status = PTR_ERR(msp_vape_supply); + printk(KERN_WARNING "msp i2s : failed to get v-ape supply\n"); + goto free_irq; + } + prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, "msp_i2s", 50); + msp->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(msp->clk)) { + status = PTR_ERR(msp->clk); + goto free_irq; + } + + init_timer(&msp->notify_timer); + msp->notify_timer.expires = jiffies + msecs_to_jiffies(1000); + msp->notify_timer.function = func_notify_timer; + msp->notify_timer.data = (unsigned long)msp; + + msp->rx_pipeid = NULL; + msp->tx_pipeid = NULL; + msp->read = NULL; + msp->write = NULL; + msp->transfer = NULL; + msp->msp_state = MSP_STATE_IDLE; + msp->loopback_enable = 0; + + dev_set_drvdata(&pdev->dev, msp); + /* I2S Controller is allocated and added in I2S controller class. */ + i2s_cont = + (struct i2s_controller *)kzalloc(sizeof(*i2s_cont), GFP_KERNEL); + if (!i2s_cont) { + dev_err(&pdev->dev, "i2s controller alloc failed \n"); + status = -EINVAL; + goto del_timer; + } + i2s_cont->dev.parent = dev; + i2s_cont->algo = &i2s_algo; + i2s_cont->data = (void *)msp; + i2s_cont->id = platform_num; + snprintf(i2s_cont->name, sizeof(i2s_cont->name), + "MSP_I2S.%04x", platform_num); + + status = i2s_add_controller(i2s_cont); + if (status) { + dev_err(&pdev->dev, "i2s add controller failed (%d)\n", status); + goto free_cont; + } + msp->i2s_cont = i2s_cont; + return status; +free_cont: + kfree(msp->i2s_cont); +del_timer: + del_timer_sync(&msp->notify_timer); + clk_put(msp->clk); +free_irq: + iounmap(msp->registers); +free_msp: + kfree(msp); + return status; +} + +/** + * msp_remove - remove function + * @pdev: platform device structure. + * Context: process + * + * remove function of msp platform driver.Handles dellocation of memory and irq + * resource. It deletes i2s_controller and one i2s_device per msp controller + * created in msp_probe. + * + * Returns error(-1) in case of failure or success(0). + */ +static int msp_remove(struct platform_device *pdev) +{ + struct msp *msp = + (struct msp *)dev_get_drvdata(&pdev->dev); + int status = 0; + i2s_del_controller(msp->i2s_cont); + del_timer_sync(&msp->notify_timer); + clk_put(msp->clk); + iounmap(msp->registers); + prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "msp_i2s"); + regulator_put(msp_vape_supply); + kfree(msp); + return status; +} +#ifdef CONFIG_PM +/** + * msp_suspend - MSP suspend function registered with PM framework. + * @pdev: Reference to platform device structure of the device + * @state: power mgmt state. + * + * This function is invoked when the system is going into sleep, called + * by the power management framework of the linux kernel. + * Nothing is required as controller is configured with every transfer. + * It is assumed that no active tranfer is in progress at this time. + * Client driver should make sure of this. + * + */ + +int msp_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct msp *msp = + (struct msp *)dev_get_drvdata(&pdev->dev); + + down(&msp->lock); + if (msp->users > 0) { + up(&msp->lock); + return -EBUSY; + } + up(&msp->lock); + + return 0; +} +/** + * msp_resume - MSP Resume function registered with PM framework. + * @pdev: Reference to platform device structure of the device + * + * This function is invoked when the system is coming out of sleep, called + * by the power management framework of the linux kernel. + * Nothing is required. + * + */ + +int msp_resume(struct platform_device *pdev) +{ + return 0; +} +#else +#define msp_suspend NULL +#define msp_resume NULL +#endif + +static struct platform_driver msp_i2s_driver = { + .probe = msp_probe, + .remove = msp_remove, + .suspend = msp_suspend, + .resume = msp_resume, + .driver = { + .owner = THIS_MODULE, + .name = "MSP_I2S", + }, +}; + +static int __init stm_msp_mod_init(void) +{ + return platform_driver_register(&msp_i2s_driver); +} + +static void __exit stm_msp_exit(void) +{ + platform_driver_unregister(&msp_i2s_driver); + return; +} + +module_init(stm_msp_mod_init); +module_exit(stm_msp_exit); + +MODULE_AUTHOR("Sandeep Kaushik"); +MODULE_DESCRIPTION("STM MSP driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/i2s/msp_i2s.h b/drivers/misc/i2s/msp_i2s.h new file mode 100644 index 00000000000..2ac86e7700e --- /dev/null +++ b/drivers/misc/i2s/msp_i2s.h @@ -0,0 +1,362 @@ +/*----------------------------------------------------------------------------------*/ +/* copyright STMicroelectronics, 2007. */ +/* */ +/* This program is free software; you can redistribute it and/or modify it under */ +/* the terms of the GNU General Public License as published by the Free */ +/* Software Foundation; either version 2.1 of the License, or (at your option) */ +/* any later version. */ +/* */ +/* 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. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see . */ +/*----------------------------------------------------------------------------------*/ + + +#ifndef STM_MSP_HEADER +#define STM_MSP_HEADER + +#define MSP_DR 0x00 +#define MSP_GCR 0x04 +#define MSP_TCF 0x08 +#define MSP_RCF 0x0c +#define MSP_SRG 0x10 +#define MSP_FLR 0x14 +#define MSP_DMACR 0x18 + +#define MSP_IMSC 0x20 +#define MSP_RI 0x24 +#define MSP_MIS 0x28 +#define MSP_ICR 0x2c +#define MSP_MCR 0x30 +#define MSP_RCV 0x34 +#define MSP_RCM 0x38 + +#define MSP_TCE0 0x40 +#define MSP_TCE1 0x44 +#define MSP_TCE2 0x48 +#define MSP_TCE3 0x4c + +#define MSP_RCE0 0x60 +#define MSP_RCE1 0x64 +#define MSP_RCE2 0x68 +#define MSP_RCE3 0x6c + +#define MSP_ITCR 0x80 +#define MSP_ITIP 0x84 +#define MSP_ITOP 0x88 +#define MSP_TSTDR 0x8c + +#define MSP_PID0 0xfe0 +#define MSP_PID1 0xfe4 +#define MSP_PID2 0xfe8 +#define MSP_PID3 0xfec + +#define MSP_CID0 0xff0 +#define MSP_CID1 0xff4 +#define MSP_CID2 0xff8 +#define MSP_CID3 0xffc + + +/* Single or dual phase mode */ +enum +{ + MSP_SINGLE_PHASE, + MSP_DUAL_PHASE +}; + + +/* Transmit/Receive shifter status +-----------------------------------*/ +enum +{ + MSP_SxHIFTER_IDLE = 0, + MSP_SHIFTER_WORKING = 1 +}; + + +/* Transmit/Receive FIFO status +---------------------------------*/ +enum +{ + MSP_FIFO_FULL, + MSP_FIFO_PART_FILLED, + MSP_FIFO_EMPTY +}; + + +/* Frame length +------------------*/ +enum +{ + MSP_FRAME_LENGTH_1 = 0, + MSP_FRAME_LENGTH_2 = 1, + MSP_FRAME_LENGTH_4 = 3, + MSP_FRAME_LENGTH_8 = 7, + MSP_FRAME_LENGTH_12 = 11, + MSP_FRAME_LENGTH_16 = 15, + MSP_FRAME_LENGTH_20 = 19, + MSP_FRAME_LENGTH_32 = 31, + MSP_FRAME_LENGTH_48 = 47, + MSP_FRAME_LENGTH_64 = 63 +}; + +/* Element length */ +enum +{ + MSP_ELEM_LENGTH_8 = 0, + MSP_ELEM_LENGTH_10 = 1, + MSP_ELEM_LENGTH_12 = 2, + MSP_ELEM_LENGTH_14 = 3, + MSP_ELEM_LENGTH_16 = 4, + MSP_ELEM_LENGTH_20 = 5, + MSP_ELEM_LENGTH_24 = 6, + MSP_ELEM_LENGTH_32 = 7 +}; + + +/* Data delay (in bit clock cycles) +---------------------------------------*/ +enum +{ + MSP_DELAY_0 = 0, + MSP_DELAY_1 = 1, + MSP_DELAY_2 = 2, + MSP_DELAY_3 = 3 +}; + + +/* Configurations of clocks (transmit, receive or sample rate generator) +-------------------------------------------------------------------------*/ +enum +{ + MSP_RISING_EDGE = 0, + MSP_FALLING_EDGE = 1 +}; + +/* Protocol dependant parameters list */ +struct msp_protocol_desc +{ + u32 phase_mode; + u32 frame_len_1; + u32 frame_len_2; + u32 element_len_1; + u32 element_len_2; + u32 data_delay; + u32 tx_clock_edge; + u32 rx_clock_edge; +}; +#define RX_ENABLE_MASK 0x00000001 +#define RX_FIFO_ENABLE_MASK 0x00000002 +#define RX_FRAME_SYNC_MASK 0x00000004 +#define DIRECT_COMPANDING_MASK 0x00000008 +#define RX_SYNC_SEL_MASK 0x00000010 +#define RX_CLK_POL_MASK 0x00000020 +#define RX_CLK_SEL_MASK 0x00000040 +#define LOOPBACK_MASK 0x00000080 +#define TX_ENABLE_MASK 0x00000100 +#define TX_FIFO_ENABLE_MASK 0x00000200 +#define TX_FRAME_SYNC_MASK 0x00000400 +#define TX_MSP_TDR_TSR 0x00000800 +#define TX_SYNC_SEL_MASK 0x00001800 +#define TX_CLK_POL_MASK 0x00002000 +#define TX_CLK_SEL_MASK 0x00004000 +#define TX_EXTRA_DELAY_MASK 0x00008000 +#define SRG_ENABLE_MASK 0x00010000 +#define SRG_CLK_POL_MASK 0x00020000 +#define SRG_CLK_SEL_MASK 0x000C0000 +#define FRAME_GEN_EN_MASK 0x00100000 +#define SPI_CLK_MODE_MASK 0x00600000 +#define SPI_BURST_MODE_MASK 0x00800000 + +#define RXEN_BIT 0 +#define RFFEN_BIT 1 +#define RFSPOL_BIT 2 +#define DCM_BIT 3 +#define RFSSEL_BIT 4 +#define RCKPOL_BIT 5 +#define RCKSEL_BIT 6 +#define LBM_BIT 7 +#define TXEN_BIT 8 +#define TFFEN_BIT 9 +#define TFSPOL_BIT 10 +#define TFSSEL_BIT 11 +#define TCKPOL_BIT 13 +#define TCKSEL_BIT 14 +#define TXDDL_BIT 15 +#define SGEN_BIT 16 +#define SCKPOL_BIT 17 +#define SCKSEL_BIT 18 +#define FGEN_BIT 20 +#define SPICKM_BIT 21 + +#define msp_rx_clkpol_bit(n) ((n & 1) << RCKPOL_BIT) +#define msp_tx_clkpol_bit(n) ((n & 1) << TCKPOL_BIT) +#define msp_spi_clk_mode_bits(n) ((n & 3) << SPICKM_BIT) + + +/* Use this to clear the clock mode bits to non-spi */ +#define MSP_NON_SPI_CLK_MASK 0x00600000 + +#define P1ELEN_BIT 0 +#define P1FLEN_BIT 3 +#define DTYP_BIT 10 +#define ENDN_BIT 12 +#define DDLY_BIT 13 +#define FSIG_BIT 15 +#define P2ELEN_BIT 16 +#define P2FLEN_BIT 19 +#define P2SM_BIT 26 +#define P2EN_BIT 27 + +#define msp_p1_elem_len_bits(n) (n & 0x00000007) +#define msp_p2_elem_len_bits(n) (((n) << P2ELEN_BIT) & 0x00070000) +#define msp_p1_frame_len_bits(n) (((n) << P1FLEN_BIT) & 0x00000378) +#define msp_p2_frame_len_bits(n) (((n) << P2FLEN_BIT) & 0x03780000) +#define msp_data_delay_bits(n) (((n) << DDLY_BIT) & 0x00003000) +#define msp_data_type_bits(n) (((n) << DTYP_BIT) & 0x00000600) +#define msp_p2_start_mode_bit(n) (n << P2SM_BIT) +#define msp_p2_enable_bit(n) (n << P2EN_BIT) + +/* Flag register +--------------------*/ +#define RX_BUSY 0x00000001 +#define RX_FIFO_EMPTY 0x00000002 +#define RX_FIFO_FULL 0x00000004 +#define TX_BUSY 0x00000008 +#define TX_FIFO_EMPTY 0x00000010 +#define TX_FIFO_FULL 0x00000020 + +#define RBUSY_BIT 0 +#define RFE_BIT 1 +#define RFU_BIT 2 +#define TBUSY_BIT 3 +#define TFE_BIT 4 +#define TFU_BIT 5 + +/* Multichannel control register +---------------------------------*/ +#define RMCEN_BIT 0 +#define RMCSF_BIT 1 +#define RCMPM_BIT 3 +#define TMCEN_BIT 5 +#define TNCSF_BIT 6 + +/* Sample rate generator register +------------------------------------*/ +#define SCKDIV_BIT 0 +#define FRWID_BIT 10 +#define FRPER_BIT 16 + +#define SCK_DIV_MASK 0x0000003FF +#define frame_width_bits(n) (((n) << FRWID_BIT) &0x0000FC00) +#define frame_period_bits(n) (((n) << FRPER_BIT) &0x1FFF0000) + + +/* DMA controller register +---------------------------*/ +#define RX_DMA_ENABLE 0x00000001 +#define TX_DMA_ENABLE 0x00000002 + +#define RDMAE_BIT 0 +#define TDMAE_BIT 1 + +/*Interrupt Register +-----------------------------------------*/ +#define RECEIVE_SERVICE_INT 0x00000001 +#define RECEIVE_OVERRUN_ERROR_INT 0x00000002 +#define RECEIVE_FRAME_SYNC_ERR_INT 0x00000004 +#define RECEIVE_FRAME_SYNC_INT 0x00000008 +#define TRANSMIT_SERVICE_INT 0x00000010 +#define TRANSMIT_UNDERRUN_ERR_INT 0x00000020 +#define TRANSMIT_FRAME_SYNC_ERR_INT 0x00000040 +#define TRANSMIT_FRAME_SYNC_INT 0x00000080 +#define ALL_INT 0x000000ff + +/* Protocol configuration values +* I2S: Single phase, 16 bits, 2 words per frame +-----------------------------------------------*/ +#define I2S_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_32, \ + MSP_ELEM_LENGTH_32, \ + MSP_DELAY_1, \ + MSP_FALLING_EDGE, \ + MSP_FALLING_EDGE \ +} + +#define PCM_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_16, \ + MSP_DATA_DELAY, \ + MSP_TX_CLOCK_EDGE, \ + MSP_RX_CLOCK_EDGE \ +} + +/* Companded PCM: Single phase, 8 bits, 1 word per frame +--------------------------------------------------------*/ +#define PCM_COMPAND_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_0, \ + MSP_RISING_EDGE, \ + MSP_FALLING_EDGE \ +} + +/* AC97: Double phase, 1 element of 16 bits during first phase, +* 12 elements of 20 bits in second phase. +--------------------------------------------------------------*/ +#define AC97_PROTOCOL_DESC \ +{ \ + MSP_DUAL_PHASE, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_12, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_20, \ + MSP_DELAY_1, \ + MSP_RISING_EDGE, \ + MSP_FALLING_EDGE \ +} + +#define SPI_MASTER_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_1, \ + MSP_FALLING_EDGE, \ + MSP_RISING_EDGE \ +} +#define SPI_SLAVE_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_1, \ + MSP_FALLING_EDGE, \ + MSP_RISING_EDGE \ +} + +#define MSP_FRAME_PERIOD_IN_MONO_MODE 256 +#define MSP_FRAME_PERIOD_IN_STEREO_MODE 32 +#define MSP_FRAME_WIDTH_IN_STEREO_MODE 16 + +#endif + diff --git a/include/linux/i2s/i2s.h b/include/linux/i2s/i2s.h new file mode 100644 index 00000000000..b67fdb2d80d --- /dev/null +++ b/include/linux/i2s/i2s.h @@ -0,0 +1,225 @@ +/*----------------------------------------------------------------------------*/ +/* copyright STMicroelectronics, 2007. */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the Free */ +/* Software Foundation; either version 2.1 of the License, or (at your option)*/ +/* any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY */ +/* or FITNES */ +/* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more */ +/* details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see . */ +/*----------------------------------------------------------------------------*/ + +#ifndef __LINUX_I2S_H +#define __LINUX_I2S_H + +/* + * INTERFACES between I2S controller-side drivers and I2S infrastructure. + */ +extern struct bus_type i2s_bus_type; +#define I2S_NAME_SIZE 48 +/** + * struct i2s_device - Controller side proxy for an I2S slave device + * @dev: Driver model representation of the device. + * @controller: I2S controller used with the device. + * @chip_select: Chipselect, distinguishing chips handled by @controller. + * @modalias: Name of the driver to use with this device, or an alias + * for that name. This appears in the sysfs "modalias" attribute + * for driver coldplugging, and in uevents used for hotplugging + * + * A @i2s_device is used to interchange data between an I2S slave + * + * In @dev, the platform_data is used to hold information about this + * device that's meaningful to the device's protocol driver, but not + * to its controller. + */ +struct i2s_device { + struct device dev; + struct i2s_controller *controller; + u8 chip_select; + char modalias[32]; +}; +struct i2s_board_info { + /* the device name and module name are coupled, like platform_bus; + * "modalias" is normally the driver name. + * + * platform_data goes to i2s_device.dev.platform_data, + */ + char modalias[32]; + const void *platform_data; + u16 id; + u16 chip_select; +}; + +#ifdef CONFIG_STM_I2S +extern int +i2s_register_board_info(struct i2s_board_info const *info, unsigned n); +#else +/* board init code may ignore whether I2S is configured or not */ +static inline int +i2s_register_board_info(struct i2s_board_info const *info, unsigned n) +{ + return 0; +} +#endif + +static inline struct i2s_device *to_i2s_device(struct device *dev) +{ + return dev ? container_of(dev, struct i2s_device, dev) : NULL; +} + +static inline struct i2s_device *i2s_dev_get(struct i2s_device *i2s) +{ + return (i2s && get_device(&i2s->dev)) ? i2s : NULL; +} + +static inline void i2s_dev_put(struct i2s_device *i2s) +{ + if (i2s) + put_device(&i2s->dev); +} + +static inline void i2s_set_drvdata(struct i2s_device *i2s, void *data) +{ + dev_set_drvdata(&i2s->dev, data); +} + +static inline void *i2s_get_drvdata(struct i2s_device *i2s) +{ + return dev_get_drvdata(&i2s->dev); +} + +struct i2s_device_id { + char name[I2S_NAME_SIZE]; + /*currently not used may be used in future */ + u32 device_id; + u32 vendor_id; +}; + +/** + * struct i2s_driver - Host side "protocol" driver + */ +struct i2s_driver { + int (*probe) (struct i2s_device *i2s); + int (*remove) (struct i2s_device *i2s); + void (*shutdown) (struct i2s_device *i2s); + int (*suspend) (struct i2s_device *i2s, pm_message_t mesg); + int (*resume) (struct i2s_device *i2s); + struct device_driver driver; + const struct i2s_device_id *id_table; + +}; + +static inline struct i2s_driver *to_i2s_driver(struct device_driver *drv) +{ + return drv ? container_of(drv, struct i2s_driver, driver) : NULL; +} + +extern int i2s_register_driver(struct i2s_driver *sdrv); + +/** + * i2s_unregister_driver - reverse effect of i2s_register_driver + * @sdrv: the driver to unregister + * Context: can sleep + */ +static inline void i2s_unregister_driver(struct i2s_driver *sdrv) +{ + if (sdrv) + driver_unregister(&sdrv->driver); +} + +/**I2S controller parameters*/ + +enum i2s_direction_t { + I2S_DIRECTION_TX = 0, + I2S_DIRECTION_RX = 1, + I2S_DIRECTION_BOTH = 2 +}; + +enum i2s_transfer_mode_t { + I2S_TRANSFER_MODE_SINGLE_DMA = 0, + I2S_TRANSFER_MODE_CYCLIC_DMA = 1, + I2S_TRANSFER_MODE_INF_LOOPBACK = 2, + I2S_TRANSFER_MODE_NON_DMA = 4, +}; + +struct i2s_message { + enum i2s_transfer_mode_t i2s_transfer_mode; + enum i2s_direction_t i2s_direction; + void *txdata; + void *rxdata; + size_t txbytes; + size_t rxbytes; + int dma_flag; + int tx_offset; + int rx_offset; + bool cyclic_dma; + struct scatterlist *sg; + int sg_len; +}; + +typedef enum { + DISABLE_ALL = 0, + DISABLE_TRANSMIT = 1, + DISABLE_RECEIVE = 2, +} i2s_flag; + +struct i2s_algorithm { + int (*cont_setup) (struct i2s_controller *i2s_cont, void *config); + int (*cont_transfer) (struct i2s_controller *i2s_cont, + struct i2s_message *message); + int (*cont_cleanup) (struct i2s_controller *i2s_cont, i2s_flag flag); + int (*cont_hw_status) (struct i2s_controller *i2s_cont); + dma_addr_t (*cont_get_pointer) (struct i2s_controller *i2s_cont, + enum i2s_direction_t i2s_direction); +}; + +struct i2s_controller { + struct module *owner; + unsigned int id; + unsigned int class; + const struct i2s_algorithm *algo; /* the algorithm to access the bus */ + void *data; + struct mutex bus_lock; + struct device dev; /* the controller device */ + char name[48]; +}; +#define to_i2s_controller(d) container_of(d, struct i2s_controller, dev) + +static inline void *i2s_get_contdata(struct i2s_controller *dev) +{ + return dev_get_drvdata(&dev->dev); +} + +static inline void i2s_set_contdata(struct i2s_controller *dev, void *data) +{ + dev_set_drvdata(&dev->dev, data); +} + +extern int i2s_add_controller(struct i2s_controller *controller); +extern int i2s_del_controller(struct i2s_controller *controller); +extern int i2s_setup(struct i2s_controller *i2s_cont, void *config); +extern int i2s_transfer(struct i2s_controller *i2s_cont, + struct i2s_message *message); +extern int i2s_cleanup(struct i2s_controller *i2s_cont, i2s_flag flag); +extern int i2s_hw_status(struct i2s_controller *i2s_cont); +extern dma_addr_t i2s_get_pointer(struct i2s_controller *i2s_cont, + enum i2s_direction_t i2s_direction); + +extern struct i2s_device *i2s_alloc_device(struct device *dev); + +extern int i2s_add_device(struct i2s_device *i2s); + +static inline void i2s_unregister_device(struct i2s_device *i2s) +{ + if (i2s) + device_unregister(&i2s->dev); +} + +#endif /* __LINUX_I2S_H */ diff --git a/include/linux/i2s/i2s_test_prot.h b/include/linux/i2s/i2s_test_prot.h new file mode 100644 index 00000000000..003d0e6e3ab --- /dev/null +++ b/include/linux/i2s/i2s_test_prot.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __I2S_TEST_PROT_DRIVER_IF_H__ +#define __I2S_TEST_PROT_DRIVER_IF_H__ +#include +struct test_prot_config { + u32 tx_config_desc; + u32 rx_config_desc; + u32 frame_freq; + u32 frame_size; + u32 data_size; + u32 direction; + u32 protocol; + u32 work_mode; + struct msp_protocol_desc protocol_desc; + void (*handler) (void *data); + void *tx_callback_data; + void *rx_callback_data; + int multichannel_configured; + struct msp_multichannel_config multichannel_config; +}; + +int i2s_testprot_drv_open(int i2s_device_num); +int i2s_testprot_drv_configure(int i2s_device_num, + struct test_prot_config *config); +int i2s_config_default_protocol(int i2s_device_num, + struct test_prot_config *config); +int __i2s_testprot_drv_configure(int i2s_device_num, + struct test_prot_config *config, + bool use_default); +int i2s_testprot_drv_transfer(int i2s_device_num, void *txdata, size_t txbytes, + void *rxdata, size_t rxbytes, + enum i2s_transfer_mode_t transfer_mode); +int i2s_testprot_drv_close(int i2s_device_num); + +#endif -- cgit v1.2.3 From 0b7be4cf79c48e5617c878cf4c4197ff0325ae3a Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Fri, 18 Mar 2011 14:57:19 +0100 Subject: spi: add stm msp driver Signed-off-by: Robert Marklund --- Documentation/DocBook/msp.tmpl | 104 ++ arch/arm/mach-ux500/include/mach/msp.h | 970 ++++++++++++++++ drivers/spi/Kconfig | 14 + drivers/spi/Makefile | 1 + drivers/spi/stm_msp.c | 1929 ++++++++++++++++++++++++++++++++ include/linux/spi/stm_msp.h | 126 +++ 6 files changed, 3144 insertions(+) create mode 100644 Documentation/DocBook/msp.tmpl create mode 100644 arch/arm/mach-ux500/include/mach/msp.h create mode 100644 drivers/spi/stm_msp.c create mode 100644 include/linux/spi/stm_msp.h diff --git a/Documentation/DocBook/msp.tmpl b/Documentation/DocBook/msp.tmpl new file mode 100644 index 00000000000..55cec352a76 --- /dev/null +++ b/Documentation/DocBook/msp.tmpl @@ -0,0 +1,104 @@ + + + + + + MSP + + + + Sandeep + Kaushik + +
+ sandeep.kaushik@st.com +
+
+
+
+ + + 2008-2009 + STMicroelectronics Pvt Ltd + + + + + Linux standard functions + + + + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + 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. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + Introduction + + This Documentation describes the API's provided by the MSP controller Driver. + MSP controller supports different protocols like I2S, PCM, SPI etc. + + + + + Known Bugs And Assumptions + + + + None + + + None. + + + + + + + + + Public Functions Provided + + Not Applicable. + + + + + Private Functions + + This Section lists the functions used by the MSP controller driver. + These functions cater to all the protocols supported namely: I2S, PCM, SPI. + +!Idrivers/misc/i2s/msp_i2s.c + +
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h new file mode 100644 index 00000000000..aecca3a59a3 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/msp.h @@ -0,0 +1,970 @@ +/* + * Copyright (c) 2009 STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +#ifndef _STM_MSP_HEADER +#define _STM_MSP_HEADER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Generic config struct. Use the actual values defined below for global + * control register + */ + +enum msp_state { + MSP_STATE_IDLE = 0, + MSP_STATE_CONFIGURED = 1, + MSP_STATE_RUN = 2, +}; + +enum msp_rx_comparison_enable_mode { + MSP_COMPARISON_DISABLED = 0, + MSP_COMPARISON_NONEQUAL_ENABLED = 2, + MSP_COMPARISON_EQUAL_ENABLED = 3 +}; + +#define RMCEN_BIT 0 +#define RMCSF_BIT 1 +#define RCMPM_BIT 3 +#define TMCEN_BIT 5 +#define TNCSF_BIT 6 + +struct msp_multichannel_config { + bool rx_multichannel_enable; + bool tx_multichannel_enable; + enum msp_rx_comparison_enable_mode rx_comparison_enable_mode; + u8 padding; + u32 comparison_value; + u32 comparison_mask; + u32 rx_channel_0_enable; + u32 rx_channel_1_enable; + u32 rx_channel_2_enable; + u32 rx_channel_3_enable; + u32 tx_channel_0_enable; + u32 tx_channel_1_enable; + u32 tx_channel_2_enable; + u32 tx_channel_3_enable; +}; + +/** + * struct msp_protocol_desc- MSP Protocol desc structure per MSP. + * @rx_phase_mode: rx_phase_mode whether single or dual. + * @tx_phase_mode: tx_phase_mode whether single or dual. + * @rx_phase2_start_mode: rx_phase2_start_mode whether imediate or after + * some delay. + * @tx_phase2_start_mode: tx_phase2_start_mode whether imediate or after + * some delay. + * @rx_bit_transfer_format: MSP or LSB. + * @tx_bit_transfer_format: MSP or LSB. + * @rx_frame_length_1: Frame1 length 1,2,3.. + * @rx_frame_length_2: Frame2 length 1,2,3.. + * @tx_frame_length_1: Frame1 length 1,2,3.. + * @tx_frame_length_2: Frame2 length 1,2,3.. + * @rx_element_length_1: Element1 length 1,2,... + * @rx_element_length_2: Element2 length 1,2,... + * @tx_element_length_1: Element1 length 1,2,... + * @tx_element_length_2: Element2 length 1,2,... + * @rx_data_delay: Delay in clk cycle after frame sync + * @tx_data_delay: Delay in clk cycle after frame sync + * @rx_clock_pol: Rxpol whether rising or falling.It indicates pol of bit clock. + * @tx_clock_pol: Txpol whether rising or falling.It indicates pol of bit clock. + * @rx_frame_sync_pol: Frame sync pol whether rising or Falling. + * @tx_frame_sync_pol: Frame sync pol whether rising or Falling. + * @rx_half_word_swap: Word swap half word, full word. + * @tx_half_word_swap: Word swap half word, full word. + * @compression_mode: Compression mode whether Alaw or Ulaw or disabled. + * @expansion_mode: Compression mode whether Alaw or Ulaw or disabled. + * @spi_clk_mode: Spi clock mode to be enabled or not. + * @spi_burst_mode: Spi burst mode to be enabled or not. + * @frame_sync_ignore: Frame sync to be ignored or not. Ignore in case of Audio + * codec acting as Master. + * @frame_period: Frame period (clk cycles) after which new frame sync occurs. + * @frame_width: Frame width (clk cycles) after which frame sycn changes state. + * @total_clocks_for_one_frame: No. of clk cycles per frame. + * + * Main Msp protocol descriptor data structure to be used to store various info + * in transmit or recevie configuration registers of an MSP. + */ + +struct msp_protocol_desc { + u32 rx_phase_mode; + u32 tx_phase_mode; + u32 rx_phase2_start_mode; + u32 tx_phase2_start_mode; + u32 rx_bit_transfer_format; + u32 tx_bit_transfer_format; + u32 rx_frame_length_1; + u32 rx_frame_length_2; + u32 tx_frame_length_1; + u32 tx_frame_length_2; + u32 rx_element_length_1; + u32 rx_element_length_2; + u32 tx_element_length_1; + u32 tx_element_length_2; + u32 rx_data_delay; + u32 tx_data_delay; + u32 rx_clock_pol; + u32 tx_clock_pol; + u32 rx_frame_sync_pol; + u32 tx_frame_sync_pol; + u32 rx_half_word_swap; + u32 tx_half_word_swap; + u32 compression_mode; + u32 expansion_mode; + u32 spi_clk_mode; + u32 spi_burst_mode; + u32 frame_sync_ignore; + u32 frame_period; + u32 frame_width; + u32 total_clocks_for_one_frame; +}; + +/** + * struct trans_data - MSP transfer data structure used during xfer. + * @message: i2s message. + * @msp: msp structure. + * @tx_handler: callback handler for transmit path. + * @rx_handler: callback handler for receive path. + * @tx_callback_data: callback data for transmit. + * @rx_callback_data: callback data for receive. + * + */ +struct trans_data { + struct i2s_message message; + struct msp *msp; + void (*tx_handler) (void *data); + void (*rx_handler) (void *data); + void *tx_callback_data; + void *rx_callback_data; +}; + +/** + * struct msp_config- MSP configuration structure used by i2s client. + * @input_clock_freq: Input clock frequency default is 48MHz. + * @rx_clock_sel: Receive clock selection (Provided by Sample Gen or external + * source). + * @tx_clock_sel: Transmit clock selection (Provided by Sample Gen or external. + * source). + * @srg_clock_sel: APB clock or clock dervied from Slave (Audio codec). + * @rx_frame_sync_pol: Receive frame sync polarity. + * @tx_frame_sync_pol: Transmit frame sync polarity. + * @rx_frame_sync_sel: Rx frame sync signal is provided by which source. + * External source or by frame generator logic. + * @tx_frame_sync_sel: Tx frame sync signal is provided by which source. + * External source or by frame generator logic. + * @rx_fifo_config: Receive fifo enable or not. + * @tx_fifo_config: Transmit fifo enable or not. + * @spi_clk_mode: In case of SPI protocol spi modes: Normal, Zero delay or + * half cycle delay. + * @spi_burst_mode: Spi burst mode is enabled or not. + * @loopback_enable: Loopback mode. + * @tx_data_enable: Transmit extra delay enable. + * @default_protocol_desc: Flag to indicate client defined protocol desc or + * statically defined in msp.h. + * @protocol_desc: Protocol desc structure filled by i2s client driver. + * In case client defined default_prtocol_desc as 0. + * @multichannel_configured: multichannel configuration structure. + * @multichannel_config: multichannel is enabled or not. + * @direction: Transmit, Receive or Both. + * @work_mode: Dma, Polling or Interrupt. + * @protocol: I2S, PCM, etc. + * @frame_freq: Sampling freq at which data is sampled. + * @frame_size: size of element. + * @data_size: data size which defines the format in which data is written on + * transmit or receive fifo. Only three modes 8,16,32 are supported. + * @def_elem_len: Flag to indicate whether default element length is to be used + * or should be changed acc to data size defined by user at run time. + * @iodelay: value for the MSP_IODLY register + * @handler: callback handler in case of interrupt or dma. + * @tx_callback_data: Callback data for transmit. + * @rx_callback_data: Callback data for receive. + * + * Main Msp configuration data structure used by i2s client driver to fill + * various info like data size, frequency etc. + */ +struct msp_config { + unsigned int input_clock_freq; + unsigned int rx_clock_sel; + unsigned int tx_clock_sel; + unsigned int srg_clock_sel; + unsigned int rx_frame_sync_pol; + unsigned int tx_frame_sync_pol; + unsigned int rx_frame_sync_sel; + unsigned int tx_frame_sync_sel; + unsigned int rx_fifo_config; + unsigned int tx_fifo_config; + unsigned int spi_clk_mode; + unsigned int spi_burst_mode; + unsigned int loopback_enable; + unsigned int tx_data_enable; + unsigned int default_protocol_desc; + struct msp_protocol_desc protocol_desc; + int multichannel_configured; + struct msp_multichannel_config multichannel_config; + unsigned int direction; + unsigned int work_mode; + unsigned int protocol; + unsigned int frame_freq; + unsigned int frame_size; + enum msp_data_size data_size; + unsigned int def_elem_len; + unsigned int iodelay; + void (*handler) (void *data); + void *tx_callback_data; + void *rx_callback_data; + +}; + +/*** Protocols ***/ +enum msp_protocol { + MSP_I2S_PROTOCOL, + MSP_PCM_PROTOCOL, + MSP_PCM_COMPAND_PROTOCOL, + MSP_AC97_PROTOCOL, + MSP_MASTER_SPI_PROTOCOL, + MSP_SLAVE_SPI_PROTOCOL, + MSP_INVALID_PROTOCOL +}; + +/*** Sample Frequencies ***/ +/* These are no longer required, frequencies in Hz can be used directly */ +enum msp_sample_freq { + MSP_SAMPLE_FREQ_NOT_SUPPORTED = -1, + MSP_SAMPLE_FREQ_8KHZ = 8000, + MSP_SAMPLE_FREQ_12KHZ = 12000, + MSP_SAMPLE_FREQ_16KHZ = 16000, + MSP_SAMPLE_FREQ_24KHZ = 24000, + MSP_SAMPLE_FREQ_32KHZ = 32000, + MSP_SAMPLE_FREQ_44KHZ = 44000, + MSP_SAMPLE_FREQ_48KHZ = 48000, + MSP_SAMPLE_FREQ_64KHZ = 64000, + MSP_SAMPLE_FREQ_88KHZ = 88000, + MSP_SAMPLE_FREQ_96KHZ = 96000, + MSP_SAMPLE_FREQ_22KHZ = 22000, + MSP_SAMPLE_FREQ_11KHZ = 11000 +}; + +/*** Input Frequencies ***/ +/* These are no longer required, frequencies in Hz can be used directly */ +enum msp_in_clock_freq { + MSP_INPUT_FREQ_1MHZ = 1000, + MSP_INPUT_FREQ_2MHZ = 2000, + MSP_INPUT_FREQ_3MHZ = 3000, + MSP_INPUT_FREQ_4MHZ = 4000, + MSP_INPUT_FREQ_5MHZ = 5000, + MSP_INPUT_FREQ_6MHZ = 6000, + MSP_INPUT_FREQ_8MHZ = 8000, + MSP_INPUT_FREQ_11MHZ = 11000, + MSP_INPUT_FREQ_12MHZ = 12000, + MSP_INPUT_FREQ_16MHZ = 16000, + MSP_INPUT_FREQ_22MHZ = 22000, + MSP_INPUT_FREQ_24MHZ = 24000, + MSP_INPUT_FREQ_48MHZ = 48000 +}; + +#define MSP_INPUT_FREQ_APB 48000000 + +/*** Stereo mode. Used for APB data accesses as 16 bits accesses (mono), + * 32 bits accesses (stereo). + ***/ +enum msp_stereo_mode { + MSP_MONO, + MSP_STEREO +}; + +/* Direction (Transmit/Receive mode) */ +enum msp_direction { + MSP_TRANSMIT_MODE, + MSP_RECEIVE_MODE, + MSP_BOTH_T_R_MODE +}; + +/* Dma mode should be used for large transfers, + * polling mode should be used for transfers of a few bytes + */ +enum msp_xfer_mode { + MSP_DMA_MODE, + MSP_POLLING_MODE, + MSP_INTERRUPT_MODE +}; + +/* User client for the MSP */ +enum msp_user { + MSP_NO_USER = 0, + MSP_USER_SPI, + MSP_USER_ALSA, + MSP_USER_SAA, +}; + +/*Flag structure for MSPx*/ +struct msp_flag { + struct semaphore lock; + enum msp_user user; +}; + +/* User client for the MSP */ +enum msp_mode { + MSP_NO_MODE = 0, + MSP_MODE_SPI, + MSP_MODE_NON_SPI, +}; + +/* Transmit and receive configuration register */ +#define MSP_BIG_ENDIAN 0x00000000 +#define MSP_LITTLE_ENDIAN 0x00001000 +#define MSP_UNEXPECTED_FS_ABORT 0x00000000 +#define MSP_UNEXPECTED_FS_IGNORE 0x00008000 +#define MSP_NON_MODE_BIT_MASK 0x00009000 + +/* Global configuration register */ +#define RX_ENABLE 0x00000001 +#define RX_FIFO_ENABLE 0x00000002 +#define RX_SYNC_SRG 0x00000010 +#define RX_CLK_POL_RISING 0x00000020 +#define RX_CLK_SEL_SRG 0x00000040 +#define TX_ENABLE 0x00000100 +#define TX_FIFO_ENABLE 0x00000200 +#define TX_SYNC_SRG_PROG 0x00001800 +#define TX_SYNC_SRG_AUTO 0x00001000 +#define TX_CLK_POL_RISING 0x00002000 +#define TX_CLK_SEL_SRG 0x00004000 +#define TX_EXTRA_DELAY_ENABLE 0x00008000 +#define SRG_ENABLE 0x00010000 +#define FRAME_GEN_ENABLE 0x00100000 +#define SRG_CLK_SEL_APB 0x00000000 +#define RX_FIFO_SYNC_HI 0x00000000 +#define TX_FIFO_SYNC_HI 0x00000000 +#define SPI_CLK_MODE_NORMAL 0x00000000 + +/* SPI Clock Modes enumertion + * SPI clock modes of MSP provides compatibility with + * the SPI protocol.MSP supports 2 SPI transfer formats. + * MSP_ZERO_DELAY_SPI_MODE:MSP transmits data over Tx/Rx + * Lines immediately after MSPTCK/MSPRCK rising/falling edge. + * MSP_HALF_CYCLE_DELY_SPI_MODE:MSP transmits data one-half cycle + * ahead of the rising/falling edge of the MSPTCK + */ + +#define MSP_FRAME_SIZE_AUTO -1 + + +#define MSP_DR 0x00 +#define MSP_GCR 0x04 +#define MSP_TCF 0x08 +#define MSP_RCF 0x0c +#define MSP_SRG 0x10 +#define MSP_FLR 0x14 +#define MSP_DMACR 0x18 + +#define MSP_IMSC 0x20 +#define MSP_RIS 0x24 +#define MSP_MIS 0x28 +#define MSP_ICR 0x2c +#define MSP_MCR 0x30 +#define MSP_RCV 0x34 +#define MSP_RCM 0x38 + +#define MSP_TCE0 0x40 +#define MSP_TCE1 0x44 +#define MSP_TCE2 0x48 +#define MSP_TCE3 0x4c + +#define MSP_RCE0 0x60 +#define MSP_RCE1 0x64 +#define MSP_RCE2 0x68 +#define MSP_RCE3 0x6c +#define MSP_IODLY 0x70 + +#define MSP_ITCR 0x80 +#define MSP_ITIP 0x84 +#define MSP_ITOP 0x88 +#define MSP_TSTDR 0x8c + +#define MSP_PID0 0xfe0 +#define MSP_PID1 0xfe4 +#define MSP_PID2 0xfe8 +#define MSP_PID3 0xfec + +#define MSP_CID0 0xff0 +#define MSP_CID1 0xff4 +#define MSP_CID2 0xff8 +#define MSP_CID3 0xffc + +/* Single or dual phase mode */ +enum msp_phase_mode { + MSP_SINGLE_PHASE, + MSP_DUAL_PHASE +}; + +/* Frame length */ +enum msp_frame_length { + MSP_FRAME_LENGTH_1 = 0, + MSP_FRAME_LENGTH_2 = 1, + MSP_FRAME_LENGTH_4 = 3, + MSP_FRAME_LENGTH_8 = 7, + MSP_FRAME_LENGTH_12 = 11, + MSP_FRAME_LENGTH_16 = 15, + MSP_FRAME_LENGTH_20 = 19, + MSP_FRAME_LENGTH_32 = 31, + MSP_FRAME_LENGTH_48 = 47, + MSP_FRAME_LENGTH_64 = 63 +}; + +/* Element length */ +enum msp_elem_length { + MSP_ELEM_LENGTH_8 = 0, + MSP_ELEM_LENGTH_10 = 1, + MSP_ELEM_LENGTH_12 = 2, + MSP_ELEM_LENGTH_14 = 3, + MSP_ELEM_LENGTH_16 = 4, + MSP_ELEM_LENGTH_20 = 5, + MSP_ELEM_LENGTH_24 = 6, + MSP_ELEM_LENGTH_32 = 7 +}; + +enum msp_data_xfer_width { + MSP_DATA_TRANSFER_WIDTH_BYTE, + MSP_DATA_TRANSFER_WIDTH_HALFWORD, + MSP_DATA_TRANSFER_WIDTH_WORD +}; + +enum msp_frame_sync { + MSP_FRAME_SYNC_UNIGNORE = 0, + MSP_FRAME_SYNC_IGNORE = 1, + +}; + +enum msp_phase2_start_mode { + MSP_PHASE2_START_MODE_IMEDIATE, + MSP_PHASE2_START_MODE_FRAME_SYNC +}; + +enum msp_btf { + MSP_BTF_MS_BIT_FIRST = 0, + MSP_BTF_LS_BIT_FIRST = 1 +}; + +enum msp_frame_sync_pol { + MSP_FRAME_SYNC_POL_ACTIVE_HIGH = 0, + MSP_FRAME_SYNC_POL_ACTIVE_LOW = 1 +}; + +/* Data delay (in bit clock cycles) */ +enum msp_delay { + MSP_DELAY_0 = 0, + MSP_DELAY_1 = 1, + MSP_DELAY_2 = 2, + MSP_DELAY_3 = 3 +}; + +/* Configurations of clocks (transmit, receive or sample rate generator) */ +enum msp_edge { + MSP_FALLING_EDGE = 0, + MSP_RISING_EDGE = 1, +}; + +enum msp_hws { + MSP_HWS_NO_SWAP = 0, + MSP_HWS_BYTE_SWAP_IN_WORD = 1, + MSP_HWS_BYTE_SWAP_IN_EACH_HALF_WORD = 2, + MSP_HWS_HALF_WORD_SWAP_IN_WORD = 3 +}; + +enum msp_compress_mode { + MSP_COMPRESS_MODE_LINEAR = 0, + MSP_COMPRESS_MODE_MU_LAW = 2, + MSP_COMPRESS_MODE_A_LAW = 3 +}; + +enum msp_spi_clock_mode { + MSP_SPI_CLOCK_MODE_NON_SPI = 0, + MSP_SPI_CLOCK_MODE_ZERO_DELAY = 2, + MSP_SPI_CLOCK_MODE_HALF_CYCLE_DELAY = 3 +}; + +enum msp_spi_burst_mode { + MSP_SPI_BURST_MODE_DISABLE = 0, + MSP_SPI_BURST_MODE_ENABLE = 1 +}; + +enum msp_expand_mode { + MSP_EXPAND_MODE_LINEAR = 0, + MSP_EXPAND_MODE_LINEAR_SIGNED = 1, + MSP_EXPAND_MODE_MU_LAW = 2, + MSP_EXPAND_MODE_A_LAW = 3 +}; + +/* Protocol dependant parameters list */ +#define RX_ENABLE_MASK BIT(0) +#define RX_FIFO_ENABLE_MASK BIT(1) +#define RX_FRAME_SYNC_MASK BIT(2) +#define DIRECT_COMPANDING_MASK BIT(3) +#define RX_SYNC_SEL_MASK BIT(4) +#define RX_CLK_POL_MASK BIT(5) +#define RX_CLK_SEL_MASK BIT(6) +#define LOOPBACK_MASK BIT(7) +#define TX_ENABLE_MASK BIT(8) +#define TX_FIFO_ENABLE_MASK BIT(9) +#define TX_FRAME_SYNC_MASK BIT(10) +#define TX_MSP_TDR_TSR BIT(11) +#define TX_SYNC_SEL_MASK (BIT(12) | BIT(11)) +#define TX_CLK_POL_MASK BIT(13) +#define TX_CLK_SEL_MASK BIT(14) +#define TX_EXTRA_DELAY_MASK BIT(15) +#define SRG_ENABLE_MASK BIT(16) +#define SRG_CLK_POL_MASK BIT(17) +#define SRG_CLK_SEL_MASK (BIT(19) | BIT(18)) +#define FRAME_GEN_EN_MASK BIT(20) +#define SPI_CLK_MODE_MASK (BIT(22) | BIT(21)) +#define SPI_BURST_MODE_MASK BIT(23) + +#define RXEN_SHIFT 0 +#define RFFEN_SHIFT 1 +#define RFSPOL_SHIFT 2 +#define DCM_SHIFT 3 +#define RFSSEL_SHIFT 4 +#define RCKPOL_SHIFT 5 +#define RCKSEL_SHIFT 6 +#define LBM_SHIFT 7 +#define TXEN_SHIFT 8 +#define TFFEN_SHIFT 9 +#define TFSPOL_SHIFT 10 +#define TFSSEL_SHIFT 11 +#define TCKPOL_SHIFT 13 +#define TCKSEL_SHIFT 14 +#define TXDDL_SHIFT 15 +#define SGEN_SHIFT 16 +#define SCKPOL_SHIFT 17 +#define SCKSEL_SHIFT 18 +#define FGEN_SHIFT 20 +#define SPICKM_SHIFT 21 +#define TBSWAP_SHIFT 28 + +#define RCKPOL_MASK BIT(0) +#define TCKPOL_MASK BIT(0) +#define SPICKM_MASK (BIT(1) | BIT(0)) +#define MSP_RX_CLKPOL_BIT(n) ((n & RCKPOL_MASK) << RCKPOL_SHIFT) +#define MSP_TX_CLKPOL_BIT(n) ((n & TCKPOL_MASK) << TCKPOL_SHIFT) +#define MSP_SPI_CLK_MODE_BITS(n) ((n & SPICKM_MASK) << SPICKM_SHIFT) + + + +/* Use this to clear the clock mode bits to non-spi */ +#define MSP_NON_SPI_CLK_MASK (BIT(22) | BIT(21)) + +#define P1ELEN_SHIFT 0 +#define P1FLEN_SHIFT 3 +#define DTYP_SHIFT 10 +#define ENDN_SHIFT 12 +#define DDLY_SHIFT 13 +#define FSIG_SHIFT 15 +#define P2ELEN_SHIFT 16 +#define P2FLEN_SHIFT 19 +#define P2SM_SHIFT 26 +#define P2EN_SHIFT 27 +#define FRAME_SYNC_SHIFT 15 + + +#define P1ELEN_MASK 0x00000007 +#define P2ELEN_MASK 0x00070000 +#define P1FLEN_MASK 0x00000378 +#define P2FLEN_MASK 0x03780000 +#define DDLY_MASK 0x00003000 +#define DTYP_MASK 0x00000600 +#define P2SM_MASK 0x04000000 +#define P2EN_MASK 0x08000000 +#define ENDN_MASK 0x00001000 +#define TFSPOL_MASK 0x00000400 +#define TBSWAP_MASK 0x30000000 +#define COMPANDING_MODE_MASK 0x00000c00 +#define FRAME_SYNC_MASK 0x00008000 + +#define MSP_P1_ELEM_LEN_BITS(n) (n & P1ELEN_MASK) +#define MSP_P2_ELEM_LEN_BITS(n) (((n) << P2ELEN_SHIFT) & P2ELEN_MASK) +#define MSP_P1_FRAME_LEN_BITS(n) (((n) << P1FLEN_SHIFT) & P1FLEN_MASK) +#define MSP_P2_FRAME_LEN_BITS(n) (((n) << P2FLEN_SHIFT) & P2FLEN_MASK) +#define MSP_DATA_DELAY_BITS(n) (((n) << DDLY_SHIFT) & DDLY_MASK) +#define MSP_DATA_TYPE_BITS(n) (((n) << DTYP_SHIFT) & DTYP_MASK) +#define MSP_P2_START_MODE_BIT(n) ((n << P2SM_SHIFT) & P2SM_MASK) +#define MSP_P2_ENABLE_BIT(n) ((n << P2EN_SHIFT) & P2EN_MASK) +#define MSP_SET_ENDIANNES_BIT(n) ((n << ENDN_SHIFT) & ENDN_MASK) +#define MSP_FRAME_SYNC_POL(n) ((n << TFSPOL_SHIFT) & TFSPOL_MASK) +#define MSP_DATA_WORD_SWAP(n) ((n << TBSWAP_SHIFT) & TBSWAP_MASK) +#define MSP_SET_COMPANDING_MODE(n) ((n << DTYP_SHIFT) & COMPANDING_MODE_MASK) +#define MSP_SET_FRAME_SYNC_IGNORE(n) ((n << FRAME_SYNC_SHIFT) & \ + FRAME_SYNC_MASK) + +/* Flag register */ +#define RX_BUSY BIT(0) +#define RX_FIFO_EMPTY BIT(1) +#define RX_FIFO_FULL BIT(2) +#define TX_BUSY BIT(3) +#define TX_FIFO_EMPTY BIT(4) +#define TX_FIFO_FULL BIT(5) + +#define RBUSY_SHIFT 0 +#define RFE_SHIFT 1 +#define RFU_SHIFT 2 +#define TBUSY_SHIFT 3 +#define TFE_SHIFT 4 +#define TFU_SHIFT 5 + +/* Multichannel control register */ +#define RMCEN_SHIFT 0 +#define RMCSF_SHIFT 1 +#define RCMPM_SHIFT 3 +#define TMCEN_SHIFT 5 +#define TNCSF_SHIFT 6 + +/* Sample rate generator register */ +#define SCKDIV_SHIFT 0 +#define FRWID_SHIFT 10 +#define FRPER_SHIFT 16 + +#define SCK_DIV_MASK 0x0000003FF +#define FRAME_WIDTH_BITS(n) (((n) << FRWID_SHIFT) & 0x0000FC00) +#define FRAME_PERIOD_BITS(n) (((n) << FRPER_SHIFT) & 0x1FFF0000) + +/* DMA controller register */ +#define RX_DMA_ENABLE BIT(0) +#define TX_DMA_ENABLE BIT(1) + +#define RDMAE_SHIFT 0 +#define TDMAE_SHIFT 1 + +/* Interrupt Register */ +#define RECEIVE_SERVICE_INT BIT(0) +#define RECEIVE_OVERRUN_ERROR_INT BIT(1) +#define RECEIVE_FRAME_SYNC_ERR_INT BIT(2) +#define RECEIVE_FRAME_SYNC_INT BIT(3) +#define TRANSMIT_SERVICE_INT BIT(4) +#define TRANSMIT_UNDERRUN_ERR_INT BIT(5) +#define TRANSMIT_FRAME_SYNC_ERR_INT BIT(6) +#define TRANSMIT_FRAME_SYNC_INT BIT(7) +#define ALL_INT 0x000000ff + +/* + * Protocol configuration values I2S: + * Single phase, 16 bits, 2 words per frame + */ +#define I2S_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_IMEDIATE, \ + MSP_PHASE2_START_MODE_IMEDIATE, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_32, \ + MSP_ELEM_LENGTH_32, \ + MSP_ELEM_LENGTH_32, \ + MSP_ELEM_LENGTH_32, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_RISING_EDGE, \ + MSP_RISING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 31, \ + 15, \ + 32, \ +} + +#define PCM_PROTOCOL_DESC \ +{ \ + MSP_DUAL_PHASE, \ + MSP_DUAL_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_16, \ + MSP_DELAY_0, \ + MSP_DELAY_0, \ + MSP_FALLING_EDGE, \ + MSP_FALLING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +/* Companded PCM: Single phase, 8 bits, 1 word per frame */ +#define PCM_COMPAND_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_0, \ + MSP_DELAY_0, \ + MSP_FALLING_EDGE, \ + MSP_RISING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +/* + * AC97: Double phase, 1 element of 16 bits during first phase, + * 12 elements of 20 bits in second phase. + */ +#define AC97_PROTOCOL_DESC \ +{ \ + MSP_DUAL_PHASE, \ + MSP_DUAL_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_12, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_12, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_20, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_20, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_FALLING_EDGE, \ + MSP_RISING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +#define SPI_MASTER_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_RISING_EDGE, \ + MSP_FALLING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +#define SPI_SLAVE_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_RISING_EDGE, \ + MSP_FALLING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +#define MSP_FRAME_PERIOD_IN_MONO_MODE 256 +#define MSP_FRAME_PERIOD_IN_STEREO_MODE 32 +#define MSP_FRAME_WIDTH_IN_STEREO_MODE 16 + +/* + * No of registers to backup during + * suspend resume + */ +#define MAX_MSP_BACKUP_REGS 36 + +enum enum_i2s_controller { + MSP_0_I2S_CONTROLLER = 1, + MSP_1_I2S_CONTROLLER, + MSP_2_I2S_CONTROLLER, + MSP_3_I2S_CONTROLLER, +}; + +/** + * struct msp - Main msp controller data structure per MSP. + * @work_mode: Mode i.e dma, polling or interrupt. + * @id: Controller id like MSP1 or MSP2 etc. + * @msp_io_error: To indicate error while transferring. + * @registers: MSP's register base address. + * @actual_data_size: Data size in which data needs to send or receive. + * @irq: MSP's irq number. + * @i2s_cont: MSP's Controller's structure pointer created per MSP. + * @lock: semaphore lock acquired while configuring msp. + * @dma_cfg_tx: TX DMA configuration + * @dma_cfg_rx: RX DMA configuration + * @tx_pipeid: TX DMA channel + * @rx_pipeid: RX DMA channel + * @msp_state: Current state of msp. + * @read: Function pointer for read, u8_msp_read,u16_msp_read,u32_msp_read. + * @write: Function pointer for write, u8_msp_write,u16_msp_write,u32_msp_write. + * @transfer: Function pointer for type of transfer i.e dma,polling or interrupt + * @xfer_data: MSP's transfer data structure. Contains info about current xfer. + * @plat_init: MSP's initialization function. + * @plat_exit: MSP's Exit function. + * @notify_timer: Timer used in Polling mode to prevent hang. + * @polling_flag: Flag used in error handling while polling. + * @def_elem_len: Flag indicates whether default elem len to be used in + * protocol_desc or not. + * @vape_opp_constraint: 1 if constraint is applied to have vape at 100OPP; 0 otherwise + * @infinite: true if an infinite transfer has been configured + * + * Main Msp private data structure to be used to store various info of a + * particular MSP.Longer description + */ +struct msp { + int work_mode; + enum enum_i2s_controller id; + int msp_io_error; + void __iomem *registers; + enum msp_data_size actual_data_size; + int irq; + struct i2s_controller *i2s_cont; + struct semaphore lock; + struct stedma40_chan_cfg *dma_cfg_rx; + struct stedma40_chan_cfg *dma_cfg_tx; + struct dma_chan *tx_pipeid; + struct dma_chan *rx_pipeid; + enum msp_state msp_state; + void (*read) (struct trans_data *xfer_data); + void (*write) (struct trans_data *xfer_data); + int (*transfer) (struct msp *msp, struct i2s_message *message); + struct trans_data xfer_data; + int (*plat_init) (void); + int (*plat_exit) (void); + struct timer_list notify_timer; + int polling_flag; + int def_elem_len; + struct clk *clk; + unsigned int direction; + int users; + int loopback_enable; + u32 backup_regs[MAX_MSP_BACKUP_REGS]; + int vape_opp_constraint; + bool infinite; +}; + +/** + * struct msp_i2s_platform_data - Main msp controller platform data structure. + * @id: Controller id like MSP1 or MSP2 etc. + * @msp_i2s_dma_rx: RX DMA channel config + * @msp_i2s_dma_tx: RX DMA channel config + * @msp_i2s_init: MSP's initialization function. + * @msp_i2s_exit: MSP's Exit function. + * @backup_regs: used for backup registers during suspend resume. + * + * Platform data structure passed by devices.c file. + */ +struct msp_i2s_platform_data { + enum enum_i2s_controller id; + struct stedma40_chan_cfg *msp_i2s_dma_rx; + struct stedma40_chan_cfg *msp_i2s_dma_tx; + int (*msp_i2s_init) (void); + int (*msp_i2s_exit) (void); +}; + +#endif diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 00c024039c9..b8aa82fa2a6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -113,6 +113,20 @@ config SPI_BITBANG need it. You only need to select this explicitly to support driver modules that aren't part of this kernel tree. +config STM_MSP_SPI + tristate "STM MSP CONTROLLER (SPI master)" + default y + help + This enables using the STM MSP controller in master + mode. + +config SPI_WORKQUEUE + bool "SPI_WORKQUEUE" + depends on STM_MSP_SPI + default n + help + This feature allow SPI works to be deferred in MSP driver. + config SPI_BUTTERFLY tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" depends on PARPORT diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 9d75d2198ff..6c10ed18023 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -62,4 +62,5 @@ obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o obj-$(CONFIG_SPI_TXX9) += spi-txx9.o obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o +obj-$(CONFIG_STM_MSP_SPI) += stm_msp.o diff --git a/drivers/spi/stm_msp.c b/drivers/spi/stm_msp.c new file mode 100644 index 00000000000..6b9d7bb75e5 --- /dev/null +++ b/drivers/spi/stm_msp.c @@ -0,0 +1,1929 @@ +/* + * drivers/spi/stm_msp.c + * + * Copyright (C) 2010 STMicroelectronics Pvt. Ltd. + * + * Author: Sachin Verma + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include + +/** + * MSP Controller Register Offsets + */ +#define MSP_DR(r) (r + 0x000) +#define MSP_GCR(r) (r + 0x004) +#define MSP_TCF(r) (r + 0x008) +#define MSP_RCF(r) (r + 0x00C) +#define MSP_SRG(r) (r + 0x010) +#define MSP_FLR(r) (r + 0x014) +#define MSP_DMACR(r) (r + 0x018) +#define MSP_IMSC(r) (r + 0x020) +#define MSP_RIS(r) (r + 0x024) +#define MSP_MIS(r) (r + 0x028) +#define MSP_ICR(r) (r + 0x02C) +#define MSP_MCR(r) (r + 0x030) +#define MSP_RCV(r) (r + 0x034) +#define MSP_RCM(r) (r + 0x038) +#define MSP_TCE0(r) (r + 0x040) +#define MSP_TCE1(r) (r + 0x044) +#define MSP_TCE2(r) (r + 0x048) +#define MSP_TCE3(r) (r + 0x04C) +#define MSP_RCE0(r) (r + 0x060) +#define MSP_RCE1(r) (r + 0x064) +#define MSP_RCE2(r) (r + 0x068) +#define MSP_RCE3(r) (r + 0x06C) +#define MSP_PID0(r) (r + 0xFE0) +#define MSP_PID1(r) (r + 0xFE4) +#define MSP_PID2(r) (r + 0xFE8) +#define MSP_PID3(r) (r + 0xFEC) + +/** + * MSP Global Configuration Register - MSP_GCR + */ +#define MSP_GCR_MASK_RXEN ((u32)(0x1UL << 0)) +#define MSP_GCR_MASK_RFFEN ((u32)(0x1UL << 1)) +#define MSP_GCR_MASK_RFSPOL ((u32)(0x1UL << 2)) +#define MSP_GCR_MASK_DCM ((u32)(0x1UL << 3)) +#define MSP_GCR_MASK_RFSSEL ((u32)(0x1UL << 4)) +#define MSP_GCR_MASK_RCKPOL ((u32)(0x1UL << 5)) +#define MSP_GCR_MASK_RCKSEL ((u32)(0x1UL << 6)) +#define MSP_GCR_MASK_LBM ((u32)(0x1UL << 7)) +#define MSP_GCR_MASK_TXEN ((u32)(0x1UL << 8)) +#define MSP_GCR_MASK_TFFEN ((u32)(0x1UL << 9)) +#define MSP_GCR_MASK_TFSPOL ((u32)(0x1UL << 10)) +#define MSP_GCR_MASK_TFSSEL ((u32)(0x3UL << 11)) +#define MSP_GCR_MASK_TCKPOL ((u32)(0x1UL << 13)) +#define MSP_GCR_MASK_TCKSEL ((u32)(0x1UL << 14)) +#define MSP_GCR_MASK_TXDDL ((u32)(0x1UL << 15)) +#define MSP_GCR_MASK_SGEN ((u32)(0x1UL << 16)) +#define MSP_GCR_MASK_SCKPOL ((u32)(0x1UL << 17)) +#define MSP_GCR_MASK_SCKSEL ((u32)(0x3UL << 18)) +#define MSP_GCR_MASK_FGEN ((u32)(0x1UL << 20)) +#define MSP_GCR_MASK_SPICKM ((u32)(0x3UL << 21)) +#define MSP_GCR_MASK_SPIBME ((u32)(0x1UL << 23)) + +/** + * MSP Transmit Configuration Register - MSP_TCF + */ +#define MSP_TCF_MASK_TP1ELEN ((u32)(0x7UL << 0)) +#define MSP_TCF_MASK_TP1FLEN ((u32)(0x7FUL << 3)) +#define MSP_TCF_MASK_TDTYP ((u32)(0x3UL << 10)) +#define MSP_TCF_MASK_TENDN ((u32)(0x1UL << 12)) +#define MSP_TCF_MASK_TDDLY ((u32)(0x3UL << 13)) +#define MSP_TCF_MASK_TFSIG ((u32)(0x1UL << 15)) +#define MSP_TCF_MASK_TP2ELEN ((u32)(0x7UL << 16)) +#define MSP_TCF_MASK_TP2FLEN ((u32)(0x7FUL << 19)) +#define MSP_TCF_MASK_TP2SM ((u32)(0x1UL << 26)) +#define MSP_TCF_MASK_TP2EN ((u32)(0x1UL << 27)) +#define MSP_TCF_MASK_TBSWAP ((u32)(0x3UL << 28)) + +/** + * MSP Receive Configuration Register - MSP_RCF + */ +#define MSP_RCF_MASK_RP1ELEN ((u32)(0x7UL << 0)) +#define MSP_RCF_MASK_RP1FLEN ((u32)(0x7FUL << 3)) +#define MSP_RCF_MASK_RDTYP ((u32)(0x3UL << 10)) +#define MSP_RCF_MASK_RENDN ((u32)(0x1UL << 12)) +#define MSP_RCF_MASK_RDDLY ((u32)(0x3UL << 13)) +#define MSP_RCF_MASK_RFSIG ((u32)(0x1UL << 15)) +#define MSP_RCF_MASK_RP2ELEN ((u32)(0x7UL << 16)) +#define MSP_RCF_MASK_RP2FLEN ((u32)(0x7FUL << 19)) +#define MSP_RCF_MASK_RP2SM ((u32)(0x1UL << 26)) +#define MSP_RCF_MASK_RP2EN ((u32)(0x1UL << 27)) +#define MSP_RCF_MASK_RBSWAP ((u32)(0x3UL << 28)) + +/** + * MSP Sample Rate Generator Register - MSP_SRG + */ +#define MSP_SRG_MASK_SCKDIV ((u32)(0x3FFUL << 0)) +#define MSP_SRG_MASK_FRWID ((u32)(0x3FUL << 10)) +#define MSP_SRG_MASK_FRPER ((u32)(0x1FFFUL << 16)) + +/** + * MSP Flag Register - MSP_FLR + */ +#define MSP_FLR_MASK_RBUSY ((u32)(0x1UL << 0)) +#define MSP_FLR_MASK_RFE ((u32)(0x1UL << 1)) +#define MSP_FLR_MASK_RFU ((u32)(0x1UL << 2)) +#define MSP_FLR_MASK_TBUSY ((u32)(0x1UL << 3)) +#define MSP_FLR_MASK_TFE ((u32)(0x1UL << 4)) +#define MSP_FLR_MASK_TFU ((u32)(0x1UL << 5)) + +/** + * MSP DMA Control Register - MSP_DMACR + */ +#define MSP_DMACR_MASK_RDMAE ((u32)(0x1UL << 0)) +#define MSP_DMACR_MASK_TDMAE ((u32)(0x1UL << 1)) + +/** + * MSP Interrupt Mask Set/Clear Register - MSP_IMSC + */ +#define MSP_IMSC_MASK_RXIM ((u32)(0x1UL << 0)) +#define MSP_IMSC_MASK_ROEIM ((u32)(0x1UL << 1)) +#define MSP_IMSC_MASK_RSEIM ((u32)(0x1UL << 2)) +#define MSP_IMSC_MASK_RFSIM ((u32)(0x1UL << 3)) +#define MSP_IMSC_MASK_TXIM ((u32)(0x1UL << 4)) +#define MSP_IMSC_MASK_TUEIM ((u32)(0x1UL << 5)) +#define MSP_IMSC_MASK_TSEIM ((u32)(0x1UL << 6)) +#define MSP_IMSC_MASK_TFSIM ((u32)(0x1UL << 7)) +#define MSP_IMSC_MASK_RFOIM ((u32)(0x1UL << 8)) +#define MSP_IMSC_MASK_TFOIM ((u32)(0x1UL << 9)) + +/** + * MSP Raw Interrupt status Register - MSP_RIS + */ +#define MSP_RIS_MASK_RXRIS ((u32)(0x1UL << 0)) +#define MSP_RIS_MASK_ROERIS ((u32)(0x1UL << 1)) +#define MSP_RIS_MASK_RSERIS ((u32)(0x1UL << 2)) +#define MSP_RIS_MASK_RFSRIS ((u32)(0x1UL << 3)) +#define MSP_RIS_MASK_TXRIS ((u32)(0x1UL << 4)) +#define MSP_RIS_MASK_TUERIS ((u32)(0x1UL << 5)) +#define MSP_RIS_MASK_TSERIS ((u32)(0x1UL << 6)) +#define MSP_RIS_MASK_TFSRIS ((u32)(0x1UL << 7)) +#define MSP_RIS_MASK_RFORIS ((u32)(0x1UL << 8)) +#define MSP_RIS_MASK_TFORIS ((u32)(0x1UL << 9)) + +/** + * MSP Masked Interrupt status Register - MSP_MIS + */ +#define MSP_MIS_MASK_RXMIS ((u32)(0x1UL << 0)) +#define MSP_MIS_MASK_ROEMIS ((u32)(0x1UL << 1)) +#define MSP_MIS_MASK_RSEMIS ((u32)(0x1UL << 2)) +#define MSP_MIS_MASK_RFSMIS ((u32)(0x1UL << 3)) +#define MSP_MIS_MASK_TXMIS ((u32)(0x1UL << 4)) +#define MSP_MIS_MASK_TUEMIS ((u32)(0x1UL << 5)) +#define MSP_MIS_MASK_TSEMIS ((u32)(0x1UL << 6)) +#define MSP_MIS_MASK_TFSMIS ((u32)(0x1UL << 7)) +#define MSP_MIS_MASK_RFOMIS ((u32)(0x1UL << 8)) +#define MSP_MIS_MASK_TFOMIS ((u32)(0x1UL << 9)) + +/** + * MSP Interrupt Clear Register - MSP_ICR + */ +#define MSP_ICR_MASK_ROEIC ((u32)(0x1UL << 1)) +#define MSP_ICR_MASK_RSEIC ((u32)(0x1UL << 2)) +#define MSP_ICR_MASK_RFSIC ((u32)(0x1UL << 3)) +#define MSP_ICR_MASK_TUEIC ((u32)(0x1UL << 5)) +#define MSP_ICR_MASK_TSEIC ((u32)(0x1UL << 6)) +#define MSP_ICR_MASK_TFSIC ((u32)(0x1UL << 7)) + +#define GEN_MASK_BITS(val, mask, sb) ((u32)((((u32)val) << (sb)) & (mask))) +#define MSP_WBITS(reg, val, mask, sb) ((reg) = (((reg) & ~(mask)) |\ + (((val) << (sb)) & (mask)))) +#define DEFAULT_MSP_REG_DMACR 0x00000000 +#define DEFAULT_MSP_REG_SRG 0x1FFF0000 + +#define DEFAULT_MSP_REG_GCR ( \ + GEN_MASK_BITS(MSP_RECEIVER_DISABLED, MSP_GCR_MASK_RXEN, 0) |\ + GEN_MASK_BITS(MSP_RX_FIFO_ENABLED, MSP_GCR_MASK_RFFEN, 1) |\ + GEN_MASK_BITS(MSP_LOOPBACK_DISABLED, MSP_GCR_MASK_LBM, 7) |\ + GEN_MASK_BITS(MSP_TRANSMITTER_DISABLED, MSP_GCR_MASK_TXEN, 8) |\ + GEN_MASK_BITS(MSP_TX_FIFO_ENABLED, MSP_GCR_MASK_TFFEN, 9) |\ + GEN_MASK_BITS(MSP_TX_FRAME_SYNC_POL_LOW, MSP_GCR_MASK_TFSPOL, 10)|\ + GEN_MASK_BITS(MSP_TX_FRAME_SYNC_INT, MSP_GCR_MASK_TFSSEL, 11) |\ + GEN_MASK_BITS(MSP_TX_CLOCK_POL_HIGH, MSP_GCR_MASK_TCKPOL, 13) |\ + GEN_MASK_BITS(MSP_IS_SPI_MASTER, MSP_GCR_MASK_TCKSEL, 14) |\ + GEN_MASK_BITS(MSP_TRANSMIT_DATA_WITHOUT_DELAY, MSP_GCR_MASK_TXDDL, 15)|\ + GEN_MASK_BITS(MSP_SAMPLE_RATE_GEN_ENABLE, MSP_GCR_MASK_SGEN, 16)|\ + GEN_MASK_BITS(MSP_CLOCK_INTERNAL, MSP_GCR_MASK_SCKSEL, 18) |\ + GEN_MASK_BITS(MSP_FRAME_GEN_ENABLE, MSP_GCR_MASK_FGEN, 20) |\ + GEN_MASK_BITS(MSP_SPI_PHASE_ZERO_CYCLE_DELAY, MSP_GCR_MASK_SPICKM, 21)|\ + GEN_MASK_BITS(SPI_BURST_MODE_DISABLE, MSP_GCR_MASK_SPIBME, 23)\ + ) +#define DEFAULT_MSP_REG_RCF ( \ + GEN_MASK_BITS(MSP_DATA_BITS_32, MSP_RCF_MASK_RP1ELEN, 0) | \ + GEN_MASK_BITS(MSP_IGNORE_RX_FRAME_SYNC_PULSE, MSP_RCF_MASK_RFSIG, 15) |\ + GEN_MASK_BITS(MSP_RX_1BIT_DATA_DELAY, MSP_RCF_MASK_RDDLY, 13) | \ + GEN_MASK_BITS(MSP_RX_ENDIANESS_LSB, MSP_RCF_MASK_RENDN, 12) \ + ) + +#define DEFAULT_MSP_REG_TCF ( \ + GEN_MASK_BITS(MSP_DATA_BITS_32, MSP_TCF_MASK_TP1ELEN, 0) | \ + GEN_MASK_BITS(MSP_IGNORE_TX_FRAME_SYNC_PULSE, MSP_TCF_MASK_TFSIG, 15) |\ + GEN_MASK_BITS(MSP_TX_1BIT_DATA_DELAY, MSP_TCF_MASK_TDDLY, 13) | \ + GEN_MASK_BITS(MSP_TX_ENDIANESS_LSB, MSP_TCF_MASK_TENDN, 12) \ + ) + +/** + * MSP Receiver/Transmitter states (enabled or disabled) + */ +#define MSP_RECEIVER_DISABLED 0 +#define MSP_RECEIVER_ENABLED 1 +#define MSP_TRANSMITTER_DISABLED 0 +#define MSP_TRANSMITTER_ENABLED 1 + +/** + * MSP Receiver/Transmitter FIFO constants + */ +#define MSP_LOOPBACK_DISABLED 0 +#define MSP_LOOPBACK_ENABLED 1 + +#define MSP_TX_FIFO_DISABLED 0 +#define MSP_TX_FIFO_ENABLED 1 +#define MSP_TX_ENDIANESS_MSB 0 +#define MSP_TX_ENDIANESS_LSB 1 + +#define MSP_RX_FIFO_DISABLED 0 +#define MSP_RX_FIFO_ENABLED 1 +#define MSP_RX_ENDIANESS_MSB 0 +#define MSP_RX_ENDIANESS_LSB 1 + +#define MSP_TX_FRAME_SYNC_EXT 0x0 +#define MSP_TX_FRAME_SYNC_INT 0x2 +#define MSP_TX_FRAME_SYNC_INT_CFG 0x3 + +#define MSP_TX_FRAME_SYNC_POL_HIGH 0 +#define MSP_TX_FRAME_SYNC_POL_LOW 1 + +#define MSP_HANDLE_RX_FRAME_SYNC_PULSE 0 +#define MSP_IGNORE_RX_FRAME_SYNC_PULSE 1 + +#define MSP_RX_NO_DATA_DELAY 0x0 +#define MSP_RX_1BIT_DATA_DELAY 0x1 +#define MSP_RX_2BIT_DATA_DELAY 0x2 +#define MSP_RX_3BIT_DATA_DELAY 0x3 + +#define MSP_HANDLE_TX_FRAME_SYNC_PULSE 0 +#define MSP_IGNORE_TX_FRAME_SYNC_PULSE 1 + +#define MSP_TX_NO_DATA_DELAY 0x0 +#define MSP_TX_1BIT_DATA_DELAY 0x1 +#define MSP_TX_2BIT_DATA_DELAY 0x2 +#define MSP_TX_3BIT_DATA_DELAY 0x3 + +#define MSP_TX_CLOCK_POL_LOW 0 +#define MSP_TX_CLOCK_POL_HIGH 1 + +#define MSP_SPI_PHASE_ZERO_CYCLE_DELAY 0x2 +#define MSP_SPI_PHASE_HALF_CYCLE_DELAY 0x3 + +#define MSP_IS_SPI_SLAVE 0 +#define MSP_IS_SPI_MASTER 1 + +#define MSP_FRAME_GEN_DISABLE 0 +#define MSP_FRAME_GEN_ENABLE 1 + +#define MSP_SAMPLE_RATE_GEN_DISABLE 0 +#define MSP_SAMPLE_RATE_GEN_ENABLE 1 + +#define SPI_BURST_MODE_DISABLE 0 +#define SPI_BURST_MODE_ENABLE 1 + +#define MSP_TRANSMIT_DATA_WITHOUT_DELAY 0 +#define MSP_TRANSMIT_DATA_WITH_DELAY 1 + +#define MSP_CLOCK_INTERNAL 0x0 /* 48 MHz */ + +/* SRG is derived from MSPSCK pin but is resynchronized on MSPRFS + * (Receive Frame Sync signal) */ +#define MSP_CLOCK_EXTERNAL 0x2 +#define MSP_CLOCK_EXTERNAL_RESYNC 0x3 + +#define DISABLE_ALL_MSP_INTERRUPTS (0x0) +#define ENABLE_ALL_MSP_INTERRUPTS (0x333) +#define CLEAR_ALL_MSP_INTERRUPTS (0xEE) +#define DEFAULT_MSP_CLK (48000000) +#define MAX_SCKDIV (1023) + +#define MSP_FIFO_DEPTH 8 + +/** + * Queue State + */ +#define QUEUE_RUNNING (0) +#define QUEUE_STOPPED (1) + +#define START_STATE ((void *)0) +#define RUNNING_STATE ((void *)1) +#define DONE_STATE ((void *)2) +#define ERROR_STATE ((void *)-1) + +/* Default values */ +#define SPI_DEFAULT_MAX_SPEED_HZ 48000 +#define SPI_TRANSFER_TIMEOUT_MS 5000 + +/* CONTROLLER COMMANDS */ +enum cntlr_commands { + DISABLE_CONTROLLER = 0, + ENABLE_CONTROLLER , + DISABLE_ALL_INTERRUPT , + ENABLE_ALL_INTERRUPT , + FLUSH_FIFO , + RESTORE_STATE , + LOAD_DEFAULT_CONFIG , + CLEAR_ALL_INTERRUPT, +}; + +struct stm_msp { + struct amba_device *adev; + struct spi_master *master; + struct stm_msp_controller *master_info; + void __iomem *regs; + struct clk *clk; +#ifdef CONFIG_SPI_WORKQUEUE + struct workqueue_struct *workqueue; +#endif + struct work_struct spi_work; + spinlock_t lock; + struct list_head queue; + int busy; + int run; + struct tasklet_struct pump_transfers; + struct timer_list spi_notify_timer; + int spi_io_error; + struct spi_message *cur_msg; + struct spi_transfer *cur_transfer; + struct chip_data *cur_chip; + void *tx; + void *tx_end; + void *rx; + void *rx_end; + void (*write)(struct stm_msp *stm_msp); + void (*read)(struct stm_msp *stm_msp); + void (*delay)(struct stm_msp *stm_msp); +}; + +/** + * struct chip_data - To maintain runtime state of SPICntlr for each client chip + * @ctr_regs: void pointer which is assigned a struct having regs of the cntlr. + * @chip_id: Chip Id assigned to this client to identify it. + * @n_bytes: how many bytes(power of 2) reqd for a given data width of client + * @write: function to be used to write when doing xfer for this chip + * @null_write: function to be used for dummy write for receiving data. + * @read: function to be used to read when doing xfer for this chip + * @null_read: function to be used to for dummy read while writting data. + * @cs_control: chip select callback provided by chip + * @xfer_type: polling/interrupt + * + * Runtime state of the SPI controller, maintained per chip, + * This would be set according to the current message that would be served + */ +struct chip_data { + void *ctr_regs; + u32 chip_id; + u8 n_bytes; + void (*write) (struct stm_msp *stm_msp); + void (*null_write) (struct stm_msp *stm_msp); + void (*read) (struct stm_msp *stm_msp); + void (*null_read) (struct stm_msp *stm_msp); + void (*delay) (struct stm_msp *stm_msp); + void (*cs_control) (u32 command); + int xfer_type; +}; + +/** + * struct msp_regs - Used to store MSP controller registry values + * used by the driver. + * @gcr: global configuration register + * @tcf: transmit configuration register + * @rcf: receive configuration register + * @srg: sample rate generator register + * @dmacr: DMA configuration register + */ +struct msp_regs { + u32 gcr; + u32 tcf; + u32 rcf; + u32 srg; + u32 dmacr; +}; + +/** + * stm_msp_controller_cmd - To execute controller commands for MSP + * @stm_msp: SPI driver private data structure + * @cmd: Command which is to be executed on the controller + */ +static int stm_msp_controller_cmd(struct stm_msp *stm_msp, int cmd) +{ + int retval = 0; + struct msp_regs *msp_regs = NULL; + + switch (cmd) { + case DISABLE_CONTROLLER: { + dev_dbg(&stm_msp->adev->dev, + "Disabling MSP controller...\n"); + writel((readl(MSP_GCR(stm_msp->regs)) & + (~(MSP_GCR_MASK_TXEN | MSP_GCR_MASK_RXEN))), + MSP_GCR(stm_msp->regs)); + break; + } + case ENABLE_CONTROLLER: { + dev_dbg(&stm_msp->adev->dev, + "Enabling MSP controller...\n"); + writel((readl(MSP_GCR(stm_msp->regs)) | + (MSP_GCR_MASK_TXEN | MSP_GCR_MASK_RXEN)), + MSP_GCR(stm_msp->regs)); + break; + } + case DISABLE_ALL_INTERRUPT: { + dev_dbg(&stm_msp->adev->dev, + "Disabling all MSP interrupts...\n"); + writel(DISABLE_ALL_MSP_INTERRUPTS, + MSP_IMSC(stm_msp->regs)); + break; + } + case ENABLE_ALL_INTERRUPT: { + dev_dbg(&stm_msp->adev->dev, + "Enabling all MSP interrupts...\n"); + writel(ENABLE_ALL_MSP_INTERRUPTS, + MSP_IMSC(stm_msp->regs)); + break; + } + case CLEAR_ALL_INTERRUPT: { + dev_dbg(&stm_msp->adev->dev, + "Clearing all MSP interrupts...\n"); + writel(CLEAR_ALL_MSP_INTERRUPTS, + MSP_ICR(stm_msp->regs)); + break; + } + case FLUSH_FIFO: { + unsigned long limit = loops_per_jiffy << 1; + + dev_dbg(&stm_msp->adev->dev, "MSP FIFO flushed\n"); + + do { + while (!(readl(MSP_FLR(stm_msp->regs)) & + MSP_FLR_MASK_RFE)) { + readl(MSP_DR(stm_msp->regs)); + } + } while ((readl(MSP_FLR(stm_msp->regs)) & + (MSP_FLR_MASK_TBUSY | MSP_FLR_MASK_RBUSY)) && + limit--); + + retval = limit; + break; + } + case RESTORE_STATE: { + msp_regs = + (struct msp_regs *)stm_msp->cur_chip->ctr_regs; + + dev_dbg(&stm_msp->adev->dev, + "Restoring MSP state...\n"); + + writel(msp_regs->gcr, MSP_GCR(stm_msp->regs)); + writel(msp_regs->tcf, MSP_TCF(stm_msp->regs)); + writel(msp_regs->rcf, MSP_RCF(stm_msp->regs)); + writel(msp_regs->srg, MSP_SRG(stm_msp->regs)); + writel(msp_regs->dmacr, MSP_DMACR(stm_msp->regs)); + writel(DISABLE_ALL_MSP_INTERRUPTS, + MSP_IMSC(stm_msp->regs)); + writel(CLEAR_ALL_MSP_INTERRUPTS, + MSP_ICR(stm_msp->regs)); + break; + } + case LOAD_DEFAULT_CONFIG: { + dev_dbg(&stm_msp->adev->dev, + "Loading default MSP config...\n"); + + writel(DEFAULT_MSP_REG_GCR, MSP_GCR(stm_msp->regs)); + writel(DEFAULT_MSP_REG_TCF, MSP_TCF(stm_msp->regs)); + writel(DEFAULT_MSP_REG_RCF, MSP_RCF(stm_msp->regs)); + writel(DEFAULT_MSP_REG_SRG, MSP_SRG(stm_msp->regs)); + writel(DEFAULT_MSP_REG_DMACR, MSP_DMACR(stm_msp->regs)); + writel(DISABLE_ALL_MSP_INTERRUPTS, + MSP_IMSC(stm_msp->regs)); + writel(CLEAR_ALL_MSP_INTERRUPTS, + MSP_ICR(stm_msp->regs)); + break; + } + default: + dev_dbg(&stm_msp->adev->dev, "Unknown command\n"); + retval = -1; + break; + } + + return retval; +} + +/** + * giveback - current spi_message is over, schedule next spi_message + * @message: current SPI message + * @stm_msp: spi driver private data structure + * + * current spi_message is over, schedule next spi_message and call + * callback of this msg. + */ +static void giveback(struct spi_message *message, struct stm_msp *stm_msp) +{ + struct spi_transfer *last_transfer; + unsigned long flags; + struct spi_message *msg; + void (*curr_cs_control)(u32 command); + + spin_lock_irqsave(&stm_msp->lock, flags); + msg = stm_msp->cur_msg; + + curr_cs_control = stm_msp->cur_chip->cs_control; + + stm_msp->cur_msg = NULL; + stm_msp->cur_transfer = NULL; + stm_msp->cur_chip = NULL; +#ifdef CONFIG_SPI_WORKQUEUE + queue_work(stm_msp->workqueue, &stm_msp->spi_work); +#else + schedule_work(&stm_msp->spi_work); +#endif + spin_unlock_irqrestore(&stm_msp->lock, flags); + + last_transfer = list_entry(msg->transfers.prev, + struct spi_transfer, transfer_list); + + if (!last_transfer->cs_change) + curr_cs_control(SPI_CHIP_DESELECT); + + msg->state = NULL; + + if (msg->complete) + msg->complete(msg->context); + + stm_msp_controller_cmd(stm_msp, DISABLE_CONTROLLER); + clk_disable(stm_msp->clk); +} + +/** + * spi_notify - Handles Polling hang issue over spi bus. + * @data: main driver data + * Context: Process. + * + * This is used to handle error condition in transfer and receive function used + * in polling mode. + * Sometimes due to passing wrong protocol desc , polling transfer may hang. + * To prevent this, timer is added. + * + * Returns void. + */ +static void spi_notify(unsigned long data) +{ + struct stm_msp *stm_msp = (struct stm_msp *)data; + stm_msp->spi_io_error = 1; + + dev_err(&stm_msp->adev->dev, + "Polling is taking time, maybe device not responding\n"); + + del_timer(&stm_msp->spi_notify_timer); +} + +/** + * stm_msp_transfer - transfer function registered to SPI master framework + * @spi: spi device which is requesting transfer + * @msg: spi message which is to handled is queued to driver queue + * + * This function is registered to the SPI framework for this SPI master + * controller. It will queue the spi_message in the queue of driver if + * the queue is not stopped and return. + */ +static int stm_msp_transfer(struct spi_device *spi, struct spi_message *msg) +{ + struct stm_msp *stm_msp = spi_master_get_devdata(spi->master); + unsigned long flags; + + spin_lock_irqsave(&stm_msp->lock, flags); + + if (stm_msp->run == QUEUE_STOPPED) { + spin_unlock_irqrestore(&stm_msp->lock, flags); + return -ESHUTDOWN; + } + dev_err(&spi->dev, "Regular request (No infinite DMA ongoing)\n"); + + msg->actual_length = 0; + msg->status = -EINPROGRESS; + msg->state = START_STATE; + + list_add_tail(&msg->queue, &stm_msp->queue); + + if ((stm_msp->run == QUEUE_RUNNING) && (!stm_msp->busy)) +#ifdef CONFIG_SPI_WORKQUEUE + queue_work(stm_msp->workqueue, &stm_msp->spi_work); +#else + schedule_work(&stm_msp->spi_work); +#endif + spin_unlock_irqrestore(&stm_msp->lock, flags); + return 0; +} + +/** + * next_transfer - Move to the Next transfer in the current spi message + * @stm_msp: spi driver private data structure + * + * This function moves though the linked list of spi transfers in the + * current spi message and returns with the state of current spi + * message i.e whether its last transfer is done(DONE_STATE) or + * Next transfer is ready(RUNNING_STATE) + */ +static void *next_transfer(struct stm_msp *stm_msp) +{ + struct spi_message *msg = stm_msp->cur_msg; + struct spi_transfer *trans = stm_msp->cur_transfer; + + /* Move to next transfer */ + if (trans->transfer_list.next != &msg->transfers) { + stm_msp->cur_transfer = list_entry(trans->transfer_list.next, + struct spi_transfer, + transfer_list); + return RUNNING_STATE; + } + return DONE_STATE; +} + +static void do_interrupt_transfer(void *data) +{ + struct stm_msp *stm_msp = (struct stm_msp *)data; + + stm_msp->tx = (void *)stm_msp->cur_transfer->tx_buf; + stm_msp->tx_end = stm_msp->tx + stm_msp->cur_transfer->len; + + stm_msp->rx = (void *)stm_msp->cur_transfer->rx_buf; + stm_msp->rx_end = stm_msp->rx + stm_msp->cur_transfer->len; + + stm_msp->write = stm_msp->tx ? + stm_msp->cur_chip->write : stm_msp->cur_chip->null_write; + stm_msp->read = stm_msp->rx ? + stm_msp->cur_chip->read : stm_msp->cur_chip->null_read; + + stm_msp->cur_chip->cs_control(SPI_CHIP_SELECT); + + stm_msp_controller_cmd(stm_msp, ENABLE_ALL_INTERRUPT); + stm_msp_controller_cmd(stm_msp, ENABLE_CONTROLLER); +} + +static void do_polling_transfer(void *data) +{ + struct stm_msp *stm_msp = (struct stm_msp *)data; + struct spi_message *message = NULL; + struct spi_transfer *transfer = NULL; + struct spi_transfer *previous = NULL; + struct chip_data *chip; + unsigned long limit = 0; + u32 timer_expire = 0; + + chip = stm_msp->cur_chip; + message = stm_msp->cur_msg; + + while (message->state != DONE_STATE) { + /* Handle for abort */ + if (message->state == ERROR_STATE) + break; + + transfer = stm_msp->cur_transfer; + + /* Delay if requested at end of transfer */ + if (message->state == RUNNING_STATE) { + previous = list_entry(transfer->transfer_list.prev, + struct spi_transfer, + transfer_list); + + if (previous->delay_usecs) + udelay(previous->delay_usecs); + + if (previous->cs_change) + stm_msp->cur_chip->cs_control(SPI_CHIP_SELECT); + } else { + /* START_STATE */ + message->state = RUNNING_STATE; + stm_msp->cur_chip->cs_control(SPI_CHIP_SELECT); + } + + /* Configuration Changing Per Transfer */ + stm_msp->tx = (void *)transfer->tx_buf; + stm_msp->tx_end = stm_msp->tx + stm_msp->cur_transfer->len; + stm_msp->rx = (void *)transfer->rx_buf; + stm_msp->rx_end = stm_msp->rx + stm_msp->cur_transfer->len; + + stm_msp->write = stm_msp->tx ? + stm_msp->cur_chip->write : + stm_msp->cur_chip->null_write; + stm_msp->read = stm_msp->rx ? + stm_msp->cur_chip->read : + stm_msp->cur_chip->null_read; + stm_msp->delay = stm_msp->cur_chip->delay; + + stm_msp_controller_cmd(stm_msp, FLUSH_FIFO); + stm_msp_controller_cmd(stm_msp, ENABLE_CONTROLLER); + + timer_expire = stm_msp->cur_transfer->len / 1024; + + if (!timer_expire) + timer_expire = SPI_TRANSFER_TIMEOUT_MS; + else + timer_expire = + (stm_msp->cur_transfer->len / 1024) * + SPI_TRANSFER_TIMEOUT_MS; + + stm_msp->spi_notify_timer.expires = + jiffies + msecs_to_jiffies(timer_expire); + + add_timer(&stm_msp->spi_notify_timer); + + dev_dbg(&stm_msp->adev->dev, "Polling transfer ongoing...\n"); + + while (stm_msp->tx < stm_msp->tx_end) { + + stm_msp_controller_cmd(stm_msp, DISABLE_CONTROLLER); + stm_msp->read(stm_msp); + stm_msp->write(stm_msp); + + stm_msp_controller_cmd(stm_msp, ENABLE_CONTROLLER); + + if (stm_msp->delay) + stm_msp->delay(stm_msp); + + if (stm_msp->spi_io_error == 1) + break; + } + + del_timer(&stm_msp->spi_notify_timer); + + if (stm_msp->spi_io_error == 1) + goto out; + + limit = loops_per_jiffy << 1; + + while ((stm_msp->rx < stm_msp->rx_end) && (limit--)) + stm_msp->read(stm_msp); + + /* Update total byte transfered */ + message->actual_length += stm_msp->cur_transfer->len; + + if (stm_msp->cur_transfer->cs_change) + stm_msp->cur_chip->cs_control(SPI_CHIP_DESELECT); + + stm_msp_controller_cmd(stm_msp, DISABLE_CONTROLLER); + + /* Move to next transfer */ + message->state = next_transfer(stm_msp); + } +out: + /* Handle end of message */ + if (message->state == DONE_STATE) + message->status = 0; + else + message->status = -EIO; + + giveback(message, stm_msp); + + stm_msp->spi_io_error = 0; /* Reset state for further transfers */ + + return; +} + +/** + * pump_messages - Workqueue function which processes spi message queue + * @work: pointer to work + * + * This function checks if there is any spi message in the queue that + * needs processing and delegate control to appropriate function + * do_polling_transfer()/do_interrupt_transfer()/do_dma_transfer() + * based on the kind of the transfer + * + */ +static void pump_messages(struct work_struct *work) +{ + struct stm_msp *stm_msp = container_of(work, struct stm_msp, spi_work); + unsigned long flags; + + /* Lock queue and check for queue work */ + spin_lock_irqsave(&stm_msp->lock, flags); + + if (list_empty(&stm_msp->queue) || stm_msp->run == QUEUE_STOPPED) { + dev_dbg(&stm_msp->adev->dev, "work_queue: Queue Empty\n"); + stm_msp->busy = 0; + spin_unlock_irqrestore(&stm_msp->lock, flags); + return; + } + /* Make sure we are not already running a message */ + if (stm_msp->cur_msg) { + spin_unlock_irqrestore(&stm_msp->lock, flags); + return; + } + + clk_enable(stm_msp->clk); + + /* Extract head of queue */ + stm_msp->cur_msg = list_entry(stm_msp->queue.next, + struct spi_message, + queue); + + list_del_init(&stm_msp->cur_msg->queue); + stm_msp->busy = 1; + spin_unlock_irqrestore(&stm_msp->lock, flags); + + /* Initial message state */ + stm_msp->cur_msg->state = START_STATE; + stm_msp->cur_transfer = list_entry(stm_msp->cur_msg->transfers.next, + struct spi_transfer, + transfer_list); + + /* Setup the SPI using the per chip configuration */ + stm_msp->cur_chip = spi_get_ctldata(stm_msp->cur_msg->spi); + stm_msp_controller_cmd(stm_msp, RESTORE_STATE); + stm_msp_controller_cmd(stm_msp, FLUSH_FIFO); + + if (stm_msp->cur_chip->xfer_type == SPI_POLLING_TRANSFER) + do_polling_transfer(stm_msp); + else if (stm_msp->cur_chip->xfer_type == SPI_INTERRUPT_TRANSFER) + do_interrupt_transfer(stm_msp); +} + +/** + * pump_transfers - Tasklet function which schedules next interrupt xfer + * @data: spi driver private data structure + */ +static void pump_transfers(unsigned long data) +{ + struct stm_msp *stm_msp = (struct stm_msp *)data; + struct spi_message *message = NULL; + struct spi_transfer *transfer = NULL; + struct spi_transfer *previous = NULL; + + message = stm_msp->cur_msg; + + /* Handle for abort */ + if (message->state == ERROR_STATE) { + message->status = -EIO; + giveback(message, stm_msp); + return; + } + + /* Handle end of message */ + if (message->state == DONE_STATE) { + message->status = 0; + giveback(message, stm_msp); + return; + } + transfer = stm_msp->cur_transfer; + + /* Delay if requested at end of transfer */ + if (message->state == RUNNING_STATE) { + previous = list_entry(transfer->transfer_list.prev, + struct spi_transfer, transfer_list); + if (previous->delay_usecs) + udelay(previous->delay_usecs); + if (previous->cs_change) + stm_msp->cur_chip->cs_control(SPI_CHIP_SELECT); + } else { + /* START_STATE */ + message->state = RUNNING_STATE; + } + stm_msp->tx = (void *)transfer->tx_buf; + stm_msp->tx_end = stm_msp->tx + stm_msp->cur_transfer->len; + stm_msp->rx = (void *)transfer->rx_buf; + stm_msp->rx_end = stm_msp->rx + stm_msp->cur_transfer->len; + + stm_msp->write = stm_msp->tx ? + stm_msp->cur_chip->write : stm_msp->cur_chip->null_write; + stm_msp->read = stm_msp->rx ? + stm_msp->cur_chip->read : stm_msp->cur_chip->null_read; + + stm_msp_controller_cmd(stm_msp, FLUSH_FIFO); + stm_msp_controller_cmd(stm_msp, ENABLE_ALL_INTERRUPT); +} + +static int init_queue(struct stm_msp *stm_msp) +{ + INIT_LIST_HEAD(&stm_msp->queue); + spin_lock_init(&stm_msp->lock); + + stm_msp->run = QUEUE_STOPPED; + stm_msp->busy = 0; + + tasklet_init(&stm_msp->pump_transfers, pump_transfers, + (unsigned long)stm_msp); + INIT_WORK(&stm_msp->spi_work, pump_messages); + +#ifdef CONFIG_SPI_WORKQUEUE + stm_msp->workqueue = create_singlethread_workqueue( + dev_name(&stm_msp->master->dev)); + + if (stm_msp->workqueue == NULL) + return -EBUSY; +#endif /* CONFIG_SPI_WORKQUEUE */ + + init_timer(&stm_msp->spi_notify_timer); + + stm_msp->spi_notify_timer.expires = jiffies + msecs_to_jiffies(1000); + stm_msp->spi_notify_timer.function = spi_notify; + stm_msp->spi_notify_timer.data = (unsigned long)stm_msp; + + return 0; +} + +static int start_queue(struct stm_msp *stm_msp) +{ + unsigned long flags; + + spin_lock_irqsave(&stm_msp->lock, flags); + + if (stm_msp->run == QUEUE_RUNNING || stm_msp->busy) { + spin_unlock_irqrestore(&stm_msp->lock, flags); + return -EBUSY; + } + + stm_msp->run = QUEUE_RUNNING; + stm_msp->cur_msg = NULL; + stm_msp->cur_transfer = NULL; + stm_msp->cur_chip = NULL; + spin_unlock_irqrestore(&stm_msp->lock, flags); + return 0; +} + +static int stop_queue(struct stm_msp *stm_msp) +{ + unsigned long flags; + unsigned limit = 500; + int status = 0; + + spin_lock_irqsave(&stm_msp->lock, flags); + + /* This is a bit lame, but is optimized for the common execution path. + * A wait_queue on the stm_msp->busy could be used, but then the common + * execution path (pump_messages) would be required to call wake_up or + * friends on every SPI message. Do this instead */ + + stm_msp->run = QUEUE_STOPPED; + + while (!list_empty(&stm_msp->queue) && stm_msp->busy && limit--) { + spin_unlock_irqrestore(&stm_msp->lock, flags); + msleep(10); + spin_lock_irqsave(&stm_msp->lock, flags); + } + + if (!list_empty(&stm_msp->queue) || stm_msp->busy) + status = -EBUSY; + + spin_unlock_irqrestore(&stm_msp->lock, flags); + + return status; +} + +static int destroy_queue(struct stm_msp *stm_msp) +{ + int status; + + status = stop_queue(stm_msp); + + if (status != 0) + return status; +#ifdef CONFIG_SPI_WORKQUEUE + destroy_workqueue(stm_msp->workqueue); +#endif + del_timer_sync(&stm_msp->spi_notify_timer); + + return 0; +} + +/** + * stm_msp_null_writer - To Write Dummy Data in Data register + * @stm_msp: spi driver private data structure + * + * This function is set as a write function for transfer which have + * Tx transfer buffer as NULL. It simply writes '0' in the Data + * register + */ +static void stm_msp_null_writer(struct stm_msp *stm_msp) +{ + u32 cur_write = 0; + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_TFU) || + (stm_msp->tx >= stm_msp->tx_end)) + return; + + writel(0x0, MSP_DR(stm_msp->regs)); + stm_msp->tx += (stm_msp->cur_chip->n_bytes); + cur_write++; + + if (cur_write == 8) + return; + } +} + +/** + * stm_msp_null_reader - To read data from Data register and discard it + * @stm_msp: spi driver private data structure + * + * This function is set as a reader function for transfer which have + * Rx Transfer buffer as null. Read Data is rejected + */ +static void stm_msp_null_reader(struct stm_msp *stm_msp) +{ + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_RFE) || + (stm_msp->rx >= stm_msp->rx_end)) + return; + + readl(MSP_DR(stm_msp->regs)); + stm_msp->rx += (stm_msp->cur_chip->n_bytes); + } +} + +/** + * stm_msp_u8_writer - Write FIFO data in Data register as a 8 Bit Data + * @stm_msp: spi driver private data structure + * + * This function writes data in Tx FIFO till it is not full + * which is indicated by the status register or our transfer is complete. + * It also updates the temporary write ptr tx in stm_msp which maintains + * current write position in transfer buffer. we do not write data more than + * FIFO depth + */ +void stm_msp_u8_writer(struct stm_msp *stm_msp) +{ + u32 cur_write = 0; + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_TFU) || + (stm_msp->tx >= stm_msp->tx_end)) + return; + + writel((u32)(*(u8 *)(stm_msp->tx)), MSP_DR(stm_msp->regs)); + stm_msp->tx += (stm_msp->cur_chip->n_bytes); + cur_write++; + + if (cur_write == MSP_FIFO_DEPTH) + return; + } +} + +/** + * stm_msp_u8_reader - Read FIFO data in Data register as a 8 Bit Data + * @stm_msp: spi driver private data structure + * + * This function reads data in Rx FIFO till it is not empty + * which is indicated by the status register or our transfer is complete. + * It also updates the temporary Read ptr rx in stm_msp which maintains + * current read position in transfer buffer + */ +void stm_msp_u8_reader(struct stm_msp *stm_msp) +{ + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_RFE) || + (stm_msp->rx >= stm_msp->rx_end)) + return; + + *(u8 *)(stm_msp->rx) = (u8)readl(MSP_DR(stm_msp->regs)); + stm_msp->rx += (stm_msp->cur_chip->n_bytes); + } +} + +/** + * stm_msp_u16_writer - Write FIFO data in Data register as a 16 Bit Data + * @stm_msp: spi driver private data structure + * + * This function writes data in Tx FIFO till it is not full + * which is indicated by the status register or our transfer is complete. + * It also updates the temporary write ptr tx in stm_msp which maintains + * current write position in transfer buffer. we do not write data more than + * FIFO depth + */ +void stm_msp_u16_writer(struct stm_msp *stm_msp) +{ + u32 cur_write = 0; + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_TFU) || + (stm_msp->tx >= stm_msp->tx_end)) + return; + + writel((u32)(*(u16 *)(stm_msp->tx)), MSP_DR(stm_msp->regs)); + stm_msp->tx += (stm_msp->cur_chip->n_bytes); + cur_write++; + + if (cur_write == MSP_FIFO_DEPTH) + return; + } +} + +/** + * stm_msp_u16_reader - Read FIFO data in Data register as a 16 Bit Data + * @stm_msp: spi driver private data structure + * + * This function reads data in Rx FIFO till it is not empty + * which is indicated by the status register or our transfer is complete. + * It also updates the temporary Read ptr rx in stm_msp which maintains + * current read position in transfer buffer + */ +void stm_msp_u16_reader(struct stm_msp *stm_msp) +{ + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_RFE) || + (stm_msp->rx >= stm_msp->rx_end)) + return; + + *(u16 *)(stm_msp->rx) = (u16)readl(MSP_DR(stm_msp->regs)); + stm_msp->rx += (stm_msp->cur_chip->n_bytes); + } +} + +/** + * stm_msp_u32_writer - Write FIFO data in Data register as a 32 Bit Data + * @stm_msp: spi driver private data structure + * + * This function writes data in Tx FIFO till it is not full + * which is indicated by the status register or our transfer is complete. + * It also updates the temporary write ptr tx in stm_msp which maintains + * current write position in transfer buffer. we do not write data more than + * FIFO depth + */ +void stm_msp_u32_writer(struct stm_msp *stm_msp) +{ + u32 cur_write = 0; + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_TFU) || + (stm_msp->tx >= stm_msp->tx_end)) + return; + + /* Write Data to Data Register */ + writel(*(u32 *)(stm_msp->tx), MSP_DR(stm_msp->regs)); + stm_msp->tx += (stm_msp->cur_chip->n_bytes); + cur_write++; + + if (cur_write == MSP_FIFO_DEPTH) + return; + } +} + +/** + * stm_msp_u32_reader - Read FIFO data in Data register as a 32 Bit Data + * @stm_msp: spi driver private data structure + * + * This function reads data in Rx FIFO till it is not empty + * which is indicated by the status register or our transfer is complete. + * It also updates the temporary Read ptr rx in stm_msp which maintains + * current read position in transfer buffer + */ +void stm_msp_u32_reader(struct stm_msp *stm_msp) +{ + u32 status; + + while (1) { + status = readl(MSP_FLR(stm_msp->regs)); + + if ((status & MSP_FLR_MASK_RFE) || + (stm_msp->rx >= stm_msp->rx_end)) + return; + + *(u32 *)(stm_msp->rx) = readl(MSP_DR(stm_msp->regs)); + stm_msp->rx += (stm_msp->cur_chip->n_bytes); + } +} + +/** + * stm_msp_interrupt_handler - Interrupt hanlder function + */ +static irqreturn_t stm_msp_interrupt_handler(int irq, void *dev_id) +{ + struct stm_msp *stm_msp = (struct stm_msp *)dev_id; + struct spi_message *msg = stm_msp->cur_msg; + u32 irq_status = 0; + u32 flag = 0; + + if (!msg) { + dev_err(&stm_msp->adev->dev, + "Bad message state in interrupt handler"); + /* Never fail */ + return IRQ_HANDLED; + } + + /* Read the Interrupt Status Register */ + irq_status = readl(MSP_MIS(stm_msp->regs)); + + if (irq_status) { + if (irq_status & MSP_MIS_MASK_ROEMIS) { /* Overrun interrupt */ + /* Bail out our Data has been corrupted */ + dev_dbg(&stm_msp->adev->dev, + "Received ROR interrupt\n"); + + stm_msp_controller_cmd(stm_msp, DISABLE_ALL_INTERRUPT); + stm_msp_controller_cmd(stm_msp, CLEAR_ALL_INTERRUPT); + stm_msp_controller_cmd(stm_msp, DISABLE_CONTROLLER); + msg->state = ERROR_STATE; + tasklet_schedule(&stm_msp->pump_transfers); + return IRQ_HANDLED; + } + + stm_msp->read(stm_msp); + stm_msp->write(stm_msp); + + if ((stm_msp->tx == stm_msp->tx_end) && (flag == 0)) { + flag = 1; + /* Disable Transmit interrupt */ + writel(readl(MSP_IMSC(stm_msp->regs)) & + (~MSP_IMSC_MASK_TXIM) & (~MSP_IMSC_MASK_TFOIM), + (stm_msp->regs + 0x14)); + } + + /* Clearing any Xmit underrun error. Overrun already handled */ + stm_msp_controller_cmd(stm_msp, CLEAR_ALL_INTERRUPT); + + if (stm_msp->rx == stm_msp->rx_end) { + stm_msp_controller_cmd(stm_msp, DISABLE_ALL_INTERRUPT); + stm_msp_controller_cmd(stm_msp, CLEAR_ALL_INTERRUPT); + + dev_dbg(&stm_msp->adev->dev, + "Interrupt transfer completed.\n"); + + /* Update total bytes transfered */ + msg->actual_length += stm_msp->cur_transfer->len; + + if (stm_msp->cur_transfer->cs_change) + stm_msp->cur_chip->cs_control( + SPI_CHIP_DESELECT); + + /* Move to next transfer */ + msg->state = next_transfer(stm_msp); + tasklet_schedule(&stm_msp->pump_transfers); + return IRQ_HANDLED; + } + } + return IRQ_HANDLED; +} + +/** + * stm_msp_cleanup - cleanup function registered to SPI master framework + * @spi: spi device which is requesting cleanup + * + * This function is registered to the SPI framework for this SPI master + * controller. It will free the runtime state of chip. + */ +static void stm_msp_cleanup(struct spi_device *spi) +{ + struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi); + struct stm_msp *stm_msp = spi_master_get_devdata(spi->master); + struct spi_master *master; + master = stm_msp->master; + + if (chip) { + kfree(chip->ctr_regs); + kfree(chip); + spi_set_ctldata(spi, NULL); + } +} + +/** + * null_cs_control - Dummy chip select function + * @command: select/delect the chip + * + * If no chip select function is provided by client this is used as dummy + * chip select + */ +static void null_cs_control(u32 command) +{ + /* Nothing to do */ + (void)command; +} + +static int verify_msp_controller_parameters(struct stm_msp_config_chip + *chip_info) +{ + + /* FIXME: check clock params */ + if ((chip_info->lbm != SPI_LOOPBACK_ENABLED) && + (chip_info->lbm != SPI_LOOPBACK_DISABLED)) { + dev_dbg(chip_info->dev, + "Loopback Mode is configured incorrectly\n"); + return -1; + } + if ((chip_info->hierarchy != SPI_MASTER) && + (chip_info->hierarchy != SPI_SLAVE)) { + dev_dbg(chip_info->dev, + "hierarchy is configured incorrectly\n"); + return -1; + } + if ((chip_info->endian_rx != SPI_FIFO_MSB) && + (chip_info->endian_rx != SPI_FIFO_LSB)) { + dev_dbg(chip_info->dev, + "Rx FIFO endianess is configured incorrectly\n"); + return -1; + } + if ((chip_info->endian_tx != SPI_FIFO_MSB) && + (chip_info->endian_tx != SPI_FIFO_LSB)) { + dev_dbg(chip_info->dev, + "Tx FIFO endianess is configured incorrectly\n"); + return -1; + } + if ((chip_info->data_size < MSP_DATA_BITS_8) || + (chip_info->data_size > MSP_DATA_BITS_32)) { + dev_dbg(chip_info->dev, + "MSP DATA Size is configured incorrectly\n"); + return -1; + } + if ((chip_info->com_mode != SPI_INTERRUPT_TRANSFER) && + (chip_info->com_mode != SPI_POLLING_TRANSFER)) { + dev_dbg(chip_info->dev, + "Communication mode is configured incorrectly\n"); + return -1; + } + if (((chip_info->proto_params).clk_phase != + SPI_CLK_ZERO_CYCLE_DELAY) && + ((chip_info->proto_params).clk_phase != + SPI_CLK_HALF_CYCLE_DELAY)) { + dev_dbg(chip_info->dev, + "Clock Phase is configured incorrectly\n"); + return -1; + } + if (((chip_info->proto_params).clk_pol != + SPI_CLK_POL_IDLE_LOW) && + ((chip_info->proto_params).clk_pol != + SPI_CLK_POL_IDLE_HIGH)) { + dev_dbg(chip_info->dev, + "Clk Polarity configured incorrectly\n"); + return -1; + } + if (chip_info->cs_control == NULL) { + dev_dbg(chip_info->dev, + "Chip Select Function is NULL for this chip\n"); + chip_info->cs_control = null_cs_control; + } + return 0; +} + +static struct stm_msp_config_chip *allocate_default_msp_chip_cfg( + struct spi_device *spi) +{ + struct stm_msp_config_chip *chip_info; + + chip_info = kzalloc(sizeof(struct stm_msp_config_chip), GFP_KERNEL); + + if (!chip_info) { + dev_err(&spi->dev, "setup - cannot allocate controller data"); + return NULL; + } + dev_dbg(&spi->dev, "Allocated Memory for controller data\n"); + + chip_info->lbm = SPI_LOOPBACK_DISABLED; + chip_info->com_mode = SPI_POLLING_TRANSFER; + chip_info->hierarchy = SPI_MASTER; + chip_info->endian_tx = SPI_FIFO_LSB; + chip_info->endian_rx = SPI_FIFO_LSB; + chip_info->data_size = MSP_DATA_BITS_32; + + if (spi->max_speed_hz != 0) + chip_info->freq = spi->max_speed_hz; + else + chip_info->freq = SPI_DEFAULT_MAX_SPEED_HZ; + + chip_info->proto_params.clk_phase = SPI_CLK_HALF_CYCLE_DELAY; + chip_info->proto_params.clk_pol = SPI_CLK_POL_IDLE_LOW; + chip_info->cs_control = null_cs_control; + + return chip_info; +} + +static void stm_msp_delay(struct stm_msp *stm_msp) +{ + udelay(15); + + while (readl(MSP_FLR(stm_msp->regs)) & + (MSP_FLR_MASK_RBUSY | MSP_FLR_MASK_TBUSY)) + udelay(1); +} + +/** + * stm_msp_setup - setup function registered to SPI master framework + * @spi: spi device which is requesting setup + * + * This function is registered to the SPI framework for this SPI master + * controller. If it is the first time when setup is called by this device, + * this function will initialize the runtime state for this chip and save + * the same in the device structure. Else it will update the runtime info + * with the updated chip info. + */ +static int stm_msp_setup(struct spi_device *spi) +{ + struct stm_msp_config_chip *chip_info; + struct chip_data *curr_cfg; + struct spi_master *master; + int status = 0; + u16 sckdiv = 0; + s16 bus_num = 0; + struct stm_msp *stm_msp = spi_master_get_devdata(spi->master); + struct msp_regs *msp_regs; + master = stm_msp->master; + bus_num = master->bus_num - 1; + + /* Get controller data */ + chip_info = spi->controller_data; + /* Get controller_state */ + curr_cfg = spi_get_ctldata(spi); + + if (curr_cfg == NULL) { + curr_cfg = kzalloc(sizeof(struct chip_data), GFP_KERNEL); + + if (!curr_cfg) { + dev_err(&stm_msp->adev->dev, + "setup - cannot allocate controller state"); + return -ENOMEM; + } + + curr_cfg->chip_id = spi->chip_select; + curr_cfg->ctr_regs = kzalloc(sizeof(struct msp_regs), + GFP_KERNEL); + + if (curr_cfg->ctr_regs == NULL) { + dev_err(&stm_msp->adev->dev, + "setup - cannot allocate mem for regs"); + goto err_first_setup; + } + + dev_err(&stm_msp->adev->dev, + "chip Id = %d\n", curr_cfg->chip_id); + + if (chip_info == NULL) { + chip_info = allocate_default_msp_chip_cfg(spi); + + if (!chip_info) { + dev_err(&stm_msp->adev->dev, + "setup - cannot allocate cntlr data"); + status = -ENOMEM; + goto err_first_setup; + } + + spi->controller_data = chip_info; + } + } + + /* Pointer back to the SPI device */ + chip_info->dev = &spi->dev; + + if (chip_info->freq == 0) { + /* Calculate Specific Freq. */ + if ((MSP_INTERNAL_CLK == chip_info->clk_freq.clk_src) || + (MSP_EXTERNAL_CLK == chip_info->clk_freq.clk_src)) { + sckdiv = chip_info->clk_freq.sckdiv; + } else { + status = -1; + dev_err(&stm_msp->adev->dev, + "setup - controller clock data is incorrect"); + goto err_config_params; + } + } else { + /* Calculate Effective Freq. */ + sckdiv = (DEFAULT_MSP_CLK / (chip_info->freq)) - 1; + + if (sckdiv > MAX_SCKDIV) { + dev_dbg(&stm_msp->adev->dev, + "SPI: Cannot set frequency less than 48Khz," + "setting lowest(48 Khz)\n"); + sckdiv = MAX_SCKDIV; + } + } + + status = verify_msp_controller_parameters(chip_info); + + if (status) { + dev_err(&stm_msp->adev->dev, + "setup - controller data is incorrect"); + goto err_config_params; + } + + /* Now set controller state based on controller data */ + curr_cfg->xfer_type = chip_info->com_mode; + curr_cfg->cs_control = chip_info->cs_control; + curr_cfg->delay = stm_msp_delay; + + curr_cfg->null_write = stm_msp_null_writer; + curr_cfg->null_read = stm_msp_null_reader; + + if (chip_info->data_size <= MSP_DATA_BITS_8) { + dev_dbg(&stm_msp->adev->dev, "Less than 8 bits per word...\n"); + + curr_cfg->n_bytes = 1; + curr_cfg->read = stm_msp_u8_reader; + curr_cfg->write = stm_msp_u8_writer; + } else if (chip_info->data_size <= MSP_DATA_BITS_16) { + dev_dbg(&stm_msp->adev->dev, "Less than 16 bits per word...\n"); + + curr_cfg->n_bytes = 2; + curr_cfg->read = stm_msp_u16_reader; + curr_cfg->write = stm_msp_u16_writer; + } else { + dev_dbg(&stm_msp->adev->dev, "Less than 32 bits per word...\n"); + + curr_cfg->n_bytes = 4; + curr_cfg->read = stm_msp_u32_reader; + curr_cfg->write = stm_msp_u32_writer; + } + + /* Now initialize all register settings reqd. for this chip */ + + msp_regs = (struct msp_regs *)(curr_cfg->ctr_regs); + msp_regs->gcr = 0x0; + msp_regs->tcf = 0x0; + msp_regs->rcf = 0x0; + msp_regs->srg = 0x0; + msp_regs->dmacr = 0x0; + + MSP_WBITS(msp_regs->dmacr, 0x0, MSP_DMACR_MASK_RDMAE, 0); + MSP_WBITS(msp_regs->dmacr, 0x0, MSP_DMACR_MASK_TDMAE, 1); + + /* GCR Reg Config */ + + MSP_WBITS(msp_regs->gcr, + MSP_RECEIVER_DISABLED, MSP_GCR_MASK_RXEN, 0); + MSP_WBITS(msp_regs->gcr, + MSP_RX_FIFO_ENABLED, MSP_GCR_MASK_RFFEN, 1); + MSP_WBITS(msp_regs->gcr, + MSP_TRANSMITTER_DISABLED, MSP_GCR_MASK_TXEN, 8); + MSP_WBITS(msp_regs->gcr, + MSP_TX_FIFO_ENABLED, MSP_GCR_MASK_TFFEN, 9); + MSP_WBITS(msp_regs->gcr, + MSP_TX_FRAME_SYNC_POL_LOW, MSP_GCR_MASK_TFSPOL, 10); + MSP_WBITS(msp_regs->gcr, + MSP_TX_FRAME_SYNC_INT, MSP_GCR_MASK_TFSSEL, 11); + MSP_WBITS(msp_regs->gcr, + MSP_TRANSMIT_DATA_WITH_DELAY, MSP_GCR_MASK_TXDDL, 15); + MSP_WBITS(msp_regs->gcr, + MSP_SAMPLE_RATE_GEN_ENABLE, MSP_GCR_MASK_SGEN, 16); + MSP_WBITS(msp_regs->gcr, + MSP_CLOCK_INTERNAL, MSP_GCR_MASK_SCKSEL, 18); + MSP_WBITS(msp_regs->gcr, + MSP_FRAME_GEN_ENABLE, MSP_GCR_MASK_FGEN, 20); + MSP_WBITS(msp_regs->gcr, + SPI_BURST_MODE_DISABLE, MSP_GCR_MASK_SPIBME, 23); + + if (chip_info->lbm == SPI_LOOPBACK_ENABLED) + MSP_WBITS(msp_regs->gcr, + MSP_LOOPBACK_ENABLED, MSP_GCR_MASK_LBM, 7); + else + MSP_WBITS(msp_regs->gcr, + MSP_LOOPBACK_DISABLED, MSP_GCR_MASK_LBM, 7); + + if (chip_info->hierarchy == SPI_MASTER) + MSP_WBITS(msp_regs->gcr, + MSP_IS_SPI_MASTER, MSP_GCR_MASK_TCKSEL, 14); + else + MSP_WBITS(msp_regs->gcr, + MSP_IS_SPI_SLAVE, MSP_GCR_MASK_TCKSEL, 14); + + if (chip_info->proto_params.clk_phase == SPI_CLK_ZERO_CYCLE_DELAY) + MSP_WBITS(msp_regs->gcr, + MSP_SPI_PHASE_ZERO_CYCLE_DELAY, + MSP_GCR_MASK_SPICKM, 21); + else + MSP_WBITS(msp_regs->gcr, + MSP_SPI_PHASE_HALF_CYCLE_DELAY, + MSP_GCR_MASK_SPICKM, 21); + + if (chip_info->proto_params.clk_pol == SPI_CLK_POL_IDLE_HIGH) + MSP_WBITS(msp_regs->gcr, + MSP_TX_CLOCK_POL_HIGH, MSP_GCR_MASK_TCKPOL, 13); + else + MSP_WBITS(msp_regs->gcr, + MSP_TX_CLOCK_POL_LOW, MSP_GCR_MASK_TCKPOL, 13); + + /* RCF Reg Config */ + MSP_WBITS(msp_regs->rcf, + MSP_IGNORE_RX_FRAME_SYNC_PULSE, MSP_RCF_MASK_RFSIG, 15); + MSP_WBITS(msp_regs->rcf, + MSP_RX_1BIT_DATA_DELAY, MSP_RCF_MASK_RDDLY, 13); + + if (chip_info->endian_rx == SPI_FIFO_LSB) + MSP_WBITS(msp_regs->rcf, + MSP_RX_ENDIANESS_LSB, MSP_RCF_MASK_RENDN, 12); + else + MSP_WBITS(msp_regs->rcf, + MSP_RX_ENDIANESS_MSB, MSP_RCF_MASK_RENDN, 12); + + MSP_WBITS(msp_regs->rcf, chip_info->data_size, MSP_RCF_MASK_RP1ELEN, 0); + + /* TCF Reg Config */ + + MSP_WBITS(msp_regs->tcf, + MSP_IGNORE_TX_FRAME_SYNC_PULSE, MSP_TCF_MASK_TFSIG, 15); + MSP_WBITS(msp_regs->tcf, + MSP_TX_1BIT_DATA_DELAY, MSP_TCF_MASK_TDDLY, 13); + + if (chip_info->endian_rx == SPI_FIFO_LSB) + MSP_WBITS(msp_regs->tcf, + MSP_TX_ENDIANESS_LSB, MSP_TCF_MASK_TENDN, 12); + else + MSP_WBITS(msp_regs->tcf, + MSP_TX_ENDIANESS_MSB, MSP_TCF_MASK_TENDN, 12); + MSP_WBITS(msp_regs->tcf, chip_info->data_size, MSP_TCF_MASK_TP1ELEN, 0); + + /* SRG Reg Config */ + + MSP_WBITS(msp_regs->srg, sckdiv, MSP_SRG_MASK_SCKDIV, 0); + + /* Save controller_state */ + spi_set_ctldata(spi, curr_cfg); + + return status; + +err_config_params: +err_first_setup: + + kfree(curr_cfg); + return status; +} + +static int __init stm_msp_probe(struct amba_device *adev, struct amba_id *id) +{ + struct device *dev = &adev->dev; + struct stm_msp_controller *platform_info = adev->dev.platform_data; + struct spi_master *master; + struct stm_msp *stm_msp = NULL; /* Data for this driver */ + int irq, status = 0; + + dev_info(dev, "STM MSP driver, device ID: 0x%08x\n", adev->periphid); + + if (platform_info == NULL) { + dev_err(dev, "probe - no platform data supplied\n"); + status = -ENODEV; + goto err_no_pdata; + } + + /* Allocate master with space for data */ + master = spi_alloc_master(dev, sizeof(struct stm_msp)); + + if (master == NULL) { + dev_err(dev, "probe - cannot alloc spi_master\n"); + status = -ENOMEM; + goto err_no_mem; + } + + stm_msp = spi_master_get_devdata(master); + stm_msp->master = master; + stm_msp->master_info = platform_info; + stm_msp->adev = adev; + + stm_msp->clk = clk_get(&adev->dev, NULL); + + if (IS_ERR(stm_msp->clk)) { + dev_err(dev, "probe - cannot find clock\n"); + status = PTR_ERR(stm_msp->clk); + goto free_master; + } + + /* Fetch the Resources, using platform data */ + status = amba_request_regions(adev, NULL); + + if (status) { + status = -ENODEV; + goto disable_clk; + } + + /* Get Hold of Device Register Area... */ + stm_msp->regs = ioremap(adev->res.start, resource_size(&adev->res)); + + if (stm_msp->regs == NULL) { + status = -ENODEV; + goto disable_clk; + } + + irq = adev->irq[0]; + + if (irq <= 0) { + status = -ENODEV; + goto err_no_iores; + } + + stm_msp_controller_cmd(stm_msp, LOAD_DEFAULT_CONFIG); + + /* Required Info for an SPI controller */ + /* Bus Number Which Assigned to this SPI controller on this board */ + master->bus_num = (u16) platform_info->id; + master->num_chipselect = platform_info->num_chipselect; + master->setup = stm_msp_setup; + master->cleanup = (void *)stm_msp_cleanup; + master->transfer = stm_msp_transfer; + + dev_dbg(dev, "BUSNO: %d\n", master->bus_num); + + /* Initialize and start queue */ + status = init_queue(stm_msp); + + if (status != 0) { + dev_err(dev, "probe - problem initializing queue\n"); + goto err_init_queue; + } + + status = start_queue(stm_msp); + + if (status != 0) { + dev_err(dev, "probe - problem starting queue\n"); + goto err_start_queue; + } + + amba_set_drvdata(adev, stm_msp); + + dev_dbg(dev, "probe succeded\n"); + dev_dbg(dev, "Bus No = %d, IRQ Line = %d, Virtual Addr: %x\n", + master->bus_num, irq, (u32)(stm_msp->regs)); + + status = request_irq(stm_msp->adev->irq[0], + stm_msp_interrupt_handler, + 0, stm_msp->master_info->device_name, + stm_msp); + + if (status < 0) { + dev_err(dev, "probe - cannot get IRQ (%d)\n", status); + goto err_irq; + } + + /* Register with the SPI framework */ + status = spi_register_master(master); + + if (status != 0) { + dev_err(dev, "probe - problem registering spi master\n"); + goto err_spi_register; + } + + return 0; + +err_spi_register: + free_irq(stm_msp->adev->irq[0], stm_msp); +err_irq: +err_init_queue: +err_start_queue: + destroy_queue(stm_msp); +err_no_iores: + iounmap(stm_msp->regs); +disable_clk: + clk_put(stm_msp->clk); +free_master: + spi_master_put(master); +err_no_mem: +err_no_pdata: + return status; +} + +static int __exit stm_msp_remove(struct amba_device *adev) +{ + struct stm_msp *stm_msp = amba_get_drvdata(adev); + int status = 0; + + if (!stm_msp) + return 0; + + /* Remove the queue */ + status = destroy_queue(stm_msp); + + if (status != 0) { + dev_err(&adev->dev, "queue remove failed (%d)\n", status); + return status; + } + + stm_msp_controller_cmd(stm_msp, LOAD_DEFAULT_CONFIG); + + /* Release map resources */ + iounmap(stm_msp->regs); + amba_release_regions(adev); + tasklet_disable(&stm_msp->pump_transfers); + free_irq(stm_msp->adev->irq[0], stm_msp); + + /* Disconnect from the SPI framework */ + spi_unregister_master(stm_msp->master); + + clk_put(stm_msp->clk); + + /* Prevent double remove */ + amba_set_drvdata(adev, NULL); + dev_dbg(&adev->dev, "remove succeded\n"); + return status; +} + +#ifdef CONFIG_PM + +/** + * stm_msp_suspend - MSP suspend function registered with PM framework. + * @dev: Reference to amba device structure of the device + * @state: power mgmt state. + * + * This function is invoked when the system is going into sleep, called + * by the power management framework of the linux kernel. + */ +static int stm_msp_suspend(struct amba_device *adev, pm_message_t state) +{ + struct stm_msp *stm_msp = amba_get_drvdata(adev); + int status = 0; + + status = stop_queue(stm_msp); + + if (status != 0) { + dev_warn(&adev->dev, "suspend cannot stop queue\n"); + return status; + } + + dev_dbg(&adev->dev, "suspended\n"); + return 0; +} + +/** + * stm_msp_resume - MSP Resume function registered with PM framework. + * @dev: Reference to amba device structure of the device + * + * This function is invoked when the system is coming out of sleep, called + * by the power management framework of the linux kernel. + */ +static int stm_msp_resume(struct amba_device *adev) +{ + struct stm_msp *stm_msp = amba_get_drvdata(adev); + int status = 0; + + /* Start the queue running */ + status = start_queue(stm_msp); + + if (status) + dev_err(&adev->dev, "problem starting queue (%d)\n", status); + else + dev_dbg(&adev->dev, "resumed\n"); + + return status; +} + +#else +#define stm_msp_suspend NULL +#define stm_msp_resume NULL +#endif /* CONFIG_PM */ + +static struct amba_id stm_msp_ids[] = { + { + .id = MSP_PER_ID, + .mask = MSP_PER_MASK, + }, + { + 0, + 0, + }, +}; + +static struct amba_driver stm_msp_driver = { + .drv = { + .name = "MSP", + }, + .id_table = stm_msp_ids, + .probe = stm_msp_probe, + .remove = __exit_p(stm_msp_remove), + .resume = stm_msp_resume, + .suspend = stm_msp_suspend, +}; + +static int __init stm_msp_init(void) +{ + return amba_driver_register(&stm_msp_driver); +} + +static void __exit stm_msp_exit(void) +{ + amba_driver_unregister(&stm_msp_driver); +} + +module_init(stm_msp_init); +module_exit(stm_msp_exit); + +MODULE_AUTHOR("Sachin Verma "); +MODULE_DESCRIPTION("STM MSP (SPI protocol) Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/spi/stm_msp.h b/include/linux/spi/stm_msp.h new file mode 100644 index 00000000000..501023105cb --- /dev/null +++ b/include/linux/spi/stm_msp.h @@ -0,0 +1,126 @@ +/* + * include/linux/spi/stm_msp.h + * + * Copyright (C) 2010 STMicroelectronics Pvt. Ltd. + * + * Author: Sachin Verma + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 _STM_MSP_H +#define _STM_MSP_H + +#include + +/* CHIP select/deselect commands */ +enum spi_chip_select { + SPI_CHIP_SELECT, + SPI_CHIP_DESELECT +}; + +/* Common configuration for different SPI controllers */ +enum spi_loopback { + SPI_LOOPBACK_DISABLED, + SPI_LOOPBACK_ENABLED +}; + +enum spi_hierarchy { + SPI_MASTER, + SPI_SLAVE +}; + +/* Endianess of FIFO Data */ +enum spi_fifo_endian { + SPI_FIFO_MSB, + SPI_FIFO_LSB +}; + +/* SPI mode of operation (Communication modes) */ +enum spi_mode { + SPI_INTERRUPT_TRANSFER, + SPI_POLLING_TRANSFER, +}; + +enum msp_data_size { + MSP_DATA_BITS_DEFAULT = -1, + MSP_DATA_BITS_8 = 0x00, + MSP_DATA_BITS_10, + MSP_DATA_BITS_12, + MSP_DATA_BITS_14, + MSP_DATA_BITS_16, + MSP_DATA_BITS_20, + MSP_DATA_BITS_24, + MSP_DATA_BITS_32, +}; + +enum msp_clk_src { + MSP_INTERNAL_CLK = 0x0, + MSP_EXTERNAL_CLK, +}; + +struct msp_clock_params { + enum msp_clk_src clk_src; + /* value from 0 to 1023 */ + u16 sckdiv; + /* Used only when MSPSCK clocks the sample rate + * generator (SCKSEL = 1Xb): + * 0b: The rising edge of MSPSCK clocks the sample rate generator + * 1b: The falling edge of MSPSCK clocks the sample rate generator */ + int sckpol; +}; + +/* Motorola SPI protocol specific definitions */ +enum spi_clk_phase { + SPI_CLK_ZERO_CYCLE_DELAY = 0x0, /* Receive data on rising edge. */ + SPI_CLK_HALF_CYCLE_DELAY /* Receive data on falling edge. */ +}; + +/* SPI Clock Polarity */ +enum spi_clk_pol { + SPI_CLK_POL_IDLE_LOW, /* Low inactive level */ + SPI_CLK_POL_IDLE_HIGH /* High inactive level */ +}; + +struct motorola_spi_proto_params { + enum spi_clk_phase clk_phase; + enum spi_clk_pol clk_pol; +}; + +struct stm_msp_config_chip { + struct device *dev; + enum spi_loopback lbm; + enum spi_hierarchy hierarchy; + enum spi_fifo_endian endian_rx; + enum spi_fifo_endian endian_tx; + enum spi_mode com_mode; + enum msp_data_size data_size; + struct msp_clock_params clk_freq; + int spi_burst_mode_enable; + struct motorola_spi_proto_params proto_params; + u32 freq; + void (*cs_control)(u32 control); +}; + +/** + * struct stm_msp_controller - device.platform_data for SPI controller devices. + * + * @num_chipselect: chipselects are used to distinguish individual + * SPI slaves, and are numbered from zero to num_chipselects - 1. + * each slave has a chipselect signal, but it's common that not + * every chipselect is connected to a slave. + */ +struct stm_msp_controller { + u8 num_chipselect; + u32 id; + u32 base_addr; + char *device_name; +}; +#endif /* _STM_MSP_H */ -- cgit v1.2.3 From cabd2894df35698004311b2b93f328a0ac9e1f0d Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Tue, 19 Oct 2010 20:17:35 +0200 Subject: sound: add ab8500 audio codec This patch is based on the following work: Add a power management scheme for AB3550 and fix bugs that hinder simultaneous playback/capture. ST-Ericsson ID: WP 259100 Author: Xie Xiaolei msp: add configuration param for MSP_IODLY ST-Ericsson ID: CR261462 Author: Rabin Vincent ab8500-acodec: remove unused dma variables ST-Ericsson ID: AP259210 Author: Rabin Vincent Signed-off-by: Mian Yousaf Kaukab --- arch/arm/mach-ux500/include/mach/ab8500_codec.h | 327 + arch/arm/mach-ux500/include/mach/ab8500_codec_p.h | 3082 +++++++++ .../mach-ux500/include/mach/ab8500_codec_p_v1_0.h | 3037 +++++++++ .../mach-ux500/include/mach/ab8500_codec_v1_0.h | 329 + .../mach-ux500/include/mach/u8500_acodec_ab8500.h | 284 + sound/Kconfig | 40 + sound/Makefile | 7 + sound/ab8500_codec.c | 6697 ++++++++++++++++++++ sound/ab8500_codec_v1_0.c | 6405 +++++++++++++++++++ sound/u8500_acodec_ab8500.c | 2522 ++++++++ 10 files changed, 22730 insertions(+) create mode 100644 arch/arm/mach-ux500/include/mach/ab8500_codec.h create mode 100644 arch/arm/mach-ux500/include/mach/ab8500_codec_p.h create mode 100644 arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h create mode 100644 arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h create mode 100644 arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h create mode 100644 sound/ab8500_codec.c create mode 100644 sound/ab8500_codec_v1_0.c create mode 100644 sound/u8500_acodec_ab8500.c diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec.h b/arch/arm/mach-ux500/include/mach/ab8500_codec.h new file mode 100644 index 00000000000..d45dea66b5d --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/ab8500_codec.h @@ -0,0 +1,327 @@ +/*****************************************************************************/ +/** +* © ST-Ericsson, 2009 - All rights reserved +* Reproduction and Communication of this document is strictly prohibited +* unless specifically authorized in writing by ST-Ericsson +* +* \brief Public header file for AB8500 Codec +* \author ST-Ericsson +*/ +/*****************************************************************************/ + +#ifndef _AB8500_CODEC_H_ +#define _AB8500_CODEC_H_ + +/*--------------------------------------------------------------------- + * Includes + *--------------------------------------------------------------------*/ +#include "hcl_defs.h" +#include "debug.h" +#include + +/*--------------------------------------------------------------------- + * Define + *--------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { + AB8500_CODEC_OK, + AB8500_CODEC_ERROR, + AB8500_CODEC_UNSUPPORTED_FEATURE, + AB8500_CODEC_INVALID_PARAMETER, + AB8500_CODEC_CONFIG_NOT_COHERENT, + AB8500_CODEC_TRANSACTION_FAILED + } t_ab8500_codec_error; + + typedef enum { + AB8500_CODEC_MASTER_MODE_DISABLE, + AB8500_CODEC_MASTER_MODE_ENABLE + } t_ab8500_codec_master_mode; + + typedef enum { + AB8500_CODEC_SLOT0, + AB8500_CODEC_SLOT1, + AB8500_CODEC_SLOT2, + AB8500_CODEC_SLOT3, + AB8500_CODEC_SLOT4, + AB8500_CODEC_SLOT5, + AB8500_CODEC_SLOT6, + AB8500_CODEC_SLOT7, + AB8500_CODEC_SLOT8, + AB8500_CODEC_SLOT9, + AB8500_CODEC_SLOT10, + AB8500_CODEC_SLOT11, + AB8500_CODEC_SLOT12, + AB8500_CODEC_SLOT13, + AB8500_CODEC_SLOT14, + AB8500_CODEC_SLOT15, + AB8500_CODEC_SLOT16, + AB8500_CODEC_SLOT17, + AB8500_CODEC_SLOT18, + AB8500_CODEC_SLOT19, + AB8500_CODEC_SLOT20, + AB8500_CODEC_SLOT21, + AB8500_CODEC_SLOT22, + AB8500_CODEC_SLOT23, + AB8500_CODEC_SLOT24, + AB8500_CODEC_SLOT25, + AB8500_CODEC_SLOT26, + AB8500_CODEC_SLOT27, + AB8500_CODEC_SLOT28, + AB8500_CODEC_SLOT29, + AB8500_CODEC_SLOT30, + AB8500_CODEC_SLOT31, + AB8500_CODEC_SLOT_UNDEFINED + } t_ab8500_codec_slot; + + typedef enum { + AB8500_CODEC_DA_CHANNEL_NUMBER_1, + AB8500_CODEC_DA_CHANNEL_NUMBER_2, + AB8500_CODEC_DA_CHANNEL_NUMBER_3, + AB8500_CODEC_DA_CHANNEL_NUMBER_4, + AB8500_CODEC_DA_CHANNEL_NUMBER_5, + AB8500_CODEC_DA_CHANNEL_NUMBER_6, + AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED + } t_ab8500_codec_da_channel_number; + + typedef enum { + AB8500_CODEC_SRC_STATE_DISABLE, + AB8500_CODEC_SRC_STATE_ENABLE + } t_ab8500_codec_src_state; + + typedef enum { + AB8500_CODEC_DEST_STATE_DISABLE, + AB8500_CODEC_DEST_STATE_ENABLE + } t_ab8500_codec_dest_state; + + typedef struct { + t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr; + t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr; + t_ab8500_codec_cr28_if0wl cr28_if0wl; + t_ab8500_codec_cr30_if1wl cr30_if1wl; + t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p; + t_ab8500_codec_cr28_if0del cr28_if0del; + } t_ab8500_codec_tdm_config; + + typedef struct { + t_ab8500_codec_cr104_bfifoint cr104_bfifoint; + t_ab8500_codec_cr105_bfifotx cr105_bfifotx; + t_ab8500_codec_cr106_bfifofsext cr106_bfifofsext; + t_ab8500_codec_cr106_bfifomsk cr106_bfifomsk; + t_ab8500_codec_cr106_bfifomstr cr106_bfifomstr; + t_ab8500_codec_cr106_bfifostrt cr106_bfifostrt; + t_ab8500_codec_cr107_bfifosampnr cr107_bfifosampnr; + t_ab8500_codec_cr108_bfifowakeup cr108_bfifowakeup; + } t_ab8500_codec_burst_fifo_config; + +/************************************************************/ +/*--------------------------------------------------------------------- + * Exported APIs + *--------------------------------------------------------------------*/ +/* Initialization */ + t_ab8500_codec_error AB8500_CODEC_Init(IN t_uint8 + slave_address_of_codec); + t_ab8500_codec_error AB8500_CODEC_Reset(void); + +/* Audio Codec basic configuration */ + t_ab8500_codec_error AB8500_CODEC_SetModeAndDirection(IN + t_ab8500_codec_direction + ab8500_codec_direction, + IN + t_ab8500_codec_mode + ab8500_codec_mode_in, + IN + t_ab8500_codec_mode + ab8500_codec_mode_out, + IN + t_ab8500_codec_tdm_config + const *const + p_tdm_config); + t_ab8500_codec_error AB8500_CODEC_SelectInput(IN t_ab8500_codec_src + ab8500_codec_src); + t_ab8500_codec_error AB8500_CODEC_SelectOutput(IN t_ab8500_codec_dest + ab8500_codec_dest); + +/* Burst FIFO configuration */ + t_ab8500_codec_error AB8500_CODEC_ConfigureBurstFifo(IN + t_ab8500_codec_burst_fifo_config + const *const + p_burst_fifo_config); + t_ab8500_codec_error AB8500_CODEC_EnableBurstFifo(void); + t_ab8500_codec_error AB8500_CODEC_DisableBurstFifo(void); + +/* Audio Codec Master mode configuration */ + t_ab8500_codec_error AB8500_CODEC_SetMasterMode(IN + t_ab8500_codec_master_mode + mode); + +/* APIs to be implemented by user */ + t_ab8500_codec_error AB8500_CODEC_Write(IN t_uint8 register_offset, + IN t_uint8 count, + IN t_uint8 * p_data); + t_ab8500_codec_error AB8500_CODEC_Read(IN t_uint8 register_offset, + IN t_uint8 count, + IN t_uint8 * p_dummy_data, + IN t_uint8 * p_data); + +/* Volume Management */ + t_ab8500_codec_error AB8500_CODEC_SetSrcVolume(IN t_ab8500_codec_src + src_device, + IN t_uint8 + in_left_volume, + IN t_uint8 + in_right_volume); + t_ab8500_codec_error AB8500_CODEC_SetDestVolume(IN t_ab8500_codec_dest + dest_device, + IN t_uint8 + out_left_volume, + IN t_uint8 + out_right_volume); + +/* Power management */ + t_ab8500_codec_error AB8500_CODEC_PowerDown(void); + t_ab8500_codec_error AB8500_CODEC_PowerUp(void); + +/* Interface Management */ + t_ab8500_codec_error AB8500_CODEC_SelectInterface(IN + t_ab8500_codec_audio_interface + audio_interface); + t_ab8500_codec_error AB8500_CODEC_GetInterface(OUT + t_ab8500_codec_audio_interface + * p_audio_interface); + +/* Slot Allocation */ + t_ab8500_codec_error AB8500_CODEC_ADSlotAllocation(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); + t_ab8500_codec_error AB8500_CODEC_DASlotAllocation(IN + t_ab8500_codec_da_channel_number + channel_number, + IN + t_ab8500_codec_cr51_to_cr56_sltoda + slot); + +/* Loopback Management */ + t_ab8500_codec_error AB8500_CODEC_SetAnalogLoopback(IN t_uint8 + out_left_volume, + IN t_uint8 + out_right_volume); + t_ab8500_codec_error AB8500_CODEC_RemoveAnalogLoopback(void); + +/* Bypass Management */ + t_ab8500_codec_error AB8500_CODEC_EnableBypassMode(void); + t_ab8500_codec_error AB8500_CODEC_DisableBypassMode(void); + +/* Power Control Management */ + t_ab8500_codec_error AB8500_CODEC_SrcPowerControl(IN t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state); + t_ab8500_codec_error AB8500_CODEC_DestPowerControl(IN + t_ab8500_codec_dest + dest_device, + t_ab8500_codec_dest_state + state); + +/* Version Management */ + t_ab8500_codec_error AB8500_CODEC_GetVersion(OUT t_version * p_version); + +#if 0 +/* Debug management */ + t_ab8500_codec_error AB8500_CODEC_SetDbgLevel(IN t_dbg_level dbg_level); + t_ab8500_codec_error AB8500_CODEC_GetDbgLevel(OUT t_dbg_level * + p_dbg_level); +#endif + +/* +** following is added by $kardad$ +*/ + +/* duplicate copy of enum from msp.h */ +/* for MSPConfiguration.in_clock_freq parameter to select msp clock freq */ + typedef enum { + CODEC_MSP_INPUT_FREQ_1MHZ = 1024, + CODEC_MSP_INPUT_FREQ_2MHZ = 2048, + CODEC_MSP_INPUT_FREQ_3MHZ = 3072, + CODEC_MSP_INPUT_FREQ_4MHZ = 4096, + CODEC_MSP_INPUT_FREQ_5MHZ = 5760, + CODEC_MSP_INPUT_FREQ_6MHZ = 6144, + CODEC_MSP_INPUT_FREQ_8MHZ = 8192, + CODEC_MSP_INPUT_FREQ_11MHZ = 11264, + CODEC_MSP_INPUT_FREQ_12MHZ = 12288, + CODEC_MSP_INPUT_FREQ_16MHZ = 16384, + CODEC_MSP_INPUT_FREQ_22MHZ = 22579, + CODEC_MSP_INPUT_FREQ_24MHZ = 24576, + CODEC_MSP_INPUT_FREQ_48MHZ = 49152 + } codec_msp_in_clock_freq_type; + +/* msp clock source internal/external for srg_clock_sel */ + typedef enum { + CODEC_MSP_APB_CLOCK = 0, + CODEC_MSP_SCK_CLOCK = 2, + CODEC_MSP_SCK_SYNC_CLOCK = 3 + } codec_msp_srg_clock_sel_type; + +/* Sample rate supported by Codec */ + + typedef enum { + CODEC_FREQUENCY_DONT_CHANGE = -100, + CODEC_SAMPLING_FREQ_RESET = -1, + CODEC_SAMPLING_FREQ_MINLIMIT = 7, + CODEC_SAMPLING_FREQ_8KHZ = 8, /*default */ + CODEC_SAMPLING_FREQ_11KHZ = 11, + CODEC_SAMPLING_FREQ_12KHZ = 12, + CODEC_SAMPLING_FREQ_16KHZ = 16, + CODEC_SAMPLING_FREQ_22KHZ = 22, + CODEC_SAMPLING_FREQ_24KHZ = 24, + CODEC_SAMPLING_FREQ_32KHZ = 32, + CODEC_SAMPLING_FREQ_44KHZ = 44, + CODEC_SAMPLING_FREQ_48KHZ = 48, + CODEC_SAMPLING_FREQ_64KHZ = 64, /*the frequencies below this line are not supported in stw5094A */ + CODEC_SAMPLING_FREQ_88KHZ = 88, + CODEC_SAMPLING_FREQ_96KHZ = 96, + CODEC_SAMPLING_FREQ_128KHZ = 128, + CODEC_SAMPLING_FREQ_176KHZ = 176, + CODEC_SAMPLING_FREQ_192KHZ = 192, + CODEC_SAMPLING_FREQ_MAXLIMIT = 193 + } t_codec_sample_frequency; + +#define RESET -1 +#define DEFAULT -100 +/***********************************************************/ +/* +** following stuff is added to compile code without debug print support $kardad$ +*/ + +#define DBGEXIT(cr) +#define DBGEXIT0(cr) +#define DBGEXIT1(cr,ch,p1) +#define DBGEXIT2(cr,ch,p1,p2) +#define DBGEXIT3(cr,ch,p1,p2,p3) +#define DBGEXIT4(cr,ch,p1,p2,p3,p4) +#define DBGEXIT5(cr,ch,p1,p2,p3,p4,p5) +#define DBGEXIT6(cr,ch,p1,p2,p3,p4,p5,p6) + +#define DBGENTER() +#define DBGENTER0() +#define DBGENTER1(ch,p1) +#define DBGENTER2(ch,p1,p2) +#define DBGENTER3(ch,p1,p2,p3) +#define DBGENTER4(ch,p1,p2,p3,p4) +#define DBGENTER5(ch,p1,p2,p3,p4,p5) +#define DBGENTER6(ch,p1,p2,p3,p4,p5,p6) + +#define DBGPRINT(dbg_level,dbg_string) +#define DBGPRINTHEX(dbg_level,dbg_string,uint32) +#define DBGPRINTDEC(dbg_level,dbg_string,uint32) +/***********************************************************/ + +#ifdef __cplusplus +} /* allow C++ to use these headers */ +#endif /* __cplusplus */ +#endif /* _AB8500_CODEC_H_ */ +/* End of file ab8500_codec.h*/ diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec_p.h b/arch/arm/mach-ux500/include/mach/ab8500_codec_p.h new file mode 100644 index 00000000000..847a1729e44 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/ab8500_codec_p.h @@ -0,0 +1,3082 @@ +/*****************************************************************************/ +/** +* © ST-Ericsson, 2009 - All rights reserved +* Reproduction and Communication of this document is strictly prohibited +* unless specifically authorized in writing by ST-Ericsson + * +* \brief Private Header file for AB8500 CODEC +* \author ST-Ericsson + */ +/*****************************************************************************/ + +#ifndef _AB8500_CODECP_H_ +#define _AB8500_CODECP_H_ + +/*---------------------------------------------------------------------------- + * Includes + *---------------------------------------------------------------------------*/ +#include "hcl_defs.h" + +#define AB8500_CODEC_HCL_VERSION_ID 2 +#define AB8500_CODEC_HCL_MAJOR_ID 0 +#define AB8500_CODEC_HCL_MINOR_ID 0 + +#define AB8500_CODEC_MASK_ONE_BIT 0x1UL +#define AB8500_CODEC_MASK_TWO_BITS 0x3UL +#define AB8500_CODEC_MASK_THREE_BITS 0x7UL +#define AB8500_CODEC_MASK_FOUR_BITS 0xFUL +#define AB8500_CODEC_MASK_FIVE_BITS 0x1FUL +#define AB8500_CODEC_MASK_SIX_BITS 0x3FUL +#define AB8500_CODEC_MASK_SEVEN_BITS 0x7FUL +#define AB8500_CODEC_MASK_EIGHT_BITS 0xFFUL + +#define AB8500_CODEC_WRITE_BITS(reg, val, bit_nb, pos) (reg) = ((t_uint8) ((((reg) & (~(bit_nb << pos))) | (((val) & bit_nb) << pos)))) + +#define AB8500_CODEC_BLOCK 0x0D + +#define AB8500_CODEC_MASK_TWO_MS_BITS 0xC0UL +#define AB8500_CODEC_MASK_SIX_LS_BITS 0x3FUL + +/* Genepi AudioCodec Control Registers */ + +#define AB8500_CODEC_CR0 0x00 +#define AB8500_CODEC_CR1 0x01 +#define AB8500_CODEC_CR2 0x02 +#define AB8500_CODEC_CR3 0x03 +#define AB8500_CODEC_CR4 0x04 +#define AB8500_CODEC_CR5 0x05 +#define AB8500_CODEC_CR6 0x06 +#define AB8500_CODEC_CR7 0x07 +#define AB8500_CODEC_CR8 0x08 +#define AB8500_CODEC_CR9 0x09 +#define AB8500_CODEC_CR10 0x0A +#define AB8500_CODEC_CR11 0x0B +#define AB8500_CODEC_CR12 0x0C +#define AB8500_CODEC_CR13 0x0D +#define AB8500_CODEC_CR14 0x0E +#define AB8500_CODEC_CR15 0x0F +#define AB8500_CODEC_CR16 0x10 +#define AB8500_CODEC_CR17 0x11 +#define AB8500_CODEC_CR18 0x12 +#define AB8500_CODEC_CR19 0x13 +#define AB8500_CODEC_CR20 0x14 +#define AB8500_CODEC_CR21 0x15 +#define AB8500_CODEC_CR22 0x16 +#define AB8500_CODEC_CR23 0x17 +#define AB8500_CODEC_CR24 0x18 +#define AB8500_CODEC_CR25 0x19 +#define AB8500_CODEC_CR26 0x1A +#define AB8500_CODEC_CR27 0x1B +#define AB8500_CODEC_CR28 0x1C +#define AB8500_CODEC_CR29 0x1D +#define AB8500_CODEC_CR30 0x1E +#define AB8500_CODEC_CR31 0x1F +#define AB8500_CODEC_CR32 0x20 +#define AB8500_CODEC_CR33 0x21 +#define AB8500_CODEC_CR34 0x22 +#define AB8500_CODEC_CR35 0x23 +#define AB8500_CODEC_CR36 0x24 +#define AB8500_CODEC_CR37 0x25 +#define AB8500_CODEC_CR38 0x26 +#define AB8500_CODEC_CR39 0x27 +#define AB8500_CODEC_CR40 0x28 +#define AB8500_CODEC_CR41 0x29 +#define AB8500_CODEC_CR42 0x2A +#define AB8500_CODEC_CR43 0x2B +#define AB8500_CODEC_CR44 0x2C +#define AB8500_CODEC_CR45 0x2D +#define AB8500_CODEC_CR46 0x2E +#define AB8500_CODEC_CR47 0x2F +#define AB8500_CODEC_CR48 0x30 +#define AB8500_CODEC_CR49 0x31 +#define AB8500_CODEC_CR50 0x32 +#define AB8500_CODEC_CR51 0x33 +#define AB8500_CODEC_CR52 0x34 +#define AB8500_CODEC_CR53 0x35 +#define AB8500_CODEC_CR54 0x36 +#define AB8500_CODEC_CR55 0x37 +#define AB8500_CODEC_CR56 0x38 +#define AB8500_CODEC_CR57 0x39 +#define AB8500_CODEC_CR58 0x3A +#define AB8500_CODEC_CR59 0x3B +#define AB8500_CODEC_CR60 0x3C +#define AB8500_CODEC_CR61 0x3D +#define AB8500_CODEC_CR62 0x3E +#define AB8500_CODEC_CR63 0x3F +#define AB8500_CODEC_CR64 0x40 +#define AB8500_CODEC_CR65 0x41 +#define AB8500_CODEC_CR66 0x42 +#define AB8500_CODEC_CR67 0x43 +#define AB8500_CODEC_CR68 0x44 +#define AB8500_CODEC_CR69 0x45 +#define AB8500_CODEC_CR70 0x46 +#define AB8500_CODEC_CR71 0x47 +#define AB8500_CODEC_CR72 0x48 +#define AB8500_CODEC_CR73 0x49 +#define AB8500_CODEC_CR74 0x4A +#define AB8500_CODEC_CR75 0x4B +#define AB8500_CODEC_CR76 0x4C +#define AB8500_CODEC_CR77 0x4D +#define AB8500_CODEC_CR78 0x4E +#define AB8500_CODEC_CR79 0x4F +#define AB8500_CODEC_CR80 0x50 +#define AB8500_CODEC_CR81 0x51 +#define AB8500_CODEC_CR82 0x52 +#define AB8500_CODEC_CR83 0x53 +#define AB8500_CODEC_CR84 0x54 +#define AB8500_CODEC_CR85 0x55 +#define AB8500_CODEC_CR86 0x56 +#define AB8500_CODEC_CR87 0x57 +#define AB8500_CODEC_CR88 0x58 +#define AB8500_CODEC_CR89 0x59 +#define AB8500_CODEC_CR90 0x5A +#define AB8500_CODEC_CR91 0x5B +#define AB8500_CODEC_CR92 0x5C +#define AB8500_CODEC_CR93 0x5D +#define AB8500_CODEC_CR94 0x5E +#define AB8500_CODEC_CR95 0x5F +#define AB8500_CODEC_CR96 0x60 +#define AB8500_CODEC_CR97 0x61 +#define AB8500_CODEC_CR98 0x62 +#define AB8500_CODEC_CR99 0x63 +#define AB8500_CODEC_CR100 0x64 +#define AB8500_CODEC_CR101 0x65 +#define AB8500_CODEC_CR102 0x66 +#define AB8500_CODEC_CR103 0x67 +#define AB8500_CODEC_CR104 0x68 +#define AB8500_CODEC_CR105 0x69 +#define AB8500_CODEC_CR106 0x6A +#define AB8500_CODEC_CR107 0x6B +#define AB8500_CODEC_CR108 0x6C +#define AB8500_CODEC_CR109 0x6D + +/* CR0-CR0x0000 */ +#define AB8500_CODEC_CR0_POWERUP 7 +#define AB8500_CODEC_CR0_ENAANA 3 + +/* CR1-CR0x0001 */ +#define AB8500_CODEC_CR1_SWRESET 7 + +/* CR2-CR0x0002 */ +#define AB8500_CODEC_CR2_ENAD1 7 +#define AB8500_CODEC_CR2_ENAD2 6 +#define AB8500_CODEC_CR2_ENAD3 5 +#define AB8500_CODEC_CR2_ENAD4 4 +#define AB8500_CODEC_CR2_ENAD5 3 +#define AB8500_CODEC_CR2_ENAD6 2 + +/* CR3-CR0x0003 */ +#define AB8500_CODEC_CR3_ENDA1 7 +#define AB8500_CODEC_CR3_ENDA2 6 +#define AB8500_CODEC_CR3_ENDA3 5 +#define AB8500_CODEC_CR3_ENDA4 4 +#define AB8500_CODEC_CR3_ENDA5 3 +#define AB8500_CODEC_CR3_ENDA6 2 + +/* CR4-CR0x0004 */ +#define AB8500_CODEC_CR4_LOWPOWHS 7 +#define AB8500_CODEC_CR4_LOWPOWDACHS 5 +#define AB8500_CODEC_CR4_LOWPOWEAR 4 +#define AB8500_CODEC_CR4_EAR_SEL_CM 2 +#define AB8500_CODEC_CR4_HS_HP_DIS 1 +#define AB8500_CODEC_CR4_EAR_HP_DIS 0 + +/* CR5-CR0x0005 */ +#define AB8500_CODEC_CR5_ENMIC1 7 +#define AB8500_CODEC_CR5_ENMIC2 6 +#define AB8500_CODEC_CR5_ENLINL 5 +#define AB8500_CODEC_CR5_ENLINR 4 +#define AB8500_CODEC_CR5_MUTMIC1 3 +#define AB8500_CODEC_CR5_MUTMIC2 2 +#define AB8500_CODEC_CR5_MUTELINL 1 +#define AB8500_CODEC_CR5_MUTELINR 0 + +/* CR6-CR0x0006 */ +#define AB8500_CODEC_CR6_ENDMIC1 7 +#define AB8500_CODEC_CR6_ENDMIC2 6 +#define AB8500_CODEC_CR6_ENDMIC3 5 +#define AB8500_CODEC_CR6_ENDMIC4 4 +#define AB8500_CODEC_CR6_ENDMIC5 3 +#define AB8500_CODEC_CR6_ENDMIC6 2 + +/* CR7-CR0x0007 */ +#define AB8500_CODEC_CR7_MIC1SEL 7 +#define AB8500_CODEC_CR7_LINRSEL 6 +#define AB8500_CODEC_CR7_ENDRVHSL 5 +#define AB8500_CODEC_CR7_ENDRVHSR 4 +#define AB8500_CODEC_CR7_ENADCMIC 2 +#define AB8500_CODEC_CR7_ENADCLINL 1 +#define AB8500_CODEC_CR7_ENADCLINR 0 + +/* CR8-CR0x0008 */ +#define AB8500_CODEC_CR8_CP_DIS_PLDWN 7 +#define AB8500_CODEC_CR8_ENEAR 6 +#define AB8500_CODEC_CR8_ENHSL 5 +#define AB8500_CODEC_CR8_ENHSR 4 +#define AB8500_CODEC_CR8_ENHFL 3 +#define AB8500_CODEC_CR8_ENHFR 2 +#define AB8500_CODEC_CR8_ENVIBL 1 +#define AB8500_CODEC_CR8_ENVIBR 0 + +/* CR9-CR0x0009 */ +#define AB8500_CODEC_CR9_ENADACEAR 6 +#define AB8500_CODEC_CR9_ENADACHSL 5 +#define AB8500_CODEC_CR9_ENADACHSR 4 +#define AB8500_CODEC_CR9_ENADACHFL 3 +#define AB8500_CODEC_CR9_ENADACHFR 2 +#define AB8500_CODEC_CR9_ENADACVIBL 1 +#define AB8500_CODEC_CR9_ENADACVIBR 0 + +/* CR10-CR0x000A */ +#define AB8500_CODEC_CR10_MUTEEAR 6 +#define AB8500_CODEC_CR10_MUTEHSL 5 +#define AB8500_CODEC_CR10_MUTEHSR 4 +#define AB8500_CODEC_CR10_MUTEHFL 3 +#define AB8500_CODEC_CR10_MUTEHFR 2 +#define AB8500_CODEC_CR10_MUTEVIBL 1 +#define AB8500_CODEC_CR10_MUTEVIBR 0 + +/* CR11-CR0x000B */ +#define AB8500_CODEC_CR11_ENSHORTPWD 7 +#define AB8500_CODEC_CR11_EARSHORTDIS 6 +#define AB8500_CODEC_CR11_HSLSHORTDIS 5 +#define AB8500_CODEC_CR11_HSRSHORTDIS 4 +#define AB8500_CODEC_CR11_HFLSHORTDIS 3 +#define AB8500_CODEC_CR11_HFRSHORTDIS 2 +#define AB8500_CODEC_CR11_VIBLSHORTDIS 1 +#define AB8500_CODEC_CR11_VIBRSHORTDIS 0 + +/* CR12-CR0x000C */ +#define AB8500_CODEC_CR12_ENCPHS 7 +#define AB8500_CODEC_CR12_HSAUTOTIME 4 +#define AB8500_CODEC_CR12_HSAUTOENSEL 1 +#define AB8500_CODEC_CR12_HSAUTOEN 0 + +/* CR13-CR0x000D */ +#define AB8500_CODEC_CR13_ENVDET_HTHRESH 4 +#define AB8500_CODEC_CR13_ENVDET_LTHRESH 0 + +/* CR14-CR0x000E */ +#define AB8500_CODEC_CR14_SMPSLVEN 7 +#define AB8500_CODEC_CR14_ENVDETSMPSEN 6 +#define AB8500_CODEC_CR14_CPLVEN 5 +#define AB8500_CODEC_CR14_ENVDETCPEN 4 +#define AB8500_CODEC_CR14_ENVDET_TIME 0 + +/* CR15-CR0x000F */ +#define AB8500_CODEC_CR15_PWMTOVIBL 7 +#define AB8500_CODEC_CR15_PWMTOVIBR 6 +#define AB8500_CODEC_CR15_PWMLCTRL 5 +#define AB8500_CODEC_CR15_PWMRCTRL 4 +#define AB8500_CODEC_CR15_PWMNLCTRL 3 +#define AB8500_CODEC_CR15_PWMPLCTRL 2 +#define AB8500_CODEC_CR15_PWMNRCTRL 1 +#define AB8500_CODEC_CR15_PWMPRCTRL 0 + +/* CR16-CR0x0010 */ +#define AB8500_CODEC_CR16_PWMNLPOL 7 +#define AB8500_CODEC_CR16_PWMNLDUTYCYCLE 0 + +/* CR17-CR0x0011 */ +#define AB8500_CODEC_CR17_PWMPLPOL 7 +#define AB8500_CODEC_CR17_PWMLPDUTYCYCLE 0 + +/* CR18-CR0x0012 */ +#define AB8500_CODEC_CR18_PWMNRPOL 7 +#define AB8500_CODEC_CR18_PWMNRDUTYCYCLE 0 + +/* CR19-CR0x0013 */ +#define AB8500_CODEC_CR19_PWMPRPOL 7 +#define AB8500_CODEC_CR19_PWMRPDUTYCYCLE 0 + +/* CR20-CR0x0014 */ +#define AB8500_CODEC_CR20_EN_SE_MIC1 7 +#define AB8500_CODEC_CR20_MIC1_GAIN 0 + +/* CR21-CR0x0015 */ +#define AB8500_CODEC_CR21_EN_SE_MIC2 7 +#define AB8500_CODEC_CR21_MIC2_GAIN 0 + +/* CR22-CR0x0016 */ +#define AB8500_CODEC_CR22_HSL_GAIN 5 +#define AB8500_CODEC_CR22_LINL_GAIN 0 + +/* CR23-CR0x0017 */ +#define AB8500_CODEC_CR23_HSR_GAIN 5 +#define AB8500_CODEC_CR23_LINR_GAIN 0 + +/* CR24-CR0x0018 */ +#define AB8500_CODEC_CR24_LINTOHSL_GAIN 0 + +/* CR25-CR0x0019 */ +#define AB8500_CODEC_CR25_LINTOHSR_GAIN 0 + +/* CR26-CR0x001A */ +#define AB8500_CODEC_CR26_AD1NH 7 +#define AB8500_CODEC_CR26_AD2NH 6 +#define AB8500_CODEC_CR26_AD3NH 5 +#define AB8500_CODEC_CR26_AD4NH 4 +#define AB8500_CODEC_CR26_AD1_VOICE 3 +#define AB8500_CODEC_CR26_AD2_VOICE 2 +#define AB8500_CODEC_CR26_AD3_VOICE 1 +#define AB8500_CODEC_CR26_AD4_VOICE 0 + +/* CR27-CR0x001B */ +#define AB8500_CODEC_CR27_EN_MASTGEN 7 +#define AB8500_CODEC_CR27_IF1_BITCLK_OSR 5 +#define AB8500_CODEC_CR27_ENFS_BITCLK1 4 +#define AB8500_CODEC_CR27_IF0_BITCLK_OSR 1 +#define AB8500_CODEC_CR27_ENFS_BITCLK0 0 + +/* CR28-CR0x001C */ +#define AB8500_CODEC_CR28_FSYNC0P 6 +#define AB8500_CODEC_CR28_BITCLK0P 5 +#define AB8500_CODEC_CR28_IF0DEL 4 +#define AB8500_CODEC_CR28_IF0FORMAT 2 +#define AB8500_CODEC_CR28_IF0WL 0 + +/* CR29-CR0x001D */ +#define AB8500_CODEC_CR29_IF0DATOIF1AD 7 +#define AB8500_CODEC_CR29_IF0CKTOIF1CK 6 +#define AB8500_CODEC_CR29_IF1MASTER 5 +#define AB8500_CODEC_CR29_IF1DATOIF0AD 3 +#define AB8500_CODEC_CR29_IF1CKTOIF0CK 2 +#define AB8500_CODEC_CR29_IF0MASTER 1 +#define AB8500_CODEC_CR29_IF0BFIFOEN 0 + +/* CR30-CR0x001E */ +#define AB8500_CODEC_CR30_FSYNC1P 6 +#define AB8500_CODEC_CR30_BITCLK1P 5 +#define AB8500_CODEC_CR30_IF1DEL 4 +#define AB8500_CODEC_CR30_IF1FORMAT 2 +#define AB8500_CODEC_CR30_IF1WL 0 + +/* CR31-CR0x001F */ +#define AB8500_CODEC_CR31_ADOTOSLOT1 4 +#define AB8500_CODEC_CR31_ADOTOSLOT0 0 + +/* CR32-CR0x0020 */ +#define AB8500_CODEC_CR32_ADOTOSLOT3 4 +#define AB8500_CODEC_CR32_ADOTOSLOT2 0 + +/* CR33-CR0x0021 */ +#define AB8500_CODEC_CR33_ADOTOSLOT5 4 +#define AB8500_CODEC_CR33_ADOTOSLOT4 0 + +/* CR34-CR0x0022 */ +#define AB8500_CODEC_CR34_ADOTOSLOT7 4 +#define AB8500_CODEC_CR34_ADOTOSLOT6 0 + +/* CR35-CR0x0023 */ +#define AB8500_CODEC_CR35_ADOTOSLOT9 4 +#define AB8500_CODEC_CR35_ADOTOSLOT8 0 + +/* CR36-CR0x0024 */ +#define AB8500_CODEC_CR36_ADOTOSLOT11 4 +#define AB8500_CODEC_CR36_ADOTOSLOT10 0 + +/* CR37-CR0x0025 */ +#define AB8500_CODEC_CR37_ADOTOSLOT13 4 +#define AB8500_CODEC_CR37_ADOTOSLOT12 0 + +/* CR38-CR0x0026 */ +#define AB8500_CODEC_CR38_ADOTOSLOT15 4 +#define AB8500_CODEC_CR38_ADOTOSLOT14 0 + +/* CR39-CR0x0027 */ +#define AB8500_CODEC_CR39_ADOTOSLOT17 4 +#define AB8500_CODEC_CR39_ADOTOSLOT16 0 + +/* CR40-CR0x0028 */ +#define AB8500_CODEC_CR40_ADOTOSLOT19 4 +#define AB8500_CODEC_CR40_ADOTOSLOT18 0 + +/* CR41-CR0x0029 */ +#define AB8500_CODEC_CR41_ADOTOSLOT21 4 +#define AB8500_CODEC_CR41_ADOTOSLOT20 0 + +/* CR42-CR0x002A */ +#define AB8500_CODEC_CR42_ADOTOSLOT23 4 +#define AB8500_CODEC_CR42_ADOTOSLOT22 0 + +/* CR43-CR0x002B */ +#define AB8500_CODEC_CR43_ADOTOSLOT25 4 +#define AB8500_CODEC_CR43_ADOTOSLOT24 0 + +/* CR44-CR0x002C */ +#define AB8500_CODEC_CR44_ADOTOSLOT27 4 +#define AB8500_CODEC_CR44_ADOTOSLOT26 0 + +/* CR45-CR0x002D */ +#define AB8500_CODEC_CR45_ADOTOSLOT29 4 +#define AB8500_CODEC_CR45_ADOTOSLOT28 0 + +/* CR46-CR0x002E */ +#define AB8500_CODEC_CR46_ADOTOSLOT31 4 +#define AB8500_CODEC_CR46_ADOTOSLOT30 0 + +/* CR47-CR0x002F */ +#define AB8500_CODEC_CR47_HIZ_SL7 7 +#define AB8500_CODEC_CR47_HIZ_SL6 6 +#define AB8500_CODEC_CR47_HIZ_SL5 5 +#define AB8500_CODEC_CR47_HIZ_SL4 4 +#define AB8500_CODEC_CR47_HIZ_SL3 3 +#define AB8500_CODEC_CR47_HIZ_SL2 2 +#define AB8500_CODEC_CR47_HIZ_SL1 1 +#define AB8500_CODEC_CR47_HIZ_SL0 0 + +/* CR48-CR0x0030 */ +#define AB8500_CODEC_CR48_HIZ_SL15 7 +#define AB8500_CODEC_CR48_HIZ_SL14 6 +#define AB8500_CODEC_CR48_HIZ_SL13 5 +#define AB8500_CODEC_CR48_HIZ_SL12 4 +#define AB8500_CODEC_CR48_HIZ_SL11 3 +#define AB8500_CODEC_CR48_HIZ_SL10 2 +#define AB8500_CODEC_CR48_HIZ_SL9 1 +#define AB8500_CODEC_CR48_HIZ_SL8 0 + +/* CR49-CR0x0031 */ +#define AB8500_CODEC_CR49_HIZ_SL23 7 +#define AB8500_CODEC_CR49_HIZ_SL22 6 +#define AB8500_CODEC_CR49_HIZ_SL21 5 +#define AB8500_CODEC_CR49_HIZ_SL20 4 +#define AB8500_CODEC_CR49_HIZ_SL19 3 +#define AB8500_CODEC_CR49_HIZ_SL18 2 +#define AB8500_CODEC_CR49_HIZ_SL17 1 +#define AB8500_CODEC_CR49_HIZ_SL16 0 + +/* CR50-CR0x0032 */ +#define AB8500_CODEC_CR50_HIZ_SL31 7 +#define AB8500_CODEC_CR50_HIZ_SL30 6 +#define AB8500_CODEC_CR50_HIZ_SL29 5 +#define AB8500_CODEC_CR50_HIZ_SL28 4 +#define AB8500_CODEC_CR50_HIZ_SL27 3 +#define AB8500_CODEC_CR50_HIZ_SL26 2 +#define AB8500_CODEC_CR50_HIZ_SL25 1 +#define AB8500_CODEC_CR50_HIZ_SL24 0 + +/* CR51-CR0x0033 */ +#define AB8500_CODEC_CR51_DA12_VOICE 7 +#define AB8500_CODEC_CR51_SLDAI1TOSLADO1 5 +#define AB8500_CODEC_CR51_SLTODA1 0 + +/* CR52-CR0x0034 */ +#define AB8500_CODEC_CR52_SLDAI1TOSLADO2 5 +#define AB8500_CODEC_CR52_SLTODA2 0 + +/* CR53-CR0x0035 */ +#define AB8500_CODEC_CR53_DA34_VOICE 7 +#define AB8500_CODEC_CR53_SLDAI1TOSLADO3 5 +#define AB8500_CODEC_CR53_SLTODA3 0 + +/* CR54-CR0x0036 */ +#define AB8500_CODEC_CR54_SLDAI1TOSLADO4 5 +#define AB8500_CODEC_CR54_SLTODA4 0 + +/* CR55-CR0x0037 */ +#define AB8500_CODEC_CR55_DA56_VOICE 7 +#define AB8500_CODEC_CR55_SLDAI1TOSLADO5 5 +#define AB8500_CODEC_CR55_SLTODA5 0 + +/* CR56-CR0x0038 */ +#define AB8500_CODEC_CR56_SLDAI1TOSLADO6 5 +#define AB8500_CODEC_CR56_SLTODA6 0 + +/* CR57-CR0x0039 */ +#define AB8500_CODEC_CR57_BFIFULL_MSK 6 +#define AB8500_CODEC_CR57_BFIEMPT_MSK 5 +#define AB8500_CODEC_CR57_DACHAN_MSK 4 +#define AB8500_CODEC_CR57_GAIN_MSK 3 +#define AB8500_CODEC_CR57_DSPAD_MSK 2 +#define AB8500_CODEC_CR57_DSPDA_MSK 1 +#define AB8500_CODEC_CR57_STFIR_MSK 0 + +/* CR58-CR0x003A */ +#define AB8500_CODEC_CR58_BFIFULL_EV 6 +#define AB8500_CODEC_CR58_BFIEMPT_EV 5 +#define AB8500_CODEC_CR58_DACHAN_EV 4 +#define AB8500_CODEC_CR58_GAIN_EV 3 +#define AB8500_CODEC_CR58_DSPAD_EV 2 +#define AB8500_CODEC_CR58_DSPDA_EV 1 +#define AB8500_CODEC_CR58_STFIR_EV 0 + +/* CR59-CR0x003B */ +#define AB8500_CODEC_CR59_VSSREADY_MSK 7 +#define AB8500_CODEC_CR59_SHRTVIBL_MSK 6 +#define AB8500_CODEC_CR59_SHRTVIBR_MSK 5 +#define AB8500_CODEC_CR59_SHRTHFL_MSK 4 +#define AB8500_CODEC_CR59_SHRTHFR_MSK 3 +#define AB8500_CODEC_CR59_SHRTHSL_MSK 2 +#define AB8500_CODEC_CR59_SHRTHSR_MSK 1 +#define AB8500_CODEC_CR59_SHRTEAR_MSK 0 + +/* CR60-CR0x003C */ +#define AB8500_CODEC_CR60_VSSREADY_EV 7 +#define AB8500_CODEC_CR60_SHRTVIBL_EV 6 +#define AB8500_CODEC_CR60_SHRTVIBR_EV 5 +#define AB8500_CODEC_CR60_SHRTHFL_EV 4 +#define AB8500_CODEC_CR60_SHRTHFR_EV 3 +#define AB8500_CODEC_CR60_SHRTHSL_EV 2 +#define AB8500_CODEC_CR60_SHRTHSR_EV 1 +#define AB8500_CODEC_CR60_SHRTEAR_EV 0 + +/* CR61-CR0x003D */ +#define AB8500_CODEC_CR61_REVISION 2 +#define AB8500_CODEC_CR61_FADE_SPEED 0 + +/* CR62-CR0x003E */ +#define AB8500_CODEC_CR62_DMIC1SINC3 5 +#define AB8500_CODEC_CR62_DMIC2SINC3 4 +#define AB8500_CODEC_CR62_DMIC3SINC3 3 +#define AB8500_CODEC_CR62_DMIC4SINC3 2 +#define AB8500_CODEC_CR62_DMIC5SINC3 1 +#define AB8500_CODEC_CR62_DMIC6SINC3 0 + +/* CR63-CR0x003F */ +#define AB8500_CODEC_CR63_DATOHSLEN 7 +#define AB8500_CODEC_CR63_DATOHSREN 6 +#define AB8500_CODEC_CR63_AD1SEL 5 +#define AB8500_CODEC_CR63_AD2SEL 4 +#define AB8500_CODEC_CR63_AD3SEL 3 +#define AB8500_CODEC_CR63_AD5SEL 2 +#define AB8500_CODEC_CR63_AD6SEL 1 +#define AB8500_CODEC_CR63_ANCSEL 0 + +/* CR64-CR0x0040 */ +#define AB8500_CODEC_CR64_DATOHFREN 7 +#define AB8500_CODEC_CR64_DATOHFLEN 6 +#define AB8500_CODEC_CR64_HFRSEL 5 +#define AB8500_CODEC_CR64_HFLSEL 4 +#define AB8500_CODEC_CR64_STFIR1SEL 2 +#define AB8500_CODEC_CR64_STFIR2SEL 0 + +/* CR65-CR0x0041 */ +#define AB8500_CODEC_CR65_FADEDIS_AD1 6 +#define AB8500_CODEC_CR65_AD1GAIN 0 + +/* CR66-CR0x0042 */ +#define AB8500_CODEC_CR66_FADEDIS_AD2 6 +#define AB8500_CODEC_CR66_AD2GAIN 0 + +/* CR67-CR0x0043 */ +#define AB8500_CODEC_CR67_FADEDIS_AD3 6 +#define AB8500_CODEC_CR67_AD3GAIN 0 + +/* CR68-CR0x0044 */ +#define AB8500_CODEC_CR68_FADEDIS_AD4 6 +#define AB8500_CODEC_CR68_AD4GAIN 0 + +/* CR69-CR0x0045 */ +#define AB8500_CODEC_CR69_FADEDIS_AD5 6 +#define AB8500_CODEC_CR69_AD5GAIN 0 + +/* CR70-CR0x0046 */ +#define AB8500_CODEC_CR70_FADEDIS_AD6 6 +#define AB8500_CODEC_CR70_AD6GAIN 0 + +/* CR71-CR0x0047 */ +#define AB8500_CODEC_CR71_FADEDIS_DA1 6 +#define AB8500_CODEC_CR71_DA1GAIN 0 + +/* CR72-CR0x0048 */ +#define AB8500_CODEC_CR72_FADEDIS_DA2 6 +#define AB8500_CODEC_CR72_DA2GAIN 0 + +/* CR73-CR0x0049 */ +#define AB8500_CODEC_CR73_FADEDIS_DA3 6 +#define AB8500_CODEC_CR73_DA3GAIN 0 + +/* CR74-CR0x004A */ +#define AB8500_CODEC_CR74_FADEDIS_DA4 6 +#define AB8500_CODEC_CR74_DA4GAIN 0 + +/* CR75-CR0x004B */ +#define AB8500_CODEC_CR75_FADEDIS_DA5 6 +#define AB8500_CODEC_CR75_DA5GAIN 0 + +/* CR76-CR0x004C */ +#define AB8500_CODEC_CR76_FADEDIS_DA6 6 +#define AB8500_CODEC_CR76_DA6GAIN 0 + +/* CR77-CR0x004D */ +#define AB8500_CODEC_CR77_FADEDIS_AD1L 6 +#define AB8500_CODEC_CR77_AD1LBGAIN 0 + +/* CR78-CR0x004E */ +#define AB8500_CODEC_CR78_FADEDIS_AD2L 6 +#define AB8500_CODEC_CR78_AD2LBGAIN 0 + +/* CR79-CR0x004F */ +#define AB8500_CODEC_CR79_HSSINC1 7 +#define AB8500_CODEC_CR79_FADEDIS_HSL 4 +#define AB8500_CODEC_CR79_HSLDGAIN 0 + +/* CR80-CR0x0050 */ +#define AB8500_CODEC_CR80_FADEDIS_HSR 4 +#define AB8500_CODEC_CR80_HSRDGAIN 0 + +/* CR81-CR0x0051 */ +#define AB8500_CODEC_CR81_STFIR1GAIN 0 + +/* CR82-CR0x0052 */ +#define AB8500_CODEC_CR82_STFIR2GAIN 0 + +/* CR83-CR0x0053 */ +#define AB8500_CODEC_CR83_ENANC 2 +#define AB8500_CODEC_CR83_ANCIIRINIT 1 +#define AB8500_CODEC_CR83_ANCFIRUPDATE 0 + +/* CR84-CR0x0054 */ +#define AB8500_CODEC_CR84_ANCINSHIFT 0 + +/* CR85-CR0x0055 */ +#define AB8500_CODEC_CR85_ANCFIROUTSHIFT 0 + +/* CR86-CR0x0056 */ +#define AB8500_CODEC_CR86_ANCSHIFTOUT 0 + +/* CR87-CR0x0057 */ +#define AB8500_CODEC_CR87_ANCFIRCOEFF_MSB 0 + +/* CR88-CR0x0058 */ +#define AB8500_CODEC_CR88_ANCFIRCOEFF_LSB 0 + +/* CR89-CR0x0059 */ +#define AB8500_CODEC_CR89_ANCIIRCOEFF_MSB 0 + +/* CR90-CR0x005A */ +#define AB8500_CODEC_CR90_ANCIIRCOEFF_LSB 0 + +/* CR91-CR0x005B */ +#define AB8500_CODEC_CR91_ANCWARPDEL_MSB 0 + +/* CR92-CR0x005C */ +#define AB8500_CODEC_CR92_ANCWARPDEL_LSB 0 + +/* CR93-CR0x005D */ +#define AB8500_CODEC_CR93_ANCFIRPEAK_MSB 0 + +/* CR94-CR0x005E */ +#define AB8500_CODEC_CR94_ANCFIRPEAK_LSB 0 + +/* CR95-CR0x005F */ +#define AB8500_CODEC_CR95_ANCIIRPEAK_MSB 0 + +/* CR96-CR0x0060 */ +#define AB8500_CODEC_CR96_ANCIIRPEAK_LSB 0 + +/* CR97-CR0x0061 */ +#define AB8500_CODEC_CR97_STFIR_SET 7 +#define AB8500_CODEC_CR97_STFIR_ADDR 0 + +/* CR98-CR0x0062 */ +#define AB8500_CODEC_CR98_STFIR_COEFF_MSB 0 + +/* CR99-CR0x0063 */ +#define AB8500_CODEC_CR99_STFIR_COEFF_LSB 0 + +/* CR100-CR0x0064 */ +#define AB8500_CODEC_CR100_ENSTFIRS 2 +#define AB8500_CODEC_CR100_STFIRSTOIF1 1 +#define AB8500_CODEC_CR100_STFIR_BUSY 0 + +/* CR101-CR0x0065 */ +#define AB8500_CODEC_CR101_PARLHF 7 +#define AB8500_CODEC_CR101_PARLVIB 6 +#define AB8500_CODEC_CR101_CLASSDVIBLSWAPEN 3 +#define AB8500_CODEC_CR101_CLASSDVIBRSWAPEN 2 +#define AB8500_CODEC_CR101_CLASSDHFLSWAPEN 1 +#define AB8500_CODEC_CR101_CLASSDHFRSWAPEN 0 + +/* CR102-CR0x0066 */ +#define AB8500_CODEC_CR102_CLASSD_FIRBYP 4 +#define AB8500_CODEC_CR102_CLASSD_HIGHVOLEN 0 + +/* CR103-CR0x0067 */ +#define AB8500_CODEC_CR103_CLASSD_DITHERHPGAIN 4 +#define AB8500_CODEC_CR103_CLASSD_DITHERWGAIN 0 + +/* CR104-CR0x0068 */ +#define AB8500_CODEC_CR104_BFIFOINT 0 + +/* CR105-CR0x0069 */ +#define AB8500_CODEC_CR105_BFIFOTX 0 + +/* CR106-CR0x006A */ +#define AB8500_CODEC_CR106_BFIFOFSEXT 4 +#define AB8500_CODEC_CR106_BFIFOMSK 2 +#define AB8500_CODEC_CR106_BFIFOMSTR 1 +#define AB8500_CODEC_CR106_BFIFOSTRT 0 + +/* CR107-CR0x006B */ +#define AB8500_CODEC_CR107_BFIFOSAMPNR 0 + +/* CR108-CR0x006C */ +#define AB8500_CODEC_CR108_BFIFOWAKEUP 0 + +/* CR109-CR0x006D */ +#define AB8500_CODEC_CR109_BFIFOSAMPLES 0 + +/* For SetVolume API*/ +#define AB8500_CODEC_MAX_VOLUME 100 + +/* Analog MIC1 & MIC2 */ +#define AB8500_CODEC_MIC_VOLUME_MAX 31 +#define AB8500_CODEC_MIC_VOLUME_MEDIUM 15 +#define AB8500_CODEC_MIC_VOLUME_MIN 0 + +/* Line-in */ +#define AB8500_CODEC_LINEIN_VOLUME_MAX 31 +#define AB8500_CODEC_LINEIN_VOLUME_MEDIUM 15 +#define AB8500_CODEC_LINEIN_VOLUME_MIN 0 + +/* HeadSet */ +#define AB8500_CODEC_HEADSET_VOLUME_MAX 0 +#define AB8500_CODEC_HEADSET_VOLUME_MEDIUM 3 +#define AB8500_CODEC_HEADSET_VOLUME_MIN 7 + +/* HeadSet Digital */ +#define AB8500_CODEC_HEADSET_D_VOLUME_MAX 0 +#define AB8500_CODEC_HEADSET_D_VOLUME_MEDIUM 7 +#define AB8500_CODEC_HEADSET_D_VOLUME_MIN 15 +#define AB8500_CODEC_HEADSET_D_VOLUME_0DB 8 + +/* Digital AD Path */ +#define AB8500_CODEC_AD_D_VOLUME_MAX 0 +#define AB8500_CODEC_AD_D_VOLUME_MEDIUM 31 +#define AB8500_CODEC_AD_D_VOLUME_MIN 63 + +/* Digital DA Path */ +#define AB8500_CODEC_DA_D_VOLUME_MAX 0 +#define AB8500_CODEC_DA_D_VOLUME_MEDIUM 31 +#define AB8500_CODEC_DA_D_VOLUME_MIN 63 + +/* EarPiece Digital */ +#define AB8500_CODEC_EARPIECE_D_VOLUME_MAX 0 +#define AB8500_CODEC_EARPIECE_D_VOLUME_MEDIUM 7 +#define AB8500_CODEC_EARPIECE_D_VOLUME_MIN 15 + +/* AD1 loopback to HFL & HFR Digital */ +#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MAX 0 +#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MEDIUM 31 +#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MIN 63 + +/* Line-in to HSL & HSR */ +#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX 0 +#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MEDIUM 9 +#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN 18 +#define AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN 19 + +/* Vibrator */ +#define AB8500_CODEC_VIBRATOR_VOLUME_MAX 100 +#define AB8500_CODEC_VIBRATOR_VOLUME_MEDIUM 50 +#define AB8500_CODEC_VIBRATOR_VOLUME_MIN 0 + +/* CR0 - 7 */ +typedef enum { + AB8500_CODEC_CR0_POWERUP_OFF, + AB8500_CODEC_CR0_POWERUP_ON +} t_ab8500_codec_cr0_powerup; + +/* CR0 - 3 */ +typedef enum { + AB8500_CODEC_CR0_ENAANA_OFF, + AB8500_CODEC_CR0_ENAANA_ON +} t_ab8500_codec_cr0_enaana; + +/* CR1 - 7 */ +typedef enum { + AB8500_CODEC_CR1_SWRESET_DISABLED, + AB8500_CODEC_CR1_SWRESET_ENABLED +} t_ab8500_codec_cr1_swreset; + +/* CR2 - 7 */ +typedef enum { + AB8500_CODEC_CR2_ENAD1_DISABLED, + AB8500_CODEC_CR2_ENAD1_ENABLED +} t_ab8500_codec_cr2_enad1; + +/* CR2 - 6 */ +typedef enum { + AB8500_CODEC_CR2_ENAD2_DISABLED, + AB8500_CODEC_CR2_ENAD2_ENABLED +} t_ab8500_codec_cr2_enad2; + +/* CR2 - 5 */ +typedef enum { + AB8500_CODEC_CR2_ENAD3_DISABLED, + AB8500_CODEC_CR2_ENAD3_ENABLED +} t_ab8500_codec_cr2_enad3; + +/* CR2 - 4 */ +typedef enum { + AB8500_CODEC_CR2_ENAD4_DISABLED, + AB8500_CODEC_CR2_ENAD4_ENABLED +} t_ab8500_codec_cr2_enad4; + +/* CR2 - 3 */ +typedef enum { + AB8500_CODEC_CR2_ENAD5_DISABLED, + AB8500_CODEC_CR2_ENAD5_ENABLED +} t_ab8500_codec_cr2_enad5; + +/* CR2 - 2 */ +typedef enum { + AB8500_CODEC_CR2_ENAD6_DISABLED, + AB8500_CODEC_CR2_ENAD6_ENABLED +} t_ab8500_codec_cr2_enad6; + +/* CR3 - 7 */ +typedef enum { + AB8500_CODEC_CR3_ENDA1_DISABLED, + AB8500_CODEC_CR3_ENDA1_ENABLED +} t_ab8500_codec_cr3_enda1; + +/* CR3 - 6 */ +typedef enum { + AB8500_CODEC_CR3_ENDA2_DISABLED, + AB8500_CODEC_CR3_ENDA2_ENABLED +} t_ab8500_codec_cr3_enda2; + +/* CR3 - 5 */ +typedef enum { + AB8500_CODEC_CR3_ENDA3_DISABLED, + AB8500_CODEC_CR3_ENDA3_ENABLED +} t_ab8500_codec_cr3_enda3; + +/* CR3 - 4 */ +typedef enum { + AB8500_CODEC_CR3_ENDA4_DISABLED, + AB8500_CODEC_CR3_ENDA4_ENABLED +} t_ab8500_codec_cr3_enda4; + +/* CR3 - 3 */ +typedef enum { + AB8500_CODEC_CR3_ENDA5_DISABLED, + AB8500_CODEC_CR3_ENDA5_ENABLED +} t_ab8500_codec_cr3_enda5; + +/* CR3 - 2 */ +typedef enum { + AB8500_CODEC_CR3_ENDA6_DISABLED, + AB8500_CODEC_CR3_ENDA6_ENABLED +} t_ab8500_codec_cr3_enda6; + +/* CR4 - 7 */ +typedef enum { + AB8500_CODEC_CR4_LOWPOWHS_NORMAL, + AB8500_CODEC_CR4_LOWPOWHS_LP +} t_ab8500_codec_cr4_lowpowhs; + +/* CR4 - 6:5 */ +typedef enum { + AB8500_CODEC_CR4_LOWPOWDACHS_NORMAL, + AB8500_CODEC_CR4_LOWPOWDACHS_DRIVERS_LP, + AB8500_CODEC_CR4_LOWPOWDACHS_LP, + AB8500_CODEC_CR4_LOWPOWDACHS_BOTH_LP +} t_ab8500_codec_cr4_lowpowdachs; + +/* CR4 - 4 */ +typedef enum { + AB8500_CODEC_CR4_LOWPOWEAR_NORMAL, + AB8500_CODEC_CR4_LOWPOWEAR_LP +} t_ab8500_codec_cr4_lowpowear; + +/* CR4 - 3:2 */ +typedef enum { + AB8500_CODEC_CR4_EAR_SEL_CM_0_95V, + AB8500_CODEC_CR4_EAR_SEL_CM_1_1V, + AB8500_CODEC_CR4_EAR_SEL_CM_1_27V, + AB8500_CODEC_CR4_EAR_SEL_CM_1_58V +} t_ab8500_codec_cr4_ear_sel_cm; + +/* CR4 - 1 */ +typedef enum { + AB8500_CODEC_CR4_HS_HP_DIS_FILTER_ENABLED, + AB8500_CODEC_CR4_HS_HP_DIS_FILTER_DISABLED +} t_ab8500_codec_cr4_hs_hp_dis; + +/* CR4 - 0 */ +typedef enum { + AB8500_CODEC_CR4_EAR_HP_DIS_FILTER_ENABLED, + AB8500_CODEC_CR4_EAR_HP_DIS_FILTER_DISABLED +} t_ab8500_codec_cr4_ear_hp_dis; + +/* CR5 - 7 */ +typedef enum { + AB8500_CODEC_CR5_ENMIC1_DISABLED, + AB8500_CODEC_CR5_ENMIC1_ENABLED +} t_ab8500_codec_cr5_enmic1; + +/* CR5 - 6 */ +typedef enum { + AB8500_CODEC_CR5_ENMIC2_DISABLED, + AB8500_CODEC_CR5_ENMIC2_ENABLED +} t_ab8500_codec_cr5_enmic2; + +/* CR5 - 5 */ +typedef enum { + AB8500_CODEC_CR5_ENLINL_DISABLED, + AB8500_CODEC_CR5_ENLINL_ENABLED +} t_ab8500_codec_cr5_enlinl; + +/* CR5 - 4 */ +typedef enum { + AB8500_CODEC_CR5_ENLINR_DISABLED, + AB8500_CODEC_CR5_ENLINR_ENABLED +} t_ab8500_codec_cr5_enlinr; + +/* CR5 - 3 */ +typedef enum { + AB8500_CODEC_CR5_MUTMIC1_DISABLED, + AB8500_CODEC_CR5_MUTMIC1_ENABLED +} t_ab8500_codec_cr5_mutmic1; + +/* CR5 - 2 */ +typedef enum { + AB8500_CODEC_CR5_MUTMIC2_DISABLED, + AB8500_CODEC_CR5_MUTMIC2_ENABLED +} t_ab8500_codec_cr5_mutmic2; + +/* CR5 - 1 */ +typedef enum { + AB8500_CODEC_CR5_MUTLINL_DISABLED, + AB8500_CODEC_CR5_MUTLINL_ENABLED +} t_ab8500_codec_cr5_mutlinl; + +/* CR5 - 0 */ +typedef enum { + AB8500_CODEC_CR5_MUTLINR_DISABLED, + AB8500_CODEC_CR5_MUTLINR_ENABLED +} t_ab8500_codec_cr5_mutlinr; + +/* CR6 - 7 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC1_DISABLED, + AB8500_CODEC_CR6_ENDMIC1_ENABLED +} t_ab8500_codec_cr6_endmic1; + +/* CR6 - 6 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC2_DISABLED, + AB8500_CODEC_CR6_ENDMIC2_ENABLED +} t_ab8500_codec_cr6_endmic2; + +/* CR6 - 5 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC3_DISABLED, + AB8500_CODEC_CR6_ENDMIC3_ENABLED +} t_ab8500_codec_cr6_endmic3; + +/* CR6 - 4 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC4_DISABLED, + AB8500_CODEC_CR6_ENDMIC4_ENABLED +} t_ab8500_codec_cr6_endmic4; + +/* CR6 - 3 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC5_DISABLED, + AB8500_CODEC_CR6_ENDMIC5_ENABLED +} t_ab8500_codec_cr6_endmic5; + +/* CR6 - 2 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC6_DISABLED, + AB8500_CODEC_CR6_ENDMIC6_ENABLED +} t_ab8500_codec_cr6_endmic6; + +/* CR7 - 7 */ +typedef enum { + AB8500_CODEC_CR7_MIC1SEL_MIC1A, + AB8500_CODEC_CR7_MIC1SEL_MIC1B +} t_ab8500_codec_cr7_mic1sel; + +/* CR7 - 6 */ +typedef enum { + AB8500_CODEC_CR7_LINRSEL_MIC2, + AB8500_CODEC_CR7_LINRSEL_LINR +} t_ab8500_codec_cr7_linrsel; + +/* CR7 - 5 */ +typedef enum { + AB8500_CODEC_CR7_ENDRVHSL_DISABLED, + AB8500_CODEC_CR7_ENDRVHSL_ENABLED +} t_ab8500_codec_cr7_endrvhsl; + +/* CR7 - 4 */ +typedef enum { + AB8500_CODEC_CR7_ENDRVHSR_DISABLED, + AB8500_CODEC_CR7_ENDRVHSR_ENABLED +} t_ab8500_codec_cr7_endrvhsr; + +/* CR7 - 2 */ +typedef enum { + AB8500_CODEC_CR7_ENADCMIC_DISABLED, + AB8500_CODEC_CR7_ENADCMIC_ENABLED +} t_ab8500_codec_cr7_enadcmic; + +/* CR7 - 1 */ +typedef enum { + AB8500_CODEC_CR7_ENADCLINL_DISABLED, + AB8500_CODEC_CR7_ENADCLINL_ENABLED +} t_ab8500_codec_cr7_enadclinl; + +/* CR7 - 0 */ +typedef enum { + AB8500_CODEC_CR7_ENADCLINR_DISABLED, + AB8500_CODEC_CR7_ENADCLINR_ENABLED +} t_ab8500_codec_cr7_enadclinr; + +/* CR8 - 7 */ +typedef enum { + AB8500_CODEC_CR8_CP_DIS_PLDWN_ENABLED, + AB8500_CODEC_CR8_CP_DIS_PLDWN_DISABLED +} t_ab8500_codec_cr8_cp_dis_pldwn; + +/* CR8 - 6 */ +typedef enum { + AB8500_CODEC_CR8_ENEAR_DISABLED, + AB8500_CODEC_CR8_ENEAR_ENABLED +} t_ab8500_codec_cr8_enear; + +/* CR8 - 5 */ +typedef enum { + AB8500_CODEC_CR8_ENHSL_DISABLED, + AB8500_CODEC_CR8_ENHSL_ENABLED +} t_ab8500_codec_cr8_enhsl; + +/* CR8 - 4 */ +typedef enum { + AB8500_CODEC_CR8_ENHSR_DISABLED, + AB8500_CODEC_CR8_ENHSR_ENABLED +} t_ab8500_codec_cr8_enhsr; + +/* CR8 - 3 */ +typedef enum { + AB8500_CODEC_CR8_ENHFL_DISABLED, + AB8500_CODEC_CR8_ENHFL_ENABLED +} t_ab8500_codec_cr8_enhfl; + +/* CR8 - 2 */ +typedef enum { + AB8500_CODEC_CR8_ENHFR_DISABLED, + AB8500_CODEC_CR8_ENHFR_ENABLED +} t_ab8500_codec_cr8_enhfr; + +/* CR8 - 1 */ +typedef enum { + AB8500_CODEC_CR8_ENVIBL_DISABLED, + AB8500_CODEC_CR8_ENVIBL_ENABLED +} t_ab8500_codec_cr8_envibl; + +/* CR8 - 0 */ +typedef enum { + AB8500_CODEC_CR8_ENVIBR_DISABLED, + AB8500_CODEC_CR8_ENVIBR_ENABLED +} t_ab8500_codec_cr8_envibr; + +/* CR9 - 6 */ +typedef enum { + AB8500_CODEC_CR9_ENDACEAR_DISABLED, + AB8500_CODEC_CR9_ENDACEAR_ENABLED +} t_ab8500_codec_cr9_endacear; + +/* CR9 - 5 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHSL_DISABLED, + AB8500_CODEC_CR9_ENDACHSL_ENABLED +} t_ab8500_codec_cr9_endachsl; + +/* CR9 - 4 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHSR_DISABLED, + AB8500_CODEC_CR9_ENDACHSR_ENABLED +} t_ab8500_codec_cr9_endachsr; + +/* CR9 - 3 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHFL_DISABLED, + AB8500_CODEC_CR9_ENDACHFL_ENABLED +} t_ab8500_codec_cr9_endachfl; + +/* CR9 - 2 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHFR_DISABLED, + AB8500_CODEC_CR9_ENDACHFR_ENABLED +} t_ab8500_codec_cr9_endachfr; + +/* CR9 - 1 */ +typedef enum { + AB8500_CODEC_CR9_ENDACVIBL_DISABLED, + AB8500_CODEC_CR9_ENDACVIBL_ENABLED +} t_ab8500_codec_cr9_endacvibl; + +/* CR9 - 0 */ +typedef enum { + AB8500_CODEC_CR9_ENDACVIBR_DISABLED, + AB8500_CODEC_CR9_ENDACVIBR_ENABLED +} t_ab8500_codec_cr9_endacvibr; + +/* CR10 - 6 */ +typedef enum { + AB8500_CODEC_CR10_MUTEEAR_DISABLED, + AB8500_CODEC_CR10_MUTEEAR_ENABLED +} t_ab8500_codec_cr10_muteear; + +/* CR10 - 5 */ +typedef enum { + AB8500_CODEC_CR10_MUTEHSL_DISABLED, + AB8500_CODEC_CR10_MUTEHSL_ENABLED +} t_ab8500_codec_cr10_mutehsl; + +/* CR10 - 4 */ +typedef enum { + AB8500_CODEC_CR10_MUTEHSR_DISABLED, + AB8500_CODEC_CR10_MUTEHSR_ENABLED +} t_ab8500_codec_cr10_mutehsr; + +/* CR10 - 3 */ +typedef enum { + AB8500_CODEC_CR10_MUTEHFL_DISABLED, + AB8500_CODEC_CR10_MUTEHFL_ENABLED +} t_ab8500_codec_cr10_mutehfl; + +/* CR10 - 2 */ +typedef enum { + AB8500_CODEC_CR10_MUTEHFR_DISABLED, + AB8500_CODEC_CR10_MUTEHFR_ENABLED +} t_ab8500_codec_cr10_mutehfr; + +/* CR10 - 1 */ +typedef enum { + AB8500_CODEC_CR10_MUTEVIBL_DISABLED, + AB8500_CODEC_CR10_MUTEVIBL_ENABLED +} t_ab8500_codec_cr10_mutevibl; + +/* CR10 - 0 */ +typedef enum { + AB8500_CODEC_CR10_MUTEVIBR_DISABLED, + AB8500_CODEC_CR10_MUTEVIBR_ENABLED +} t_ab8500_codec_cr10_mutevibr; + +/* CR11 - 7 */ +typedef enum { + AB8500_CODEC_CR11_EARSHORTPWD_DISABLED, + AB8500_CODEC_CR11_EARSHORTPWD_ENABLED +} t_ab8500_codec_cr11_earshortpwd; + +/* CR11 - 6 */ +typedef enum { + AB8500_CODEC_CR11_EARSHORTDIS_ENABLED, + AB8500_CODEC_CR11_EARSHORTDIS_DISABLED +} t_ab8500_codec_cr11_earshortdis; + +/* CR11 - 5 */ +typedef enum { + AB8500_CODEC_CR11_HSLSHORTDIS_ENABLED, + AB8500_CODEC_CR11_HSLSHORTDIS_DISABLED +} t_ab8500_codec_cr11_hslshortdis; + +/* CR11 - 4 */ +typedef enum { + AB8500_CODEC_CR11_HSRSHORTDIS_ENABLED, + AB8500_CODEC_CR11_HSRSHORTDIS_DISABLED +} t_ab8500_codec_cr11_hsrshortdis; + +/* CR11 - 3 */ +typedef enum { + AB8500_CODEC_CR11_HFLSHORTDIS_ENABLED, + AB8500_CODEC_CR11_HFLSHORTDIS_DISABLED +} t_ab8500_codec_cr11_hflshortdis; + +/* CR11 - 2 */ +typedef enum { + AB8500_CODEC_CR11_HFRSHORTDIS_ENABLED, + AB8500_CODEC_CR11_HFRSHORTDIS_DISABLED +} t_ab8500_codec_cr11_hfrshortdis; + +/* CR11 - 1 */ +typedef enum { + AB8500_CODEC_CR11_VIBLSHORTDIS_ENABLED, + AB8500_CODEC_CR11_VIBLSHORTDIS_DISABLED +} t_ab8500_codec_cr11_viblshortdis; + +/* CR11 - 0 */ +typedef enum { + AB8500_CODEC_CR11_VIBRSHORTDIS_ENABLED, + AB8500_CODEC_CR11_VIBRSHORTDIS_DISABLED +} t_ab8500_codec_cr11_vibrshortdis; + +/* CR12 - 7 */ +typedef enum { + AB8500_CODEC_CR12_ENCPHS_DISABLED, + AB8500_CODEC_CR12_ENCPHS_ENABLED +} t_ab8500_codec_cr12_encphs; + +/* CR12 - 6:4 */ +typedef enum { + AB8500_CODEC_CR12_HSAUTOTIME_6_6USEC, + AB8500_CODEC_CR12_HSAUTOTIME_13_3USEC, + AB8500_CODEC_CR12_HSAUTOTIME_26_6USEC, + AB8500_CODEC_CR12_HSAUTOTIME_53_2USEC, + AB8500_CODEC_CR12_HSAUTOTIME_106_4USEC, + AB8500_CODEC_CR12_HSAUTOTIME_212_8USEC, + AB8500_CODEC_CR12_HSAUTOTIME_425_6USEC, + AB8500_CODEC_CR12_HSAUTOTIME_851_2USEC, +} t_ab8500_codec_cr12_hsautotime; + +/* CR12 - 1 */ +typedef enum { + AB8500_CODEC_CR12_HSAUTOENSEL_DISABLED, + AB8500_CODEC_CR12_HSAUTOENSEL_ENABLED +} t_ab8500_codec_cr12_hsautoensel; + +/* CR12 - 0 */ +typedef enum { + AB8500_CODEC_CR12_HSAUTOEN_DISABLED, + AB8500_CODEC_CR12_HSAUTOEN_ENABLED +} t_ab8500_codec_cr12_hsautoen; + +/* CR13 - 7:4 */ +typedef enum { + AB8500_CODEC_CR13_ENVDET_HTHRESH_25, + AB8500_CODEC_CR13_ENVDET_HTHRESH_50, + AB8500_CODEC_CR13_ENVDET_HTHRESH_100, + AB8500_CODEC_CR13_ENVDET_HTHRESH_150, + AB8500_CODEC_CR13_ENVDET_HTHRESH_200, + AB8500_CODEC_CR13_ENVDET_HTHRESH_250, + AB8500_CODEC_CR13_ENVDET_HTHRESH_300, + AB8500_CODEC_CR13_ENVDET_HTHRESH_350, + AB8500_CODEC_CR13_ENVDET_HTHRESH_400, + AB8500_CODEC_CR13_ENVDET_HTHRESH_450, + AB8500_CODEC_CR13_ENVDET_HTHRESH_500, + AB8500_CODEC_CR13_ENVDET_HTHRESH_550, + AB8500_CODEC_CR13_ENVDET_HTHRESH_600, + AB8500_CODEC_CR13_ENVDET_HTHRESH_650, + AB8500_CODEC_CR13_ENVDET_HTHRESH_700, + AB8500_CODEC_CR13_ENVDET_HTHRESH_750 +} t_ab8500_codec_cr13_envdet_hthresh; + +/* CR13 - 3:0 */ +typedef enum { + AB8500_CODEC_CR13_ENVDET_LTHRESH_25, + AB8500_CODEC_CR13_ENVDET_LTHRESH_50, + AB8500_CODEC_CR13_ENVDET_LTHRESH_100, + AB8500_CODEC_CR13_ENVDET_LTHRESH_150, + AB8500_CODEC_CR13_ENVDET_LTHRESH_200, + AB8500_CODEC_CR13_ENVDET_LTHRESH_250, + AB8500_CODEC_CR13_ENVDET_LTHRESH_300, + AB8500_CODEC_CR13_ENVDET_LTHRESH_350, + AB8500_CODEC_CR13_ENVDET_LTHRESH_400, + AB8500_CODEC_CR13_ENVDET_LTHRESH_450, + AB8500_CODEC_CR13_ENVDET_LTHRESH_500, + AB8500_CODEC_CR13_ENVDET_LTHRESH_550, + AB8500_CODEC_CR13_ENVDET_LTHRESH_600, + AB8500_CODEC_CR13_ENVDET_LTHRESH_650, + AB8500_CODEC_CR13_ENVDET_LTHRESH_700, + AB8500_CODEC_CR13_ENVDET_LTHRESH_750 +} t_ab8500_codec_cr13_envdet_lthresh; + +/* CR14 - 7 */ +typedef enum { + AB8500_CODEC_CR14_SMPSLVEN_HIGHVOLTAGE, + AB8500_CODEC_CR14_SMPSLVEN_LOWVOLTAGE +} t_ab8500_codec_cr14_smpslven; + +/* CR14 - 6 */ +typedef enum { + AB8500_CODEC_CR14_ENVDETSMPSEN_DISABLED, + AB8500_CODEC_CR14_ENVDETSMPSEN_ENABLED +} t_ab8500_codec_cr14_envdetsmpsen; + +/* CR14 - 5 */ +typedef enum { + AB8500_CODEC_CR14_CPLVEN_HIGHVOLTAGE, + AB8500_CODEC_CR14_CPLVEN_LOWVOLTAGE +} t_ab8500_codec_cr14_cplven; + +/* CR14 - 4 */ +typedef enum { + AB8500_CODEC_CR14_ENVDETCPEN_DISABLED, + AB8500_CODEC_CR14_ENVDETCPEN_ENABLED +} t_ab8500_codec_cr14_envdetcpen; + +/* CR14 - 3:0 */ +typedef enum { + AB8500_CODEC_CR14_ENVET_TIME_27USEC, + AB8500_CODEC_CR14_ENVET_TIME_53USEC, + AB8500_CODEC_CR14_ENVET_TIME_106USEC, + AB8500_CODEC_CR14_ENVET_TIME_212USEC, + AB8500_CODEC_CR14_ENVET_TIME_424USEC, + AB8500_CODEC_CR14_ENVET_TIME_848USEC, + AB8500_CODEC_CR14_ENVET_TIME_1MSEC, + AB8500_CODEC_CR14_ENVET_TIME_3MSEC, + AB8500_CODEC_CR14_ENVET_TIME_6MSEC, + AB8500_CODEC_CR14_ENVET_TIME_13MSEC, + AB8500_CODEC_CR14_ENVET_TIME_27MSEC, + AB8500_CODEC_CR14_ENVET_TIME_54MSEC, + AB8500_CODEC_CR14_ENVET_TIME_109MSEC, + AB8500_CODEC_CR14_ENVET_TIME_218MSEC, + AB8500_CODEC_CR14_ENVET_TIME_436MSEC, + AB8500_CODEC_CR14_ENVET_TIME_872MSEC, +} t_ab8500_codec_cr14_envet_time; + +/* CR15 - 7 */ +typedef enum { + AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH, + AB8500_CODEC_CR15_PWMTOVIBL_PWM +} t_ab8500_codec_cr15_pwmtovibl; + +/* CR15 - 6 */ +typedef enum { + AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH, + AB8500_CODEC_CR15_PWMTOVIBR_PWM +} t_ab8500_codec_cr15_pwmtovibr; + +/* CR15 - 5 */ +typedef enum { + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL, + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE +} t_ab8500_codec_cr15_pwmlctrl; + +/* CR15 - 4 */ +typedef enum { + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL, + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE +} t_ab8500_codec_cr15_pwmrctrl; + +/* CR15 - 3 */ +typedef enum { + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL, + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE +} t_ab8500_codec_cr15_pwmnlctrl; + +/* CR15 - 2 */ +typedef enum { + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL, + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE +} t_ab8500_codec_cr15_pwmplctrl; + +/* CR15 - 1 */ +typedef enum { + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL, + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE +} t_ab8500_codec_cr15_pwmnrctrl; + +/* CR15 - 0 */ +typedef enum { + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL, + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE +} t_ab8500_codec_cr15_pwmprctrl; + +/* CR16 - 7 */ +typedef enum { + AB8500_CODEC_CR16_PWMNLPOL_GNDVIB, + AB8500_CODEC_CR16_PWMNLPOL_VINVIB +} t_ab8500_codec_cr16_pwmnlpol; + +/* CR16 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr16_pwmnldutycycle; + +/* CR17 - 7 */ +typedef enum { + AB8500_CODEC_CR17_PWMPLPOL_GNDVIB, + AB8500_CODEC_CR17_PWMPLPOL_VINVIB +} t_ab8500_codec_cr17_pwmplpol; + +/* CR17 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr17_pwmpldutycycle; + +/* CR18 - 7 */ +typedef enum { + AB8500_CODEC_CR18_PWMNRPOL_GNDVIB, + AB8500_CODEC_CR18_PWMNRPOL_VINVIB +} t_ab8500_codec_cr18_pwmnrpol; + +/* CR18 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr18_pwmnrdutycycle; + +/* CR19 - 7 */ +typedef enum { + AB8500_CODEC_CR19_PWMPRPOL_GNDVIB, + AB8500_CODEC_CR19_PWMPRPOL_VINVIB +} t_ab8500_codec_cr19_pwmprpol; + +/* CR19 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr19_pwmprdutycycle; + +/* CR20 - 7 */ +typedef enum { + AB8500_CODEC_CR20_EN_SE_MIC1_DIFFERENTIAL, + AB8500_CODEC_CR20_EN_SE_MIC1_SINGLE +} t_ab8500_codec_cr20_en_se_mic1; + +/* CR20 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr20_mic1_gain; + +/* CR21 - 7 */ +typedef enum { + AB8500_CODEC_CR21_EN_SE_MIC2_DIFFERENTIAL, + AB8500_CODEC_CR21_EN_SE_MIC2_SINGLE +} t_ab8500_codec_cr21_en_se_mic2; + +/* CR21 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr21_mic2_gain; + +/* CR22 - 7:5 */ +typedef t_uint8 t_ab8500_codec_cr22_hsl_gain; + +/* CR22 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr22_linl_gain; + +/* CR23 - 7:5 */ +typedef t_uint8 t_ab8500_codec_cr23_hsr_gain; + +/* CR23 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr23_linr_gain; + +/* CR24 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr24_lintohsl_gain; + +/* CR25 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr25_lintohsr_gain; + +/* CR26 - 7 */ +typedef enum { + AB8500_CODEC_CR26_AD1NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD1NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad1nh; + +/* CR26 - 6 */ +typedef enum { + AB8500_CODEC_CR26_AD2NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD2NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad2nh; + +/* CR26 - 5 */ +typedef enum { + AB8500_CODEC_CR26_AD3NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD3NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad3nh; + +/* CR26 - 4 */ +typedef enum { + AB8500_CODEC_CR26_AD4NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD4NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad4nh; + +/* CR26 - 3 */ +typedef enum { + AB8500_CODEC_CR26_AD1_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD1_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad1_voice; + +/* CR26 - 2 */ +typedef enum { + AB8500_CODEC_CR26_AD2_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD2_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad2_voice; + +/* CR26 - 1 */ +typedef enum { + AB8500_CODEC_CR26_AD3_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD3_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad3_voice; + +/* CR26 - 0 */ +typedef enum { + AB8500_CODEC_CR26_AD4_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD4_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad4_voice; + +/* CR27 - 7 */ +typedef enum { + AB8500_CODEC_CR27_EN_MASTGEN_DISABLED, + AB8500_CODEC_CR27_EN_MASTGEN_ENABLED +} t_ab8500_codec_cr27_en_mastgen; + +/* CR27 - 6:5 */ +typedef enum { + AB8500_CODEC_CR27_IF1_BITCLK_OSR_32, + AB8500_CODEC_CR27_IF1_BITCLK_OSR_64, + AB8500_CODEC_CR27_IF1_BITCLK_OSR_128, + AB8500_CODEC_CR27_IF1_BITCLK_OSR_256 +} t_ab8500_codec_cr27_if1_bitclk_osr; + +/* CR27 - 4 */ +typedef enum { + AB8500_CODEC_CR27_ENFS_BITCLK1_DISABLED, + AB8500_CODEC_CR27_ENFS_BITCLK1_ENABLED +} t_ab8500_codec_cr27_enfs_bitclk1; + +/* CR27 - 2:1 */ +typedef enum { + AB8500_CODEC_CR27_IF0_BITCLK_OSR_32, + AB8500_CODEC_CR27_IF0_BITCLK_OSR_64, + AB8500_CODEC_CR27_IF0_BITCLK_OSR_128, + AB8500_CODEC_CR27_IF0_BITCLK_OSR_256 +} t_ab8500_codec_cr27_if0_bitclk_osr; + +/* CR27 - 0 */ +typedef enum { + AB8500_CODEC_CR27_ENFS_BITCLK0_DISABLED, + AB8500_CODEC_CR27_ENFS_BITCLK0_ENABLED +} t_ab8500_codec_cr27_enfs_bitclk0; + +/* CR28 - 6 */ +typedef enum { + AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE, + AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE +} t_ab8500_codec_cr28_fsync0p; + +/* CR28 - 5 */ +typedef enum { + AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE, + AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE +} t_ab8500_codec_cr28_bitclk0p; + +/* CR28 - 4 */ +typedef enum { + AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED, + AB8500_CODEC_CR28_IF0DEL_DELAYED +} t_ab8500_codec_cr28_if0del; + +/* CR28 - 3:2 */ +typedef enum { + AB8500_CODEC_CR28_IF0FORMAT_DISABLED, + AB8500_CODEC_CR28_IF0FORMAT_TDM, + AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED +} t_ab8500_codec_cr28_if0format; + +/* CR28 - 1:0 */ +typedef enum { + AB8500_CODEC_CR28_IF0WL_16BITS, + AB8500_CODEC_CR28_IF0WL_20BITS, + AB8500_CODEC_CR28_IF0WL_24BITS, + AB8500_CODEC_CR28_IF0WL_32BITS +} t_ab8500_codec_cr28_if0wl; + +/* CR29 - 7 */ +typedef enum { + AB8500_CODEC_CR29_IF0DATOIF1AD_NOTSENT, + AB8500_CODEC_CR29_IF0DATOIF1AD_SENT +} t_ab8500_codec_cr29_if0datoif1ad; + +/* CR29 - 6 */ +typedef enum { + AB8500_CODEC_CR29_IF0CKTOIF1CK_NOTSENT, + AB8500_CODEC_CR29_IF0CKTOIF1CK_SENT +} t_ab8500_codec_cr29_if0cktoif1ck; + +/* CR29 - 5 */ +typedef enum { + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_INPUT, + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_OUTPUT +} t_ab8500_codec_cr29_if1master; + +/* CR29 - 3 */ +typedef enum { + AB8500_CODEC_CR29_IF1DATOIF0AD_NOTSENT, + AB8500_CODEC_CR29_IF1DATOIF0AD_SENT +} t_ab8500_codec_cr29_if1datoif0ad; + +/* CR29 - 2 */ +typedef enum { + AB8500_CODEC_CR29_IF1CKTOIF0CK_NOTSENT, + AB8500_CODEC_CR29_IF1CKTOIF0CK_SENT +} t_ab8500_codec_cr29_if1cktoif0ck; + +/* CR29 - 1 */ +typedef enum { + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_INPUT, + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_OUTPUT +} t_ab8500_codec_cr29_if0master; + +/* CR29 - 0 */ +typedef enum { + AB8500_CODEC_CR29_IF0BFIFOEN_NORMAL_MODE, + AB8500_CODEC_CR29_IF0BFIFOEN_BURST_MODE +} t_ab8500_codec_cr29_if0bfifoen; + +/* CR30 - 6 */ +typedef enum { + AB8500_CODEC_CR30_FSYNC1P_RISING_EDGE, + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE +} t_ab8500_codec_cr30_fsync1p; + +/* CR30 - 5 */ +typedef enum { + AB8500_CODEC_CR30_BITCLK1P_RISING_EDGE, + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE +} t_ab8500_codec_cr30_bitclk1p; + +/* CR30 - 4 */ +typedef enum { + AB8500_CODEC_CR30_IF1DEL_NOT_DELAYED, + AB8500_CODEC_CR30_IF1DEL_DELAYED +} t_ab8500_codec_cr30_if1del; + +/* CR30 - 3:2 */ +typedef enum { + AB8500_CODEC_CR30_IF1FORMAT_DISABLED, + AB8500_CODEC_CR30_IF1FORMAT_TDM, + AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED +} t_ab8500_codec_cr30_if1format; + +/* CR30 - 1:0 */ +typedef enum { + AB8500_CODEC_CR30_IF1WL_16BITS, + AB8500_CODEC_CR30_IF1WL_20BITS, + AB8500_CODEC_CR30_IF1WL_24BITS, + AB8500_CODEC_CR30_IF1WL_32BITS +} t_ab8500_codec_cr30_if1wl; + +/* CR31:46 - 7:4 or 3:0 */ +/* In ab8500_codec.h */ + +/* CR47:50 - 7/6/5/4/3/2/1/0 */ +typedef enum { + AB8500_CODEC_CR47_TO_CR50_HIZ_SL_LOW_IMPEDANCE, + AB8500_CODEC_CR47_TO_CR50_HIZ_SL_HIGH_IMPEDANCE, +} t_ab8500_codec_cr47_to_cr50_hiz_sl; + +/* CR51 - 7 */ +typedef enum { + AB8500_CODEC_CR51_DA12_VOICE_AUDIOFILTER, + AB8500_CODEC_CR51_DA12_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr51_da12_voice; + +/* CR51 - 5 */ +typedef enum { + AB8500_CODEC_CR51_SLDAI1TOSLADO1_NOT_LOOPEDBACK, + AB8500_CODEC_CR51_SLDAI1TOSLADO1_LOOPEDBACK +} t_ab8500_codec_cr51_sldai1toslado1; + +/* CR51:56 - 4:0 */ +/* In ab8500_codec.h */ + +/* CR52 - 5 */ +typedef enum { + AB8500_CODEC_CR52_SLDAI2TOSLADO2_NOT_LOOPEDBACK, + AB8500_CODEC_CR52_SLDAI2TOSLADO2_LOOPEDBACK +} t_ab8500_codec_cr52_sldai2toslado2; + +/* CR53 - 7 */ +typedef enum { + AB8500_CODEC_CR53_DA34_VOICE_AUDIOFILTER, + AB8500_CODEC_CR53_DA34_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr53_da34_voice; + +/* CR53 - 5 */ +typedef enum { + AB8500_CODEC_CR53_SLDAI3TOSLADO3_NOT_LOOPEDBACK, + AB8500_CODEC_CR53_SLDAI3TOSLADO3_LOOPEDBACK +} t_ab8500_codec_cr53_sldai3toslado3; + +/* CR54 - 5 */ +typedef enum { + AB8500_CODEC_CR54_SLDAI4TOSLADO4_NOT_LOOPEDBACK, + AB8500_CODEC_CR54_SLDAI4TOSLADO4_LOOPEDBACK +} t_ab8500_codec_cr54_sldai4toslado4; + +/* CR55 - 7 */ +typedef enum { + AB8500_CODEC_CR55_DA56_VOICE_AUDIOFILTER, + AB8500_CODEC_CR55_DA56_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr55_da56_voice; + +/* CR55 - 6:5 */ +typedef enum { + AB8500_CODEC_CR55_SLDAI5TOSLADO5_NOT_LOOPEDBACK, + AB8500_CODEC_CR55_SLDAI5TOSLADO5_DA_IN1_LOOPEDBACK, + AB8500_CODEC_CR55_SLDAI5TOSLADO5_DA_IN3_LOOPEDBACK, + AB8500_CODEC_CR55_SLDAI5TOSLADO5_DA_IN5_LOOPEDBACK +} t_ab8500_codec_cr55_sldai5toslado5; + +/* CR56 - 6:5 */ +typedef enum { + AB8500_CODEC_CR56_SLDAI6TOSLADO7_NOT_LOOPEDBACK, + AB8500_CODEC_CR56_SLDAI6TOSLADO7_DA_IN2_LOOPEDBACK, + AB8500_CODEC_CR56_SLDAI6TOSLADO7_DA_IN4_LOOPEDBACK, + AB8500_CODEC_CR56_SLDAI6TOSLADO7_DA_IN6_LOOPEDBACK +} t_ab8500_codec_cr56_sldai6toslado7; + +/* CR57 - 6 */ +typedef enum { + AB8500_CODEC_CR57_BFIFULL_MSK_MASKED, + AB8500_CODEC_CR57_BFIFULL_MSK_ENABLED +} t_ab8500_codec_cr57_bfifull_msk; + +/* CR57 - 5 */ +typedef enum { + AB8500_CODEC_CR57_BFIEMPT_MSK_MASKED, + AB8500_CODEC_CR57_BFIEMPT_MSK_ENABLED +} t_ab8500_codec_cr57_bfiempt_msk; + +/* CR57 - 4 */ +typedef enum { + AB8500_CODEC_CR57_DACHAN_MSK_MASKED, + AB8500_CODEC_CR57_DACHAN_MSK_ENABLED +} t_ab8500_codec_cr57_dachan_msk; + +/* CR57 - 3 */ +typedef enum { + AB8500_CODEC_CR57_GAIN_MSK_MASKED, + AB8500_CODEC_CR57_GAIN_MSK_ENABLED +} t_ab8500_codec_cr57_gain_msk; + +/* CR57 - 2 */ +typedef enum { + AB8500_CODEC_CR57_DSPAD_MSK_MASKED, + AB8500_CODEC_CR57_DSPAD_MSK_ENABLED +} t_ab8500_codec_cr57_dspad_msk; + +/* CR57 - 1 */ +typedef enum { + AB8500_CODEC_CR57_DSPDA_MSK_MASKED, + AB8500_CODEC_CR57_DSPDA_MSK_ENABLED +} t_ab8500_codec_cr57_dspda_msk; + +/* CR57 - 0 */ +typedef enum { + AB8500_CODEC_CR57_STFIR_MSK_MASKED, + AB8500_CODEC_CR57_STFIR_MSK_ENABLED +} t_ab8500_codec_cr57_stfir_msk; + +/* CR58 - Read Only */ +/* CR58 - 6 */ +typedef enum { + AB8500_CODEC_CR58_BFIFULL_EV_NOT_FULL, + AB8500_CODEC_CR58_BFIFULL_EV_FULL +} t_ab8500_codec_cr58_bfifull_ev; + +/* CR58 - 5 */ +typedef enum { + AB8500_CODEC_CR58_BFIEMPT_EV_NOT_EMPTY, + AB8500_CODEC_CR58_BFIEMPT_EV_EMPTY +} t_ab8500_codec_cr58_bfiempt_ev; + +/* CR58 - 4 */ +typedef enum { + AB8500_CODEC_CR58_DACHAN_EV_NO_SATURATION, + AB8500_CODEC_CR58_DACHAN_EV_SATURATION +} t_ab8500_codec_cr58_dachan_ev; + +/* CR58 - 3 */ +typedef enum { + AB8500_CODEC_CR58_GAIN_EV_NO_SATURATION, + AB8500_CODEC_CR58_GAIN_EV_SATURATION +} t_ab8500_codec_cr58_gain_ev; + +/* CR58 - 2 */ +typedef enum { + AB8500_CODEC_CR58_DSPAD_EV_NO_SATURATION, + AB8500_CODEC_CR58_DSPAD_EV_SATURATION +} t_ab8500_codec_cr58_dspad_ev; + +/* CR58 - 1 */ +typedef enum { + AB8500_CODEC_CR58_DSPDA_EV_NO_SATURATION, + AB8500_CODEC_CR58_DSPDA_EV_SATURATION +} t_ab8500_codec_cr58_dspda_ev; + +/* CR58 - 0 */ +typedef enum { + AB8500_CODEC_CR58_STFIR_EV_NO_SATURATION, + AB8500_CODEC_CR58_STFIR_EV_SATURATION +} t_ab8500_codec_cr58_stfir_ev; + +/* CR59 - 7 */ +typedef enum { + AB8500_CODEC_CR59_VSSREADY_MSK_MASKED, + AB8500_CODEC_CR59_VSSREADY_MSK_ENABLED +} t_ab8500_codec_cr59_vssready_msk; + +/* CR59 - 6 */ +typedef enum { + AB8500_CODEC_CR59_SHRTVIBL_MSK_MASKED, + AB8500_CODEC_CR59_SHRTVIBL_MSK_ENABLED +} t_ab8500_codec_cr59_shrtvibl_msk; + +/* CR59 - 5 */ +typedef enum { + AB8500_CODEC_CR59_SHRTVIBR_MSK_MASKED, + AB8500_CODEC_CR59_SHRTVIBR_MSK_ENABLED +} t_ab8500_codec_cr59_shrtvibr_msk; + +/* CR59 - 4 */ +typedef enum { + AB8500_CODEC_CR59_SHRTHFL_MSK_MASKED, + AB8500_CODEC_CR59_SHRTHFL_MSK_ENABLED +} t_ab8500_codec_cr59_shrthfl_msk; + +/* CR59 - 3 */ +typedef enum { + AB8500_CODEC_CR59_SHRTHFR_MSK_MASKED, + AB8500_CODEC_CR59_SHRTHFR_MSK_ENABLED +} t_ab8500_codec_cr59_shrthfr_msk; + +/* CR59 - 2 */ +typedef enum { + AB8500_CODEC_CR59_SHRTHSL_MSK_MASKED, + AB8500_CODEC_CR59_SHRTHSL_MSK_ENABLED +} t_ab8500_codec_cr59_shrthsl_msk; + +/* CR59 - 1 */ +typedef enum { + AB8500_CODEC_CR59_SHRTHSR_MSK_MASKED, + AB8500_CODEC_CR59_SHRTHSR_MSK_ENABLED +} t_ab8500_codec_cr59_shrthsr_msk; + +/* CR59 - 0 */ +typedef enum { + AB8500_CODEC_CR59_SHRTEAR_MSK_MASKED, + AB8500_CODEC_CR59_SHRTEAR_MSK_ENABLED +} t_ab8500_codec_cr59_shrtear_msk; + +/* CR60 - Read Only */ +/* CR60 - 7 */ +typedef enum { + AB8500_CODEC_CR60_VSSREADY_EV_NOT_READY, + AB8500_CODEC_CR60_VSSREADY_EV_READY +} t_ab8500_codec_cr60_vssready_ev; + +/* CR60 - 6 */ +typedef enum { + AB8500_CODEC_CR60_SHRTVIBL_EV_NO_SHORTCIRCUIT, + AB8500_CODEC_CR60_SHRTVIBL_EV_SHORTCIRCUIT +} t_ab8500_codec_cr60_shrtvibl_ev; + +/* CR60 - 5 */ +typedef enum { + AB8500_CODEC_CR60_SHRTVIBR_EV_NO_SHORTCIRCUIT, + AB8500_CODEC_CR60_SHRTVIBR_EV_SHORTCIRCUIT +} t_ab8500_codec_cr60_shrtvibr_ev; + +/* CR60 - 4 */ +typedef enum { + AB8500_CODEC_CR60_SHRTHFL_EV_NO_SHORTCIRCUIT, + AB8500_CODEC_CR60_SHRTHFL_EV_SHORTCIRCUIT +} t_ab8500_codec_cr60_shrthfl_ev; + +/* CR60 - 3 */ +typedef enum { + AB8500_CODEC_CR60_SHRTHFR_EV_NO_SHORTCIRCUIT, + AB8500_CODEC_CR60_SHRTHFR_EV_SHORTCIRCUIT +} t_ab8500_codec_cr60_shrthfr_ev; + +/* CR60 - 2 */ +typedef enum { + AB8500_CODEC_CR60_SHRTHSL_EV_NO_SHORTCIRCUIT, + AB8500_CODEC_CR60_SHRTHSL_EV_SHORTCIRCUIT +} t_ab8500_codec_cr60_shrthsl_ev; + +/* CR60 - 1 */ +typedef enum { + AB8500_CODEC_CR60_SHRTHSR_EV_NO_SHORTCIRCUIT, + AB8500_CODEC_CR60_SHRTHSR_EV_SHORTCIRCUIT +} t_ab8500_codec_cr60_shrthsr_ev; + +/* CR60 - 0 */ +typedef enum { + AB8500_CODEC_CR60_SHRTEAR_EV_NO_SHORTCIRCUIT, + AB8500_CODEC_CR60_SHRTEAR_EV_SHORTCIRCUIT +} t_ab8500_codec_cr60_shrtear_ev; + +/* CR61 - 6:2 - Read Only */ +typedef enum { + AB8500_CODEC_CR61_REVISION_1_0, + AB8500_CODEC_CR61_REVISION_TBD +} t_ab8500_codec_cr61_revision; + +/* CR61 - 1:0 */ +typedef enum { + AB8500_CODEC_CR61_FADE_SPEED_1MS, + AB8500_CODEC_CR61_FADE_SPEED_4MS, + AB8500_CODEC_CR61_FADE_SPEED_8MS, + AB8500_CODEC_CR61_FADE_SPEED_16MS +} t_ab8500_codec_cr61_fade_speed; + +/* CR62 - Read Only */ +/* CR62 - 5 */ +typedef enum { + AB8500_CODEC_CR62_DMIC1SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC1SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic1sinc3; + +/* CR62 - 4 */ +typedef enum { + AB8500_CODEC_CR62_DMIC2SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC2SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic2sinc3; + +/* CR62 - 3 */ +typedef enum { + AB8500_CODEC_CR62_DMIC3SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC3SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic3sinc3; + +/* CR62 - 2 */ +typedef enum { + AB8500_CODEC_CR62_DMIC4SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC4SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic4sinc3; + +/* CR62 - 1 */ +typedef enum { + AB8500_CODEC_CR62_DMIC5SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC5SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic5sinc3; + +/* CR62 - 0 */ +typedef enum { + AB8500_CODEC_CR62_DMIC6SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC6SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic6sinc3; + +/* CR63 - 7 */ +typedef enum { + AB8500_CODEC_CR63_DATOHSLEN_DISABLED, + AB8500_CODEC_CR63_DATOHSLEN_ENABLED +} t_ab8500_codec_cr63_datohslen; + +/* CR63 - 6 */ +typedef enum { + AB8500_CODEC_CR63_DATOHSREN_DISABLED, + AB8500_CODEC_CR63_DATOHSREN_ENABLED +} t_ab8500_codec_cr63_datohsren; + +/* CR63 - 5 */ +typedef enum { + AB8500_CODEC_CR63_AD1SEL_LINLADL_SELECTED, + AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED +} t_ab8500_codec_cr63_ad1sel; + +/* CR63 - 4 */ +typedef enum { + AB8500_CODEC_CR63_AD2SEL_LINRADR_SELECTED, + AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED +} t_ab8500_codec_cr63_ad2sel; + +/* CR63 - 3 */ +typedef enum { + AB8500_CODEC_CR63_AD3SEL_ADMO_SELECTED, + AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED +} t_ab8500_codec_cr63_ad3sel; + +/* CR63 - 2 */ +typedef enum { + AB8500_CODEC_CR63_AD5SEL_AMADR_SELECTED, + AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED +} t_ab8500_codec_cr63_ad5sel; + +/* CR63 - 1 */ +typedef enum { + AB8500_CODEC_CR63_AD6SEL_ADMO_SELECTED, + AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED +} t_ab8500_codec_cr63_ad6sel; + +/* CR63 - 0 */ +typedef enum { + AB8500_CODEC_CR63_ANCSEL_NOT_MIXED_IN_EAR, + AB8500_CODEC_CR63_ANCSEL_MIXED_IN_EAR +} t_ab8500_codec_cr63_ancsel; + +/* CR64 - 7 */ +typedef enum { + AB8500_CODEC_CR64_DATOHFREN_NOT_MIXED_TO_HFR, + AB8500_CODEC_CR64_DATOHFREN_MIXED_TO_HFR +} t_ab8500_codec_cr64_datohfren; + +/* CR64 - 6 */ +typedef enum { + AB8500_CODEC_CR64_DATOHFLEN_NOT_MIXED_TO_HFL, + AB8500_CODEC_CR64_DATOHFLEN_MIXED_TO_HFL +} t_ab8500_codec_cr64_datohflen; + +/* CR64 - 5 */ +typedef enum { + AB8500_CODEC_CR64_HFRSEL_DA4_MIXED_TO_HFR, + AB8500_CODEC_CR64_HFRSEL_ANC_MIXED_TO_HFR +} t_ab8500_codec_cr64_hfrsel; + +/* CR64 - 4 */ +typedef enum { + AB8500_CODEC_CR64_HFLSEL_DA3_MIXED_TO_HFL, + AB8500_CODEC_CR64_HFLSEL_ANC_MIXED_TO_HFL +} t_ab8500_codec_cr64_hflsel; + +/* CR64 - 3:2 */ +typedef enum { + AB8500_CODEC_CR64_STFIR1SEL_AD_OUT1_SELECTED, + AB8500_CODEC_CR64_STFIR1SEL_AD_OUT3_SELECTED, + AB8500_CODEC_CR64_STFIR1SEL_DA_IN1_SELECTED +} t_ab8500_codec_cr64_stfir1sel; + +/* CR64 - 1:0 */ +typedef enum { + AB8500_CODEC_CR64_STFIR2SEL_AD_OUT2_SELECTED, + AB8500_CODEC_CR64_STFIR2SEL_AD_OUT4_SELECTED, + AB8500_CODEC_CR64_STFIR2SEL_DA_IN2_SELECTED +} t_ab8500_codec_cr64_stfir2sel; + +/* CR65 - 6 */ +typedef enum { + AB8500_CODEC_CR65_FADEDIS_AD1_ENABLED, + AB8500_CODEC_CR65_FADEDIS_AD1_DISABLED +} t_ab8500_codec_cr65_fadedis_ad1; + +/* CR65 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr65_ad1gain; + +/* CR66 - 6 */ +typedef enum { + AB8500_CODEC_CR66_FADEDIS_AD2_ENABLED, + AB8500_CODEC_CR66_FADEDIS_AD2_DISABLED +} t_ab8500_codec_cr66_fadedis_ad2; + +/* CR66 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr66_ad2gain; + +/* CR67 - 6 */ +typedef enum { + AB8500_CODEC_CR67_FADEDIS_AD3_ENABLED, + AB8500_CODEC_CR67_FADEDIS_AD3_DISABLED +} t_ab8500_codec_cr67_fadedis_ad3; + +/* CR67 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr67_ad3gain; + +/* CR68 - 6 */ +typedef enum { + AB8500_CODEC_CR68_FADEDIS_AD4_ENABLED, + AB8500_CODEC_CR68_FADEDIS_AD4_DISABLED +} t_ab8500_codec_cr68_fadedis_ad4; + +/* CR68 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr68_ad4gain; + +/* CR69 - 6 */ +typedef enum { + AB8500_CODEC_CR69_FADEDIS_AD5_ENABLED, + AB8500_CODEC_CR69_FADEDIS_AD5_DISABLED +} t_ab8500_codec_cr69_fadedis_ad5; + +/* CR69 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr69_ad5gain; + +/* CR70 - 6 */ +typedef enum { + AB8500_CODEC_CR70_FADEDIS_AD6_ENABLED, + AB8500_CODEC_CR70_FADEDIS_AD6_DISABLED +} t_ab8500_codec_cr70_fadedis_ad6; + +/* CR70 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr70_ad6gain; + +/* CR71 - 6 */ +typedef enum { + AB8500_CODEC_CR71_FADEDIS_DA1_ENABLED, + AB8500_CODEC_CR71_FADEDIS_DA1_DISABLED +} t_ab8500_codec_cr71_fadedis_da1; + +/* CR71 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr71_da1gain; + +/* CR72 - 6 */ +typedef enum { + AB8500_CODEC_CR72_FADEDIS_DA2_ENABLED, + AB8500_CODEC_CR72_FADEDIS_DA2_DISABLED +} t_ab8500_codec_cr72_fadedis_da2; + +/* CR72 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr72_da2gain; + +/* CR73 - 6 */ +typedef enum { + AB8500_CODEC_CR73_FADEDIS_DA3_ENABLED, + AB8500_CODEC_CR73_FADEDIS_DA3_DISABLED +} t_ab8500_codec_cr73_fadedis_da3; + +/* CR73 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr73_da3gain; + +/* CR74 - 6 */ +typedef enum { + AB8500_CODEC_CR74_FADEDIS_DA4_ENABLED, + AB8500_CODEC_CR74_FADEDIS_DA4_DISABLED +} t_ab8500_codec_cr74_fadedis_da4; + +/* CR74 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr74_da4gain; + +/* CR75 - 6 */ +typedef enum { + AB8500_CODEC_CR75_FADEDIS_DA5_ENABLED, + AB8500_CODEC_CR75_FADEDIS_DA5_DISABLED +} t_ab8500_codec_cr75_fadedis_da5; + +/* CR75 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr75_da5gain; + +/* CR76 - 6 */ +typedef enum { + AB8500_CODEC_CR76_FADEDIS_DA6_ENABLED, + AB8500_CODEC_CR76_FADEDIS_DA6_DISABLED +} t_ab8500_codec_cr76_fadedis_da6; + +/* CR76 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr76_da6gain; + +/* CR77 - 6 */ +typedef enum { + AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_ENABLED, + AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_DISABLED +} t_ab8500_codec_cr77_fadedis_ad1l; + +/* CR77 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr77_ad1lbgain_to_hfl; + +/* CR78 - 6 */ +typedef enum { + AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_ENABLED, + AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_DISABLED +} t_ab8500_codec_cr78_fadedis_ad2l; + +/* CR78 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr78_ad2lbgain_to_hfr; + +/* CR79 - 7 */ +typedef enum { + AB8500_CODEC_CR79_HSSINC1_SINC3_CHOOSEN, + AB8500_CODEC_CR79_HSSINC1_SINC1_CHOOSEN +} t_ab8500_codec_cr79_hssinc1; + +/* CR79 - 4 */ +typedef enum { + AB8500_CODEC_CR79_FADEDIS_HSL_ENABLED, + AB8500_CODEC_CR79_FADEDIS_HSL_DISABLED +} t_ab8500_codec_cr79_fadedis_hsl; + +/* CR79 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr79_hsldgain; + +/* CR80 - 4 */ +typedef enum { + AB8500_CODEC_CR80_FADEDIS_HSR_ENABLED, + AB8500_CODEC_CR80_FADEDIS_HSR_DISABLED +} t_ab8500_codec_cr80_fadedis_hsr; + +/* CR80 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr80_hsrdgain; + +/* CR81 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr81_stfir1gain; + +/* CR82 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr82_stfir2gain; + +/* CR83 - 2 */ +typedef enum { + AB8500_CODEC_CR83_ENANC_DISABLED, + AB8500_CODEC_CR83_ENANC_ENABLED +} t_ab8500_codec_cr83_enanc; + +/* CR83 - 1 */ +typedef enum { + AB8500_CODEC_CR83_ANCIIRINIT_NOT_STARTED, + AB8500_CODEC_CR83_ANCIIRINIT_STARTED +} t_ab8500_codec_cr83_anciirinit; + +/* CR83 - 0 */ +typedef enum { + AB8500_CODEC_CR83_ANCFIRUPDATE_RESETTED, + AB8500_CODEC_CR83_ANCFIRUPDATE_NOT_RESETTED +} t_ab8500_codec_cr83_ancfirupdate; + +/* CR84 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr84_ancinshift; + +/* CR85 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr85_ancfiroutshift; + +/* CR86 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr86_ancshiftout; + +/* CR87 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr87_ancfircoeff_msb; + +/* CR88 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr88_ancfircoeff_lsb; + +/* CR89 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr89_anciircoeff_msb; + +/* CR90 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr90_anciircoeff_lsb; + +/* CR91 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr91_ancwarpdel_msb; + +/* CR92 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr92_ancwarpdel_lsb; + +/* CR93 - Read Only */ +/* CR93 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr93_ancfirpeak_msb; + +/* CR94 - Read Only */ +/* CR94 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr94_ancfirpeak_lsb; + +/* CR95 - Read Only */ +/* CR95 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr95_anciirpeak_msb; + +/* CR96 - Read Only */ +/* CR96 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr96_anciirpeak_lsb; + +/* CR97 - 7 */ +typedef enum { + AB8500_CODEC_CR97_STFIR_SET_LAST_NOT_APPLIED, + AB8500_CODEC_CR97_STFIR_SET_LAST_APPLIED +} t_ab8500_codec_cr97_stfir_set; + +/* CR97 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr97_stfir_addr; + +/* CR98 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr98_stfir_coeff_msb; + +/* CR99 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr99_stfir_coeff_lsb; + +/* CR100 - 2 */ +typedef enum { + AB8500_CODEC_CR100_ENSTFIRS_DISABLED, + AB8500_CODEC_CR100_ENSTFIRS_ENABLED +} t_ab8500_codec_cr100_enstfirs; + +/* CR100 - 1 */ +typedef enum { + AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF0_DATA_RATE, + AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF1_DATA_RATE +} t_ab8500_codec_cr100_stfirstoif1; + +/* CR100 - 0 */ +typedef enum { + AB8500_CODEC_CR100_STFIR_BUSY_READY, + AB8500_CODEC_CR100_STFIR_BUSY_NOT_READY +} t_ab8500_codec_cr100_stfir_busy; + +/* CR101 - 7 */ +typedef enum { + AB8500_CODEC_CR101_PARLHF_INDEPENDENT, + AB8500_CODEC_CR101_PARLHF_BRIDGED +} t_ab8500_codec_cr101_parlhf; + +/* CR101 - 6 */ +typedef enum { + AB8500_CODEC_CR101_PARLVIB_INDEPENDENT, + AB8500_CODEC_CR101_PARLVIB_BRIDGED +} t_ab8500_codec_cr101_parlvib; + +/* CR101 - 3 */ +typedef enum { + AB8500_CODEC_CR101_CLASSD_VIBLSWAPEN_DISABLED, + AB8500_CODEC_CR101_CLASSD_VIBLSWAPEN_ENABLED +} t_ab8500_codec_cr101_classd_viblswapen; + +/* CR101 - 2 */ +typedef enum { + AB8500_CODEC_CR101_CLASSD_VIBRSWAPEN_DISABLED, + AB8500_CODEC_CR101_CLASSD_VIBRSWAPEN_ENABLED +} t_ab8500_codec_cr101_classd_vibrswapen; + +/* CR101 - 1 */ +typedef enum { + AB8500_CODEC_CR101_CLASSD_HFLSWAPEN_DISABLED, + AB8500_CODEC_CR101_CLASSD_HFLSWAPEN_ENABLED +} t_ab8500_codec_cr101_classd_hflswapen; + +/* CR101 - 0 */ +typedef enum { + AB8500_CODEC_CR101_CLASSD_HFRSWAPEN_DISABLED, + AB8500_CODEC_CR101_CLASSD_HFRSWAPEN_ENABLED +} t_ab8500_codec_cr101_classd_hfrswapen; + +/* CR102 - 7:4 */ +typedef enum { + AB8500_CODEC_CR102_CLASSD_FIRBYP_ALL_ENABLED = 0, + AB8500_CODEC_CR102_CLASSD_FIRBYP_HFL_BYPASSED = 1, + AB8500_CODEC_CR102_CLASSD_FIRBYP_HFR_BYPASSED = 2, + AB8500_CODEC_CR102_CLASSD_FIRBYP_VIBL_BYPASSED = 4, + AB8500_CODEC_CR102_CLASSD_FIRBYP_VIBR_BYPASSED = 8 +} t_ab8500_codec_cr102_classd_firbyp; + +/* CR102 - 3:0 */ +typedef enum { + AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_DISABLED = 0, + AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_HFL_HIGHVOL = 1, + AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_HFR_HIGHVOL = 2, + AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_VIBL_HIGHVOL = 4, + AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_VIBR_HIGHVOL = 8 +} t_ab8500_codec_cr102_classd_highvolen; + +/* CR103 - 7:4 */ +typedef t_uint8 t_ab8500_codec_cr103_classd_ditherhpgain; + +/* CR103 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr103_classd_ditherwgain; + +/* CR104 - 5:0 */ +/* In ab8500_codec.h */ + +/* CR105 - 7:0 */ +/* In ab8500_codec.h */ + +/* CR106 - 6:4 */ +/* In ab8500_codec.h */ + +/* CR106 - 2 */ +/* In ab8500_codec.h */ + +/* CR106 - 1 */ +/* In ab8500_codec.h */ + +/* CR106 - 0 */ +/* In ab8500_codec.h */ + +/* CR107 - 7:0 */ +/* In ab8500_codec.h */ + +/* CR108 - 7:0 */ +/* In ab8500_codec.h */ + +/* CR109 - Read Only */ +/* CR109 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr109_bfifosamples; + +typedef enum { + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT4, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT5, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT6, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT7, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT8, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_ZEROS, + AB8500_CODEC_CR31_TO_CR46_SLOT_IS_TRISTATE = 15, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED +} t_ab8500_codec_cr31_to_cr46_ad_data_allocation; + +typedef enum { + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT00, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT01, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT02, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT03, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT04, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT05, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT06, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT07, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT08, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT09, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT10, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT11, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT12, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT13, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT14, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT15, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT16, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT17, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT18, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT19, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT20, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT21, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT22, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT23, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT24, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT25, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT26, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT27, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT28, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT29, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT30, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT31, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT_UNDEFINED +} t_ab8500_codec_cr51_to_cr56_sltoda; + +/* CR104 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr104_bfifoint; + +/* CR105 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr105_bfifotx; + +/* CR106 - 6:4 */ +typedef enum { + AB8500_CODEC_CR106_BFIFOFSEXT_NO_EXTRA_CLK, + AB8500_CODEC_CR106_BFIFOFSEXT_1SLOT_EXTRA_CLK, + AB8500_CODEC_CR106_BFIFOFSEXT_2SLOT_EXTRA_CLK, + AB8500_CODEC_CR106_BFIFOFSEXT_3SLOT_EXTRA_CLK, + AB8500_CODEC_CR106_BFIFOFSEXT_4SLOT_EXTRA_CLK, + AB8500_CODEC_CR106_BFIFOFSEXT_5SLOT_EXTRA_CLK, + AB8500_CODEC_CR106_BFIFOFSEXT_6SLOT_EXTRA_CLK +} t_ab8500_codec_cr106_bfifofsext; + +/* CR106 - 2 */ +typedef enum { + AB8500_CODEC_CR106_BFIFOMSK_AD_DATA0_UNMASKED, + AB8500_CODEC_CR106_BFIFOMSK_AD_DATA0_MASKED +} t_ab8500_codec_cr106_bfifomsk; + +/* CR106 - 1 */ +typedef enum { + AB8500_CODEC_CR106_BFIFOMSTR_SLAVE_MODE, + AB8500_CODEC_CR106_BFIFOMSTR_MASTER_MODE +} t_ab8500_codec_cr106_bfifomstr; + +/* CR106 - 0 */ +typedef enum { + AB8500_CODEC_CR106_BFIFOSTRT_STOPPED, + AB8500_CODEC_CR106_BFIFOSTRT_RUNNING +} t_ab8500_codec_cr106_bfifostrt; + +/* CR107 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr107_bfifosampnr; + +/* CR108 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr108_bfifowakeup; + +/*configuration structure for AB8500 Codec*/ +typedef struct { + /* CR0 */ + t_ab8500_codec_cr0_powerup cr0_powerup; + t_ab8500_codec_cr0_enaana cr0_enaana; + + /* CR1 */ + t_ab8500_codec_cr1_swreset cr1_swreset; + + /* CR2 */ + t_ab8500_codec_cr2_enad1 cr2_enad1; + t_ab8500_codec_cr2_enad2 cr2_enad2; + t_ab8500_codec_cr2_enad3 cr2_enad3; + t_ab8500_codec_cr2_enad4 cr2_enad4; + t_ab8500_codec_cr2_enad5 cr2_enad5; + t_ab8500_codec_cr2_enad6 cr2_enad6; + + /* CR3 */ + t_ab8500_codec_cr3_enda1 cr3_enda1; + t_ab8500_codec_cr3_enda2 cr3_enda2; + t_ab8500_codec_cr3_enda3 cr3_enda3; + t_ab8500_codec_cr3_enda4 cr3_enda4; + t_ab8500_codec_cr3_enda5 cr3_enda5; + t_ab8500_codec_cr3_enda6 cr3_enda6; + + /* CR4 */ + t_ab8500_codec_cr4_lowpowhs cr4_lowpowhs; + t_ab8500_codec_cr4_lowpowdachs cr4_lowpowdachs; + t_ab8500_codec_cr4_lowpowear cr4_lowpowear; + t_ab8500_codec_cr4_ear_sel_cm cr4_ear_sel_cm; + t_ab8500_codec_cr4_hs_hp_dis cr4_hs_hp_dis; + t_ab8500_codec_cr4_ear_hp_dis cr4_ear_hp_dis; + + /* CR5 */ + t_ab8500_codec_cr5_enmic1 cr5_enmic1; + t_ab8500_codec_cr5_enmic2 cr5_enmic2; + t_ab8500_codec_cr5_enlinl cr5_enlinl; + t_ab8500_codec_cr5_enlinr cr5_enlinr; + t_ab8500_codec_cr5_mutmic1 cr5_mutmic1; + t_ab8500_codec_cr5_mutmic2 cr5_mutmic2; + t_ab8500_codec_cr5_mutlinl cr5_mutlinl; + t_ab8500_codec_cr5_mutlinr cr5_mutlinr; + + /* CR6 */ + t_ab8500_codec_cr6_endmic1 cr6_endmic1; + t_ab8500_codec_cr6_endmic2 cr6_endmic2; + t_ab8500_codec_cr6_endmic3 cr6_endmic3; + t_ab8500_codec_cr6_endmic4 cr6_endmic4; + t_ab8500_codec_cr6_endmic5 cr6_endmic5; + t_ab8500_codec_cr6_endmic6 cr6_endmic6; + + /* CR7 */ + t_ab8500_codec_cr7_mic1sel cr7_mic1sel; + t_ab8500_codec_cr7_linrsel cr7_linrsel; + t_ab8500_codec_cr7_endrvhsl cr7_endrvhsl; + t_ab8500_codec_cr7_endrvhsr cr7_endrvhsr; + t_ab8500_codec_cr7_enadcmic cr7_enadcmic; + t_ab8500_codec_cr7_enadclinl cr7_enadclinl; + t_ab8500_codec_cr7_enadclinr cr7_enadclinr; + + /* CR8 */ + t_ab8500_codec_cr8_cp_dis_pldwn cr8_cp_dis_pldwn; + t_ab8500_codec_cr8_enear cr8_enear; + t_ab8500_codec_cr8_enhsl cr8_enhsl; + t_ab8500_codec_cr8_enhsr cr8_enhsr; + t_ab8500_codec_cr8_enhfl cr8_enhfl; + t_ab8500_codec_cr8_enhfr cr8_enhfr; + t_ab8500_codec_cr8_envibl cr8_envibl; + t_ab8500_codec_cr8_envibr cr8_envibr; + + /* CR9 */ + t_ab8500_codec_cr9_endacear cr9_endacear; + t_ab8500_codec_cr9_endachsl cr9_endachsl; + t_ab8500_codec_cr9_endachsr cr9_endachsr; + t_ab8500_codec_cr9_endachfl cr9_endachfl; + t_ab8500_codec_cr9_endachfr cr9_endachfr; + t_ab8500_codec_cr9_endacvibl cr9_endacvibl; + t_ab8500_codec_cr9_endacvibr cr9_endacvibr; + + /* CR10 */ + t_ab8500_codec_cr10_muteear cr10_muteear; + t_ab8500_codec_cr10_mutehsl cr10_mutehsl; + t_ab8500_codec_cr10_mutehsr cr10_mutehsr; + t_ab8500_codec_cr10_mutehfl cr10_mutehfl; + t_ab8500_codec_cr10_mutehfr cr10_mutehfr; + t_ab8500_codec_cr10_mutevibl cr10_mutevibl; + t_ab8500_codec_cr10_mutevibr cr10_mutevibr; + + /* CR11 */ + t_ab8500_codec_cr11_earshortpwd cr11_earshortpwd; + t_ab8500_codec_cr11_earshortdis cr11_earshortdis; + t_ab8500_codec_cr11_hslshortdis cr11_hslshortdis; + t_ab8500_codec_cr11_hsrshortdis cr11_hsrshortdis; + t_ab8500_codec_cr11_hflshortdis cr11_hflshortdis; + t_ab8500_codec_cr11_hfrshortdis cr11_hfrshortdis; + t_ab8500_codec_cr11_viblshortdis cr11_viblshortdis; + t_ab8500_codec_cr11_vibrshortdis cr11_vibrshortdis; + + /* CR12 */ + t_ab8500_codec_cr12_encphs cr12_encphs; + t_ab8500_codec_cr12_hsautotime cr12_hsautotime; + t_ab8500_codec_cr12_hsautoensel cr12_hsautoensel; + t_ab8500_codec_cr12_hsautoen cr12_hsautoen; + + /* CR13 */ + t_ab8500_codec_cr13_envdet_hthresh cr13_envdet_hthresh; + t_ab8500_codec_cr13_envdet_lthresh cr13_envdet_lthresh; + + /* CR14 */ + t_ab8500_codec_cr14_smpslven cr14_smpslven; + t_ab8500_codec_cr14_envdetsmpsen cr14_envdetsmpsen; + t_ab8500_codec_cr14_cplven cr14_cplven; + t_ab8500_codec_cr14_envdetcpen cr14_envdetcpen; + t_ab8500_codec_cr14_envet_time cr14_envet_time; + + /* CR15 */ + t_ab8500_codec_cr15_pwmtovibl cr15_pwmtovibl; + t_ab8500_codec_cr15_pwmtovibr cr15_pwmtovibr; + t_ab8500_codec_cr15_pwmlctrl cr15_pwmlctrl; + t_ab8500_codec_cr15_pwmrctrl cr15_pwmrctrl; + t_ab8500_codec_cr15_pwmnlctrl cr15_pwmnlctrl; + t_ab8500_codec_cr15_pwmplctrl cr15_pwmplctrl; + t_ab8500_codec_cr15_pwmnrctrl cr15_pwmnrctrl; + t_ab8500_codec_cr15_pwmprctrl cr15_pwmprctrl; + + /* CR16 */ + t_ab8500_codec_cr16_pwmnlpol cr16_pwmnlpol; + t_ab8500_codec_cr16_pwmnldutycycle cr16_pwmnldutycycle; + + /* CR17 */ + t_ab8500_codec_cr17_pwmplpol cr17_pwmplpol; + t_ab8500_codec_cr17_pwmpldutycycle cr17_pwmpldutycycle; + + /* CR18 */ + t_ab8500_codec_cr18_pwmnrpol cr18_pwmnrpol; + t_ab8500_codec_cr18_pwmnrdutycycle cr18_pwmnrdutycycle; + + /* CR19 */ + t_ab8500_codec_cr19_pwmprpol cr19_pwmprpol; + t_ab8500_codec_cr19_pwmprdutycycle cr19_pwmprdutycycle; + + /* CR20 */ + t_ab8500_codec_cr20_en_se_mic1 cr20_en_se_mic1; + t_ab8500_codec_cr20_mic1_gain cr20_mic1_gain; + + /* CR21 */ + t_ab8500_codec_cr21_en_se_mic2 cr21_en_se_mic2; + t_ab8500_codec_cr21_mic2_gain cr21_mic2_gain; + + /* CR22 */ + t_ab8500_codec_cr22_hsl_gain cr22_hsl_gain; + t_ab8500_codec_cr22_linl_gain cr22_linl_gain; + + /* CR23 */ + t_ab8500_codec_cr23_hsr_gain cr23_hsr_gain; + t_ab8500_codec_cr23_linr_gain cr23_linr_gain; + + /* CR24 */ + t_ab8500_codec_cr24_lintohsl_gain cr24_lintohsl_gain; + + /* CR25 */ + t_ab8500_codec_cr25_lintohsr_gain cr25_lintohsr_gain; + + /* CR26 */ + t_ab8500_codec_cr26_ad1nh cr26_ad1nh; + t_ab8500_codec_cr26_ad2nh cr26_ad2nh; + t_ab8500_codec_cr26_ad3nh cr26_ad3nh; + t_ab8500_codec_cr26_ad4nh cr26_ad4nh; + t_ab8500_codec_cr26_ad1_voice cr26_ad1_voice; + t_ab8500_codec_cr26_ad2_voice cr26_ad2_voice; + t_ab8500_codec_cr26_ad3_voice cr26_ad3_voice; + t_ab8500_codec_cr26_ad4_voice cr26_ad4_voice; + + /* CR27 */ + t_ab8500_codec_cr27_en_mastgen cr27_en_mastgen; + t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr; + t_ab8500_codec_cr27_enfs_bitclk1 cr27_enfs_bitclk1; + t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr; + t_ab8500_codec_cr27_enfs_bitclk0 cr27_enfs_bitclk0; + + /* CR28 */ + t_ab8500_codec_cr28_fsync0p cr28_fsync0p; + t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p; + t_ab8500_codec_cr28_if0del cr28_if0del; + t_ab8500_codec_cr28_if0format cr28_if0format; + t_ab8500_codec_cr28_if0wl cr28_if0wl; + + /* CR29 */ + t_ab8500_codec_cr29_if0datoif1ad cr29_if0datoif1ad; + t_ab8500_codec_cr29_if0cktoif1ck cr29_if0cktoif1ck; + t_ab8500_codec_cr29_if1master cr29_if1master; + t_ab8500_codec_cr29_if1datoif0ad cr29_if1datoif0ad; + t_ab8500_codec_cr29_if1cktoif0ck cr29_if1cktoif0ck; + t_ab8500_codec_cr29_if0master cr29_if0master; + t_ab8500_codec_cr29_if0bfifoen cr29_if0bfifoen; + + /* CR30 */ + t_ab8500_codec_cr30_fsync1p cr30_fsync1p; + t_ab8500_codec_cr30_bitclk1p cr30_bitclk1p; + t_ab8500_codec_cr30_if1del cr30_if1del; + t_ab8500_codec_cr30_if1format cr30_if1format; + t_ab8500_codec_cr30_if1wl cr30_if1wl; + + /* CR31 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot1; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot0; + + /* CR32 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot3; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot2; + + /* CR33 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot5; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot4; + + /* CR34 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot7; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot6; + + /* CR35 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot9; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot8; + + /* CR36 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot11; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot10; + + /* CR37 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot13; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot12; + + /* CR38 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot15; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot14; + + /* CR39 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot17; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot16; + + /* CR40 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot19; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot18; + + /* CR41 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot21; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot20; + + /* CR42 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot23; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot22; + + /* CR43 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot25; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot24; + + /* CR44 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot27; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot26; + + /* CR45 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot29; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot28; + + /* CR46 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot31; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot30; + + /* CR47 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl7; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl6; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl5; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl4; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl3; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl2; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl1; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl0; + + /* CR48 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl15; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl14; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl13; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl12; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl11; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl10; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl9; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl8; + + /* CR49 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl23; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl22; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl21; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl20; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl19; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl18; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl17; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl16; + + /* CR50 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl31; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl30; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl29; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl28; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl27; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl26; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl25; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl24; + + /* CR51 */ + t_ab8500_codec_cr51_da12_voice cr51_da12_voice; + t_ab8500_codec_cr51_sldai1toslado1 cr51_sldai1toslado1; + t_ab8500_codec_cr51_to_cr56_sltoda cr51_sltoda1; + + /* CR52 */ + t_ab8500_codec_cr52_sldai2toslado2 cr52_sldai2toslado2; + t_ab8500_codec_cr51_to_cr56_sltoda cr52_sltoda2; + + /* CR53 */ + t_ab8500_codec_cr53_da34_voice cr53_da34_voice; + t_ab8500_codec_cr53_sldai3toslado3 cr53_sldai3toslado3; + t_ab8500_codec_cr51_to_cr56_sltoda cr53_sltoda3; + + /* CR54 */ + t_ab8500_codec_cr54_sldai4toslado4 cr54_sldai4toslado4; + t_ab8500_codec_cr51_to_cr56_sltoda cr54_sltoda4; + + /* CR55 */ + t_ab8500_codec_cr55_da56_voice cr55_da56_voice; + t_ab8500_codec_cr55_sldai5toslado5 cr55_sldai5toslado5; + t_ab8500_codec_cr51_to_cr56_sltoda cr55_sltoda5; + + /* CR56 */ + t_ab8500_codec_cr56_sldai6toslado7 cr56_sldai6toslado7; + t_ab8500_codec_cr51_to_cr56_sltoda cr56_sltoda6; + + /* CR57 */ + t_ab8500_codec_cr57_bfifull_msk cr57_bfifull_msk; + t_ab8500_codec_cr57_bfiempt_msk cr57_bfiempt_msk; + t_ab8500_codec_cr57_dachan_msk cr57_dachan_msk; + t_ab8500_codec_cr57_gain_msk cr57_gain_msk; + t_ab8500_codec_cr57_dspad_msk cr57_dspad_msk; + t_ab8500_codec_cr57_dspda_msk cr57_dspda_msk; + t_ab8500_codec_cr57_stfir_msk cr57_stfir_msk; + + /* CR58 */ + t_ab8500_codec_cr58_bfifull_ev cr58_bfifull_ev; + t_ab8500_codec_cr58_bfiempt_ev cr58_bfiempt_ev; + t_ab8500_codec_cr58_dachan_ev cr58_dachan_ev; + t_ab8500_codec_cr58_gain_ev cr58_gain_ev; + t_ab8500_codec_cr58_dspad_ev cr58_dspad_ev; + t_ab8500_codec_cr58_dspda_ev cr58_dspda_ev; + t_ab8500_codec_cr58_stfir_ev cr58_stfir_ev; + + /* CR59 */ + t_ab8500_codec_cr59_vssready_msk cr59_vssready_msk; + t_ab8500_codec_cr59_shrtvibl_msk cr59_shrtvibl_msk; + t_ab8500_codec_cr59_shrtvibr_msk cr59_shrtvibr_msk; + t_ab8500_codec_cr59_shrthfl_msk cr59_shrthfl_msk; + t_ab8500_codec_cr59_shrthfr_msk cr59_shrthfr_msk; + t_ab8500_codec_cr59_shrthsl_msk cr59_shrthsl_msk; + t_ab8500_codec_cr59_shrthsr_msk cr59_shrthsr_msk; + t_ab8500_codec_cr59_shrtear_msk cr59_shrtear_msk; + + /* CR60 */ + t_ab8500_codec_cr60_vssready_ev cr60_vssready_ev; + t_ab8500_codec_cr60_shrtvibl_ev cr60_shrtvibl_ev; + t_ab8500_codec_cr60_shrtvibr_ev cr60_shrtvibr_ev; + t_ab8500_codec_cr60_shrthfl_ev cr60_shrthfl_ev; + t_ab8500_codec_cr60_shrthfr_ev cr60_shrthfr_ev; + t_ab8500_codec_cr60_shrthsl_ev cr60_shrthsl_ev; + t_ab8500_codec_cr60_shrthsr_ev cr60_shrthsr_ev; + t_ab8500_codec_cr60_shrtear_ev cr60_shrtear_ev; + + /* CR61 */ + t_ab8500_codec_cr61_revision cr61_revision; + t_ab8500_codec_cr61_fade_speed cr61_fade_speed; + + /* CR62 */ + t_ab8500_codec_cr62_dmic1sinc3 cr62_dmic1sinc3; + t_ab8500_codec_cr62_dmic2sinc3 cr62_dmic2sinc3; + t_ab8500_codec_cr62_dmic3sinc3 cr62_dmic3sinc3; + t_ab8500_codec_cr62_dmic4sinc3 cr62_dmic4sinc3; + t_ab8500_codec_cr62_dmic5sinc3 cr62_dmic5sinc3; + t_ab8500_codec_cr62_dmic6sinc3 cr62_dmic6sinc3; + + /* CR63 */ + t_ab8500_codec_cr63_datohslen cr63_datohslen; + t_ab8500_codec_cr63_datohsren cr63_datohsren; + t_ab8500_codec_cr63_ad1sel cr63_ad1sel; + t_ab8500_codec_cr63_ad2sel cr63_ad2sel; + t_ab8500_codec_cr63_ad3sel cr63_ad3sel; + t_ab8500_codec_cr63_ad5sel cr63_ad5sel; + t_ab8500_codec_cr63_ad6sel cr63_ad6sel; + t_ab8500_codec_cr63_ancsel cr63_ancsel; + + /* CR64 */ + t_ab8500_codec_cr64_datohfren cr64_datohfren; + t_ab8500_codec_cr64_datohflen cr64_datohflen; + t_ab8500_codec_cr64_hfrsel cr64_hfrsel; + t_ab8500_codec_cr64_hflsel cr64_hflsel; + t_ab8500_codec_cr64_stfir1sel cr64_stfir1sel; + t_ab8500_codec_cr64_stfir2sel cr64_stfir2sel; + + /* CR65 */ + t_ab8500_codec_cr65_fadedis_ad1 cr65_fadedis_ad1; + t_ab8500_codec_cr65_ad1gain cr65_ad1gain; + + /* CR66 */ + t_ab8500_codec_cr66_fadedis_ad2 cr66_fadedis_ad2; + t_ab8500_codec_cr66_ad2gain cr66_ad2gain; + + /* CR67 */ + t_ab8500_codec_cr67_fadedis_ad3 cr67_fadedis_ad3; + t_ab8500_codec_cr67_ad3gain cr67_ad3gain; + + /* CR68 */ + t_ab8500_codec_cr68_fadedis_ad4 cr68_fadedis_ad4; + t_ab8500_codec_cr68_ad4gain cr68_ad4gain; + + /* CR69 */ + t_ab8500_codec_cr69_fadedis_ad5 cr69_fadedis_ad5; + t_ab8500_codec_cr69_ad5gain cr69_ad5gain; + + /* CR70 */ + t_ab8500_codec_cr70_fadedis_ad6 cr70_fadedis_ad6; + t_ab8500_codec_cr70_ad6gain cr70_ad6gain; + + /* CR71 */ + t_ab8500_codec_cr71_fadedis_da1 cr71_fadedis_da1; + t_ab8500_codec_cr71_da1gain cr71_da1gain; + + /* CR72 */ + t_ab8500_codec_cr72_fadedis_da2 cr72_fadedis_da2; + t_ab8500_codec_cr72_da2gain cr72_da2gain; + + /* CR73 */ + t_ab8500_codec_cr73_fadedis_da3 cr73_fadedis_da3; + t_ab8500_codec_cr73_da3gain cr73_da3gain; + + /* CR74 */ + t_ab8500_codec_cr74_fadedis_da4 cr74_fadedis_da4; + t_ab8500_codec_cr74_da4gain cr74_da4gain; + + /* CR75 */ + t_ab8500_codec_cr75_fadedis_da5 cr75_fadedis_da5; + t_ab8500_codec_cr75_da5gain cr75_da5gain; + + /* CR76 */ + t_ab8500_codec_cr76_fadedis_da6 cr76_fadedis_da6; + t_ab8500_codec_cr76_da6gain cr76_da6gain; + + /* CR77 */ + t_ab8500_codec_cr77_fadedis_ad1l cr77_fadedis_ad1l; + t_ab8500_codec_cr77_ad1lbgain_to_hfl cr77_ad1lbgain_to_hfl; + + /* CR78 */ + t_ab8500_codec_cr78_fadedis_ad2l cr78_fadedis_ad2l; + t_ab8500_codec_cr78_ad2lbgain_to_hfr cr78_ad2lbgain_to_hfr; + + /* CR79 */ + t_ab8500_codec_cr79_hssinc1 cr79_hssinc1; + t_ab8500_codec_cr79_fadedis_hsl cr79_fadedis_hsl; + t_ab8500_codec_cr79_hsldgain cr79_hsldgain; + + /* CR80 */ + t_ab8500_codec_cr80_fadedis_hsr cr80_fadedis_hsr; + t_ab8500_codec_cr80_hsrdgain cr80_hsrdgain; + + /* CR81 */ + t_ab8500_codec_cr81_stfir1gain cr81_stfir1gain; + + /* CR82 */ + t_ab8500_codec_cr82_stfir2gain cr82_stfir2gain; + + /* CR83 */ + t_ab8500_codec_cr83_enanc cr83_enanc; + t_ab8500_codec_cr83_anciirinit cr83_anciirinit; + t_ab8500_codec_cr83_ancfirupdate cr83_ancfirupdate; + + /* CR84 */ + t_ab8500_codec_cr84_ancinshift cr84_ancinshift; + + /* CR85 */ + t_ab8500_codec_cr85_ancfiroutshift cr85_ancfiroutshift; + + /* CR86 */ + t_ab8500_codec_cr86_ancshiftout cr86_ancshiftout; + + /* CR87 */ + t_ab8500_codec_cr87_ancfircoeff_msb cr87_ancfircoeff_msb; + + /* CR88 */ + t_ab8500_codec_cr88_ancfircoeff_lsb cr88_ancfircoeff_lsb; + + /* CR89 */ + t_ab8500_codec_cr89_anciircoeff_msb cr89_anciircoeff_msb; + + /* CR90 */ + t_ab8500_codec_cr90_anciircoeff_lsb cr90_anciircoeff_lsb; + + /* CR91 */ + t_ab8500_codec_cr91_ancwarpdel_msb cr91_ancwarpdel_msb; + + /* CR92 */ + t_ab8500_codec_cr92_ancwarpdel_lsb cr92_ancwarpdel_lsb; + + /* CR93 */ + t_ab8500_codec_cr93_ancfirpeak_msb cr93_ancfirpeak_msb; + + /* CR94 */ + t_ab8500_codec_cr94_ancfirpeak_lsb cr94_ancfirpeak_lsb; + + /* CR95 */ + t_ab8500_codec_cr95_anciirpeak_msb cr95_anciirpeak_msb; + + /* CR96 */ + t_ab8500_codec_cr96_anciirpeak_lsb cr96_anciirpeak_lsb; + + /* CR97 */ + t_ab8500_codec_cr97_stfir_set cr97_stfir_set; + t_ab8500_codec_cr97_stfir_addr cr97_stfir_addr; + + /* CR98 */ + t_ab8500_codec_cr98_stfir_coeff_msb cr98_stfir_coeff_msb; + + /* CR99 */ + t_ab8500_codec_cr99_stfir_coeff_lsb cr99_stfir_coeff_lsb; + + /* CR100 */ + t_ab8500_codec_cr100_enstfirs cr100_enstfirs; + t_ab8500_codec_cr100_stfirstoif1 cr100_stfirstoif1; + t_ab8500_codec_cr100_stfir_busy cr100_stfir_busy; + + /* CR101 */ + t_ab8500_codec_cr101_parlhf cr101_parlhf; + t_ab8500_codec_cr101_parlvib cr101_parlvib; + t_ab8500_codec_cr101_classd_viblswapen cr101_classd_viblswapen; + t_ab8500_codec_cr101_classd_vibrswapen cr101_classd_vibrswapen; + t_ab8500_codec_cr101_classd_hflswapen cr101_classd_hflswapen; + t_ab8500_codec_cr101_classd_hfrswapen cr101_classd_hfrswapen; + + /* CR102 */ + t_ab8500_codec_cr102_classd_firbyp cr102_classd_firbyp; + t_ab8500_codec_cr102_classd_highvolen cr102_classd_highvolen; + + /* CR103 */ + t_ab8500_codec_cr103_classd_ditherhpgain cr103_classd_ditherhpgain; + t_ab8500_codec_cr103_classd_ditherwgain cr103_classd_ditherwgain; + + /* CR104 */ + t_ab8500_codec_cr104_bfifoint cr104_bfifoint; + + /* CR105 */ + t_ab8500_codec_cr105_bfifotx cr105_bfifotx; + + /* CR106 */ + t_ab8500_codec_cr106_bfifofsext cr106_bfifofsext; + t_ab8500_codec_cr106_bfifomsk cr106_bfifomsk; + t_ab8500_codec_cr106_bfifomstr cr106_bfifomstr; + t_ab8500_codec_cr106_bfifostrt cr106_bfifostrt; + + /* CR107 */ + t_ab8500_codec_cr107_bfifosampnr cr107_bfifosampnr; + + /* CR108 */ + t_ab8500_codec_cr108_bfifowakeup cr108_bfifowakeup; + + /* CR109 */ + t_ab8500_codec_cr109_bfifosamples cr109_bfifosamples; + +} t_ab8500_codec_configuration; + +typedef enum { + AB8500_CODEC_DIRECTION_IN, + AB8500_CODEC_DIRECTION_OUT, + AB8500_CODEC_DIRECTION_INOUT +} t_ab8500_codec_direction; + +typedef enum { + AB8500_CODEC_MODE_HIFI, + AB8500_CODEC_MODE_VOICE, + AB8500_CODEC_MODE_MANUAL_SETTING +} t_ab8500_codec_mode; + +typedef enum { + AB8500_CODEC_AUDIO_INTERFACE_0, + AB8500_CODEC_AUDIO_INTERFACE_1 +} t_ab8500_codec_audio_interface; + +typedef enum { + AB8500_CODEC_SRC_LINEIN, + AB8500_CODEC_SRC_MICROPHONE_1A, + AB8500_CODEC_SRC_MICROPHONE_1B, + AB8500_CODEC_SRC_MICROPHONE_2, + AB8500_CODEC_SRC_D_MICROPHONE_1, + AB8500_CODEC_SRC_D_MICROPHONE_2, + AB8500_CODEC_SRC_D_MICROPHONE_3, + AB8500_CODEC_SRC_D_MICROPHONE_4, + AB8500_CODEC_SRC_D_MICROPHONE_5, + AB8500_CODEC_SRC_D_MICROPHONE_6, + AB8500_CODEC_SRC_FM_RX, + AB8500_CODEC_SRC_ALL +} t_ab8500_codec_src; + +typedef enum { + AB8500_CODEC_DEST_HEADSET, + AB8500_CODEC_DEST_EARPIECE, + AB8500_CODEC_DEST_HANDSFREE, + AB8500_CODEC_DEST_VIBRATOR_L, + AB8500_CODEC_DEST_VIBRATOR_R, + AB8500_CODEC_DEST_ALL +} t_ab8500_codec_dest; + +typedef struct { + t_uint8 slave_address_of_ab8500_codec; + t_ab8500_codec_direction ab8500_codec_direction; + t_ab8500_codec_mode ab8500_codec_mode_in; + t_ab8500_codec_mode ab8500_codec_mode_out; + t_ab8500_codec_audio_interface audio_interface; + t_ab8500_codec_src ab8500_codec_src; + t_ab8500_codec_dest ab8500_codec_dest; + t_uint8 in_left_volume; + t_uint8 in_right_volume; + t_uint8 out_left_volume; + t_uint8 out_right_volume; + + t_ab8500_codec_configuration ab8500_codec_configuration; +} t_ab8500_codec_system_context; +#endif /* _AB8500_CODECP_H_ */ + +/* End of file AB8500_CODECP.h */ diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h b/arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h new file mode 100644 index 00000000000..866cd0c80f1 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h @@ -0,0 +1,3037 @@ +/*****************************************************************************/ +/** +* © ST-Ericsson, 2009 - All rights reserved +* Reproduction and Communication of this document is strictly prohibited +* unless specifically authorized in writing by ST-Ericsson +* +* \brief Private Header file for AB8500 CODEC +* \author ST-Ericsson +*/ +/*****************************************************************************/ + +#ifndef _AB8500_CODECP_V1_0_H_ +#define _AB8500_CODECP_V1_0_H_ + +/*---------------------------------------------------------------------------- + * Includes + *---------------------------------------------------------------------------*/ +#include "hcl_defs.h" + +#define AB8500_CODEC_HCL_VERSION_ID 3 +#define AB8500_CODEC_HCL_MAJOR_ID 0 +#define AB8500_CODEC_HCL_MINOR_ID 0 + +#define AB8500_CODEC_MASK_ONE_BIT 0x1UL +#define AB8500_CODEC_MASK_TWO_BITS 0x3UL +#define AB8500_CODEC_MASK_THREE_BITS 0x7UL +#define AB8500_CODEC_MASK_FOUR_BITS 0xFUL +#define AB8500_CODEC_MASK_FIVE_BITS 0x1FUL +#define AB8500_CODEC_MASK_SIX_BITS 0x3FUL +#define AB8500_CODEC_MASK_SEVEN_BITS 0x7FUL +#define AB8500_CODEC_MASK_EIGHT_BITS 0xFFUL + +#define AB8500_CODEC_WRITE_BITS(reg, val, bit_nb, pos) (reg) = ((t_uint8) ((((reg) & (~(bit_nb << pos))) | (((val) & bit_nb) << pos)))) + +#define AB8500_CODEC_BLOCK 0x0D + +#define AB8500_CODEC_MASK_TWO_MS_BITS 0xC0UL +#define AB8500_CODEC_MASK_SIX_LS_BITS 0x3FUL + +/* Genepi AudioCodec Control Registers */ + +#define AB8500_CODEC_CR0 0x00 +#define AB8500_CODEC_CR1 0x01 +#define AB8500_CODEC_CR2 0x02 +#define AB8500_CODEC_CR3 0x03 +#define AB8500_CODEC_CR4 0x04 +#define AB8500_CODEC_CR5 0x05 +#define AB8500_CODEC_CR6 0x06 +#define AB8500_CODEC_CR7 0x07 +#define AB8500_CODEC_CR8 0x08 +#define AB8500_CODEC_CR9 0x09 +#define AB8500_CODEC_CR10 0x0A +#define AB8500_CODEC_CR11 0x0B +#define AB8500_CODEC_CR12 0x0C +#define AB8500_CODEC_CR13 0x0D +#define AB8500_CODEC_CR14 0x0E +#define AB8500_CODEC_CR15 0x0F +#define AB8500_CODEC_CR16 0x10 +#define AB8500_CODEC_CR17 0x11 +#define AB8500_CODEC_CR18 0x12 +#define AB8500_CODEC_CR19 0x13 +#define AB8500_CODEC_CR20 0x14 +#define AB8500_CODEC_CR21 0x15 +#define AB8500_CODEC_CR22 0x16 +#define AB8500_CODEC_CR23 0x17 +#define AB8500_CODEC_CR24 0x18 +#define AB8500_CODEC_CR25 0x19 +#define AB8500_CODEC_CR26 0x1A +#define AB8500_CODEC_CR27 0x1B +#define AB8500_CODEC_CR28 0x1C +#define AB8500_CODEC_CR29 0x1D +#define AB8500_CODEC_CR30 0x1E +#define AB8500_CODEC_CR31 0x1F +#define AB8500_CODEC_CR32 0x20 +#define AB8500_CODEC_CR33 0x21 +#define AB8500_CODEC_CR34 0x22 +#define AB8500_CODEC_CR35 0x23 +#define AB8500_CODEC_CR36 0x24 +#define AB8500_CODEC_CR37 0x25 +#define AB8500_CODEC_CR38 0x26 +#define AB8500_CODEC_CR39 0x27 +#define AB8500_CODEC_CR40 0x28 +#define AB8500_CODEC_CR41 0x29 +#define AB8500_CODEC_CR42 0x2A +#define AB8500_CODEC_CR43 0x2B +#define AB8500_CODEC_CR44 0x2C +#define AB8500_CODEC_CR45 0x2D +#define AB8500_CODEC_CR46 0x2E +#define AB8500_CODEC_CR47 0x2F +#define AB8500_CODEC_CR48 0x30 +#define AB8500_CODEC_CR49 0x31 +#define AB8500_CODEC_CR50 0x32 +#define AB8500_CODEC_CR51 0x33 +#define AB8500_CODEC_CR52 0x34 +#define AB8500_CODEC_CR53 0x35 +#define AB8500_CODEC_CR54 0x36 +#define AB8500_CODEC_CR55 0x37 +#define AB8500_CODEC_CR56 0x38 +#define AB8500_CODEC_CR57 0x39 +#define AB8500_CODEC_CR58 0x3A +#define AB8500_CODEC_CR59 0x3B +#define AB8500_CODEC_CR60 0x3C +#define AB8500_CODEC_CR61 0x3D +#define AB8500_CODEC_CR62 0x3E +#define AB8500_CODEC_CR63 0x3F +#define AB8500_CODEC_CR64 0x40 +#define AB8500_CODEC_CR65 0x41 +#define AB8500_CODEC_CR66 0x42 +#define AB8500_CODEC_CR67 0x43 +#define AB8500_CODEC_CR68 0x44 +#define AB8500_CODEC_CR69 0x45 +#define AB8500_CODEC_CR70 0x46 +#define AB8500_CODEC_CR71 0x47 +#define AB8500_CODEC_CR72 0x48 +#define AB8500_CODEC_CR73 0x49 +#define AB8500_CODEC_CR74 0x4A +#define AB8500_CODEC_CR75 0x4B +#define AB8500_CODEC_CR76 0x4C +#define AB8500_CODEC_CR77 0x4D +#define AB8500_CODEC_CR78 0x4E +#define AB8500_CODEC_CR79 0x4F +#define AB8500_CODEC_CR80 0x50 +#define AB8500_CODEC_CR81 0x51 +#define AB8500_CODEC_CR82 0x52 +#define AB8500_CODEC_CR83 0x53 +#define AB8500_CODEC_CR84 0x54 +#define AB8500_CODEC_CR85 0x55 +#define AB8500_CODEC_CR86 0x56 +#define AB8500_CODEC_CR87 0x57 +#define AB8500_CODEC_CR88 0x58 +#define AB8500_CODEC_CR89 0x59 +#define AB8500_CODEC_CR90 0x5A +#define AB8500_CODEC_CR91 0x5B +#define AB8500_CODEC_CR92 0x5C +#define AB8500_CODEC_CR93 0x5D +#define AB8500_CODEC_CR94 0x5E +#define AB8500_CODEC_CR95 0x5F +#define AB8500_CODEC_CR96 0x60 +#define AB8500_CODEC_CR97 0x61 +#define AB8500_CODEC_CR98 0x62 +#define AB8500_CODEC_CR99 0x63 +#define AB8500_CODEC_CR100 0x64 +#define AB8500_CODEC_CR101 0x65 +#define AB8500_CODEC_CR102 0x66 +#define AB8500_CODEC_CR103 0x67 +#define AB8500_CODEC_CR104 0x68 +#define AB8500_CODEC_CR105 0x69 +#define AB8500_CODEC_CR106 0x6A +#define AB8500_CODEC_CR107 0x6B +#define AB8500_CODEC_CR108 0x6C +#define AB8500_CODEC_CR109 0x6D +#define AB8500_CODEC_CR110 0x6E +#define AB8500_CODEC_CR111 0x6F + +/* CR0-CR0x0000 */ +#define AB8500_CODEC_CR0_POWERUP 7 +#define AB8500_CODEC_CR0_ENAANA 3 + +/* CR1-CR0x0001 */ +#define AB8500_CODEC_CR1_SWRESET 7 + +/* CR2-CR0x0002 */ +#define AB8500_CODEC_CR2_ENAD1 7 +#define AB8500_CODEC_CR2_ENAD2 6 +#define AB8500_CODEC_CR2_ENAD3 5 +#define AB8500_CODEC_CR2_ENAD4 4 +#define AB8500_CODEC_CR2_ENAD5 3 +#define AB8500_CODEC_CR2_ENAD6 2 + +/* CR3-CR0x0003 */ +#define AB8500_CODEC_CR3_ENDA1 7 +#define AB8500_CODEC_CR3_ENDA2 6 +#define AB8500_CODEC_CR3_ENDA3 5 +#define AB8500_CODEC_CR3_ENDA4 4 +#define AB8500_CODEC_CR3_ENDA5 3 +#define AB8500_CODEC_CR3_ENDA6 2 + +/* CR4-CR0x0004 */ +#define AB8500_CODEC_CR4_LOWPOWHS 7 +#define AB8500_CODEC_CR4_LOWPOWDACHS 5 +#define AB8500_CODEC_CR4_LOWPOWEAR 4 +#define AB8500_CODEC_CR4_EAR_SEL_CM 2 +#define AB8500_CODEC_CR4_HS_HP_EN 1 + +/* CR5-CR0x0005 */ +#define AB8500_CODEC_CR5_ENMIC1 7 +#define AB8500_CODEC_CR5_ENMIC2 6 +#define AB8500_CODEC_CR5_ENLINL 5 +#define AB8500_CODEC_CR5_ENLINR 4 +#define AB8500_CODEC_CR5_MUTMIC1 3 +#define AB8500_CODEC_CR5_MUTMIC2 2 +#define AB8500_CODEC_CR5_MUTELINL 1 +#define AB8500_CODEC_CR5_MUTELINR 0 + +/* CR6-CR0x0006 */ +#define AB8500_CODEC_CR6_ENDMIC1 7 +#define AB8500_CODEC_CR6_ENDMIC2 6 +#define AB8500_CODEC_CR6_ENDMIC3 5 +#define AB8500_CODEC_CR6_ENDMIC4 4 +#define AB8500_CODEC_CR6_ENDMIC5 3 +#define AB8500_CODEC_CR6_ENDMIC6 2 + +/* CR7-CR0x0007 */ +#define AB8500_CODEC_CR7_MIC1SEL 7 +#define AB8500_CODEC_CR7_LINRSEL 6 +#define AB8500_CODEC_CR7_ENDRVHSL 5 +#define AB8500_CODEC_CR7_ENDRVHSR 4 +#define AB8500_CODEC_CR7_ENADCMIC 2 +#define AB8500_CODEC_CR7_ENADCLINL 1 +#define AB8500_CODEC_CR7_ENADCLINR 0 + +/* CR8-CR0x0008 */ +#define AB8500_CODEC_CR8_CP_DIS_PLDWN 7 +#define AB8500_CODEC_CR8_ENEAR 6 +#define AB8500_CODEC_CR8_ENHSL 5 +#define AB8500_CODEC_CR8_ENHSR 4 +#define AB8500_CODEC_CR8_ENHFL 3 +#define AB8500_CODEC_CR8_ENHFR 2 +#define AB8500_CODEC_CR8_ENVIBL 1 +#define AB8500_CODEC_CR8_ENVIBR 0 + +/* CR9-CR0x0009 */ +#define AB8500_CODEC_CR9_ENADACEAR 6 +#define AB8500_CODEC_CR9_ENADACHSL 5 +#define AB8500_CODEC_CR9_ENADACHSR 4 +#define AB8500_CODEC_CR9_ENADACHFL 3 +#define AB8500_CODEC_CR9_ENADACHFR 2 +#define AB8500_CODEC_CR9_ENADACVIBL 1 +#define AB8500_CODEC_CR9_ENADACVIBR 0 + +/* CR10-CR0x000A */ +#define AB8500_CODEC_CR10_MUTEEAR 6 +#define AB8500_CODEC_CR10_MUTEHSL 5 +#define AB8500_CODEC_CR10_MUTEHSR 4 + +/* CR11-CR0x000B */ +#define AB8500_CODEC_CR11_ENSHORTPWD 7 +#define AB8500_CODEC_CR11_EARSHORTDIS 6 +#define AB8500_CODEC_CR11_HSSHORTDIS 5 +#define AB8500_CODEC_CR11_HSPULLDEN 4 +#define AB8500_CODEC_CR11_HSOSCEN 2 +#define AB8500_CODEC_CR11_HSFADEN 1 +#define AB8500_CODEC_CR11_HSZCDDIS 0 + +/* CR12-CR0x000C */ +#define AB8500_CODEC_CR12_ENCPHS 7 +#define AB8500_CODEC_CR12_HSAUTOEN 0 + +/* CR13-CR0x000D */ +#define AB8500_CODEC_CR13_ENVDET_HTHRESH 4 +#define AB8500_CODEC_CR13_ENVDET_LTHRESH 0 + +/* CR14-CR0x000E */ +#define AB8500_CODEC_CR14_SMPSLVEN 7 +#define AB8500_CODEC_CR14_ENVDETSMPSEN 6 +#define AB8500_CODEC_CR14_CPLVEN 5 +#define AB8500_CODEC_CR14_ENVDETCPEN 4 +#define AB8500_CODEC_CR14_ENVDET_TIME 0 + +/* CR15-CR0x000F */ +#define AB8500_CODEC_CR15_PWMTOVIBL 7 +#define AB8500_CODEC_CR15_PWMTOVIBR 6 +#define AB8500_CODEC_CR15_PWMLCTRL 5 +#define AB8500_CODEC_CR15_PWMRCTRL 4 +#define AB8500_CODEC_CR15_PWMNLCTRL 3 +#define AB8500_CODEC_CR15_PWMPLCTRL 2 +#define AB8500_CODEC_CR15_PWMNRCTRL 1 +#define AB8500_CODEC_CR15_PWMPRCTRL 0 + +/* CR16-CR0x0010 */ +#define AB8500_CODEC_CR16_PWMNLPOL 7 +#define AB8500_CODEC_CR16_PWMNLDUTYCYCLE 0 + +/* CR17-CR0x0011 */ +#define AB8500_CODEC_CR17_PWMPLPOL 7 +#define AB8500_CODEC_CR17_PWMLPDUTYCYCLE 0 + +/* CR18-CR0x0012 */ +#define AB8500_CODEC_CR18_PWMNRPOL 7 +#define AB8500_CODEC_CR18_PWMNRDUTYCYCLE 0 + +/* CR19-CR0x0013 */ +#define AB8500_CODEC_CR19_PWMPRPOL 7 +#define AB8500_CODEC_CR19_PWMRPDUTYCYCLE 0 + +/* CR20-CR0x0014 */ +#define AB8500_CODEC_CR20_EN_SE_MIC1 7 +#define AB8500_CODEC_CR20_LOW_POW_MIC1 6 +#define AB8500_CODEC_CR20_MIC1_GAIN 0 + +/* CR21-CR0x0015 */ +#define AB8500_CODEC_CR21_EN_SE_MIC2 7 +#define AB8500_CODEC_CR21_LOW_POW_MIC2 6 +#define AB8500_CODEC_CR21_MIC2_GAIN 0 + +/* CR22-CR0x0016 */ +#define AB8500_CODEC_CR22_HSL_GAIN 4 +#define AB8500_CODEC_CR22_HSR_GAIN 0 + +/* CR23-CR0x0017 */ +#define AB8500_CODEC_CR23_LINL_GAIN 4 +#define AB8500_CODEC_CR23_LINR_GAIN 0 + +/* CR24-CR0x0018 */ +#define AB8500_CODEC_CR24_LINTOHSL_GAIN 0 + +/* CR25-CR0x0019 */ +#define AB8500_CODEC_CR25_LINTOHSR_GAIN 0 + +/* CR26-CR0x001A */ +#define AB8500_CODEC_CR26_AD1NH 7 +#define AB8500_CODEC_CR26_AD2NH 6 +#define AB8500_CODEC_CR26_AD3NH 5 +#define AB8500_CODEC_CR26_AD4NH 4 +#define AB8500_CODEC_CR26_AD1_VOICE 3 +#define AB8500_CODEC_CR26_AD2_VOICE 2 +#define AB8500_CODEC_CR26_AD3_VOICE 1 +#define AB8500_CODEC_CR26_AD4_VOICE 0 + +/* CR27-CR0x001B */ +#define AB8500_CODEC_CR27_EN_MASTGEN 7 +#define AB8500_CODEC_CR27_IF1_BITCLK_OSR 5 +#define AB8500_CODEC_CR27_ENFS_BITCLK1 4 +#define AB8500_CODEC_CR27_IF0_BITCLK_OSR 1 +#define AB8500_CODEC_CR27_ENFS_BITCLK0 0 + +/* CR28-CR0x001C */ +#define AB8500_CODEC_CR28_FSYNC0P 6 +#define AB8500_CODEC_CR28_BITCLK0P 5 +#define AB8500_CODEC_CR28_IF0DEL 4 +#define AB8500_CODEC_CR28_IF0FORMAT 2 +#define AB8500_CODEC_CR28_IF0WL 0 + +/* CR29-CR0x001D */ +#define AB8500_CODEC_CR29_IF0DATOIF1AD 7 +#define AB8500_CODEC_CR29_IF0CKTOIF1CK 6 +#define AB8500_CODEC_CR29_IF1MASTER 5 +#define AB8500_CODEC_CR29_IF1DATOIF0AD 3 +#define AB8500_CODEC_CR29_IF1CKTOIF0CK 2 +#define AB8500_CODEC_CR29_IF0MASTER 1 +#define AB8500_CODEC_CR29_IF0BFIFOEN 0 + +/* CR30-CR0x001E */ +#define AB8500_CODEC_CR30_FSYNC1P 6 +#define AB8500_CODEC_CR30_BITCLK1P 5 +#define AB8500_CODEC_CR30_IF1DEL 4 +#define AB8500_CODEC_CR30_IF1FORMAT 2 +#define AB8500_CODEC_CR30_IF1WL 0 + +/* CR31-CR0x001F */ +#define AB8500_CODEC_CR31_ADOTOSLOT1 4 +#define AB8500_CODEC_CR31_ADOTOSLOT0 0 + +/* CR32-CR0x0020 */ +#define AB8500_CODEC_CR32_ADOTOSLOT3 4 +#define AB8500_CODEC_CR32_ADOTOSLOT2 0 + +/* CR33-CR0x0021 */ +#define AB8500_CODEC_CR33_ADOTOSLOT5 4 +#define AB8500_CODEC_CR33_ADOTOSLOT4 0 + +/* CR34-CR0x0022 */ +#define AB8500_CODEC_CR34_ADOTOSLOT7 4 +#define AB8500_CODEC_CR34_ADOTOSLOT6 0 + +/* CR35-CR0x0023 */ +#define AB8500_CODEC_CR35_ADOTOSLOT9 4 +#define AB8500_CODEC_CR35_ADOTOSLOT8 0 + +/* CR36-CR0x0024 */ +#define AB8500_CODEC_CR36_ADOTOSLOT11 4 +#define AB8500_CODEC_CR36_ADOTOSLOT10 0 + +/* CR37-CR0x0025 */ +#define AB8500_CODEC_CR37_ADOTOSLOT13 4 +#define AB8500_CODEC_CR37_ADOTOSLOT12 0 + +/* CR38-CR0x0026 */ +#define AB8500_CODEC_CR38_ADOTOSLOT15 4 +#define AB8500_CODEC_CR38_ADOTOSLOT14 0 + +/* CR39-CR0x0027 */ +#define AB8500_CODEC_CR39_ADOTOSLOT17 4 +#define AB8500_CODEC_CR39_ADOTOSLOT16 0 + +/* CR40-CR0x0028 */ +#define AB8500_CODEC_CR40_ADOTOSLOT19 4 +#define AB8500_CODEC_CR40_ADOTOSLOT18 0 + +/* CR41-CR0x0029 */ +#define AB8500_CODEC_CR41_ADOTOSLOT21 4 +#define AB8500_CODEC_CR41_ADOTOSLOT20 0 + +/* CR42-CR0x002A */ +#define AB8500_CODEC_CR42_ADOTOSLOT23 4 +#define AB8500_CODEC_CR42_ADOTOSLOT22 0 + +/* CR43-CR0x002B */ +#define AB8500_CODEC_CR43_ADOTOSLOT25 4 +#define AB8500_CODEC_CR43_ADOTOSLOT24 0 + +/* CR44-CR0x002C */ +#define AB8500_CODEC_CR44_ADOTOSLOT27 4 +#define AB8500_CODEC_CR44_ADOTOSLOT26 0 + +/* CR45-CR0x002D */ +#define AB8500_CODEC_CR45_ADOTOSLOT29 4 +#define AB8500_CODEC_CR45_ADOTOSLOT28 0 + +/* CR46-CR0x002E */ +#define AB8500_CODEC_CR46_ADOTOSLOT31 4 +#define AB8500_CODEC_CR46_ADOTOSLOT30 0 + +/* CR47-CR0x002F */ +#define AB8500_CODEC_CR47_HIZ_SL7 7 +#define AB8500_CODEC_CR47_HIZ_SL6 6 +#define AB8500_CODEC_CR47_HIZ_SL5 5 +#define AB8500_CODEC_CR47_HIZ_SL4 4 +#define AB8500_CODEC_CR47_HIZ_SL3 3 +#define AB8500_CODEC_CR47_HIZ_SL2 2 +#define AB8500_CODEC_CR47_HIZ_SL1 1 +#define AB8500_CODEC_CR47_HIZ_SL0 0 + +/* CR48-CR0x0030 */ +#define AB8500_CODEC_CR48_HIZ_SL15 7 +#define AB8500_CODEC_CR48_HIZ_SL14 6 +#define AB8500_CODEC_CR48_HIZ_SL13 5 +#define AB8500_CODEC_CR48_HIZ_SL12 4 +#define AB8500_CODEC_CR48_HIZ_SL11 3 +#define AB8500_CODEC_CR48_HIZ_SL10 2 +#define AB8500_CODEC_CR48_HIZ_SL9 1 +#define AB8500_CODEC_CR48_HIZ_SL8 0 + +/* CR49-CR0x0031 */ +#define AB8500_CODEC_CR49_HIZ_SL23 7 +#define AB8500_CODEC_CR49_HIZ_SL22 6 +#define AB8500_CODEC_CR49_HIZ_SL21 5 +#define AB8500_CODEC_CR49_HIZ_SL20 4 +#define AB8500_CODEC_CR49_HIZ_SL19 3 +#define AB8500_CODEC_CR49_HIZ_SL18 2 +#define AB8500_CODEC_CR49_HIZ_SL17 1 +#define AB8500_CODEC_CR49_HIZ_SL16 0 + +/* CR50-CR0x0032 */ +#define AB8500_CODEC_CR50_HIZ_SL31 7 +#define AB8500_CODEC_CR50_HIZ_SL30 6 +#define AB8500_CODEC_CR50_HIZ_SL29 5 +#define AB8500_CODEC_CR50_HIZ_SL28 4 +#define AB8500_CODEC_CR50_HIZ_SL27 3 +#define AB8500_CODEC_CR50_HIZ_SL26 2 +#define AB8500_CODEC_CR50_HIZ_SL25 1 +#define AB8500_CODEC_CR50_HIZ_SL24 0 + +/* CR51-CR0x0033 */ +#define AB8500_CODEC_CR51_DA12_VOICE 7 +#define AB8500_CODEC_CR51_SWAP_DA12_34 6 +#define AB8500_CODEC_CR51_SLDAI7TOSLADO1 5 +#define AB8500_CODEC_CR51_SLTODA1 0 + +/* CR52-CR0x0034 */ +#define AB8500_CODEC_CR52_SLDAI8TOSLADO2 5 +#define AB8500_CODEC_CR52_SLTODA2 0 + +/* CR53-CR0x0035 */ +#define AB8500_CODEC_CR53_DA34_VOICE 7 +#define AB8500_CODEC_CR53_SLDAI7TOSLADO3 5 +#define AB8500_CODEC_CR53_SLTODA3 0 + +/* CR54-CR0x0036 */ +#define AB8500_CODEC_CR54_SLDAI8TOSLADO4 5 +#define AB8500_CODEC_CR54_SLTODA4 0 + +/* CR55-CR0x0037 */ +#define AB8500_CODEC_CR55_DA56_VOICE 7 +#define AB8500_CODEC_CR55_SLDAI7TOSLADO5 5 +#define AB8500_CODEC_CR55_SLTODA5 0 + +/* CR56-CR0x0038 */ +#define AB8500_CODEC_CR56_SLDAI8TOSLADO6 5 +#define AB8500_CODEC_CR56_SLTODA6 0 + +/* CR57-CR0x0039 */ +#define AB8500_CODEC_CR57_SLDAI8TOSLADO7 5 +#define AB8500_CODEC_CR57_SLTODA7 0 + +/* CR58-CR0x003A */ +#define AB8500_CODEC_CR58_SLDAI7TOSLADO8 5 +#define AB8500_CODEC_CR58_SLTODA8 0 + +/* CR59-CR0x003B */ +#define AB8500_CODEC_CR59_PARLHF 7 +#define AB8500_CODEC_CR59_PARLVIB 6 +#define AB8500_CODEC_CR59_CLASSDVIB1SWAPEN 3 +#define AB8500_CODEC_CR59_CLASSDVIB2SWAPEN 2 +#define AB8500_CODEC_CR59_CLASSDHFLSWAPEN 1 +#define AB8500_CODEC_CR59_CLASSDHFRSWAPEN 0 + +/* CR60-CR0x003C */ +#define AB8500_CODEC_CR60_CLASSD_FIR_BYP 4 +#define AB8500_CODEC_CR60_CLASSD_HIGHVOL_EN 0 + +/* CR61-CR0x003D */ +#define AB8500_CODEC_CR61_CLASSD_DITH_HPGAIN 4 +#define AB8500_CODEC_CR61_CLASSD_DITH_WGAIN 0 + +/* CR62-CR0x003E */ +#define AB8500_CODEC_CR62_DMIC1SINC3 5 +#define AB8500_CODEC_CR62_DMIC2SINC3 4 +#define AB8500_CODEC_CR62_DMIC3SINC3 3 +#define AB8500_CODEC_CR62_DMIC4SINC3 2 +#define AB8500_CODEC_CR62_DMIC5SINC3 1 +#define AB8500_CODEC_CR62_DMIC6SINC3 0 + +/* CR63-CR0x003F */ +#define AB8500_CODEC_CR63_DATOHSLEN 7 +#define AB8500_CODEC_CR63_DATOHSREN 6 +#define AB8500_CODEC_CR63_AD1SEL 5 +#define AB8500_CODEC_CR63_AD2SEL 4 +#define AB8500_CODEC_CR63_AD3SEL 3 +#define AB8500_CODEC_CR63_AD5SEL 2 +#define AB8500_CODEC_CR63_AD6SEL 1 +#define AB8500_CODEC_CR63_ANCSEL 0 + +/* CR64-CR0x0040 */ +#define AB8500_CODEC_CR64_DATOHFREN 7 +#define AB8500_CODEC_CR64_DATOHFLEN 6 +#define AB8500_CODEC_CR64_HFRSEL 5 +#define AB8500_CODEC_CR64_HFLSEL 4 +#define AB8500_CODEC_CR64_STFIR1SEL 2 +#define AB8500_CODEC_CR64_STFIR2SEL 0 + +/* CR65-CR0x0041 */ +#define AB8500_CODEC_CR65_FADEDIS_AD1 6 +#define AB8500_CODEC_CR65_AD1GAIN 0 + +/* CR66-CR0x0042 */ +#define AB8500_CODEC_CR66_FADEDIS_AD2 6 +#define AB8500_CODEC_CR66_AD2GAIN 0 + +/* CR67-CR0x0043 */ +#define AB8500_CODEC_CR67_FADEDIS_AD3 6 +#define AB8500_CODEC_CR67_AD3GAIN 0 + +/* CR68-CR0x0044 */ +#define AB8500_CODEC_CR68_FADEDIS_AD4 6 +#define AB8500_CODEC_CR68_AD4GAIN 0 + +/* CR69-CR0x0045 */ +#define AB8500_CODEC_CR69_FADEDIS_AD5 6 +#define AB8500_CODEC_CR69_AD5GAIN 0 + +/* CR70-CR0x0046 */ +#define AB8500_CODEC_CR70_FADEDIS_AD6 6 +#define AB8500_CODEC_CR70_AD6GAIN 0 + +/* CR71-CR0x0047 */ +#define AB8500_CODEC_CR71_FADEDIS_DA1 6 +#define AB8500_CODEC_CR71_DA1GAIN 0 + +/* CR72-CR0x0048 */ +#define AB8500_CODEC_CR72_FADEDIS_DA2 6 +#define AB8500_CODEC_CR72_DA2GAIN 0 + +/* CR73-CR0x0049 */ +#define AB8500_CODEC_CR73_FADEDIS_DA3 6 +#define AB8500_CODEC_CR73_DA3GAIN 0 + +/* CR74-CR0x004A */ +#define AB8500_CODEC_CR74_FADEDIS_DA4 6 +#define AB8500_CODEC_CR74_DA4GAIN 0 + +/* CR75-CR0x004B */ +#define AB8500_CODEC_CR75_FADEDIS_DA5 6 +#define AB8500_CODEC_CR75_DA5GAIN 0 + +/* CR76-CR0x004C */ +#define AB8500_CODEC_CR76_FADEDIS_DA6 6 +#define AB8500_CODEC_CR76_DA6GAIN 0 + +/* CR77-CR0x004D */ +#define AB8500_CODEC_CR77_FADEDIS_AD1L 6 +#define AB8500_CODEC_CR77_AD1LBGAIN 0 + +/* CR78-CR0x004E */ +#define AB8500_CODEC_CR78_FADEDIS_AD2L 6 +#define AB8500_CODEC_CR78_AD2LBGAIN 0 + +/* CR79-CR0x004F */ +#define AB8500_CODEC_CR79_HSSINC1 7 +#define AB8500_CODEC_CR79_FADEDIS_HSL 4 +#define AB8500_CODEC_CR79_HSLDGAIN 0 + +/* CR80-CR0x0050 */ +#define AB8500_CODEC_CR80_FADE_SPEED 6 +#define AB8500_CODEC_CR80_FADEDIS_HSR 4 +#define AB8500_CODEC_CR80_HSRDGAIN 0 + +/* CR81-CR0x0051 */ +#define AB8500_CODEC_CR81_STFIR1GAIN 0 + +/* CR82-CR0x0052 */ +#define AB8500_CODEC_CR82_STFIR2GAIN 0 + +/* CR83-CR0x0053 */ +#define AB8500_CODEC_CR83_ENANC 2 +#define AB8500_CODEC_CR83_ANCIIRINIT 1 +#define AB8500_CODEC_CR83_ANCFIRUPDATE 0 + +/* CR84-CR0x0054 */ +#define AB8500_CODEC_CR84_ANCINSHIFT 0 + +/* CR85-CR0x0055 */ +#define AB8500_CODEC_CR85_ANCFIROUTSHIFT 0 + +/* CR86-CR0x0056 */ +#define AB8500_CODEC_CR86_ANCSHIFTOUT 0 + +/* CR87-CR0x0057 */ +#define AB8500_CODEC_CR87_ANCFIRCOEFF_MSB 0 + +/* CR88-CR0x0058 */ +#define AB8500_CODEC_CR88_ANCFIRCOEFF_LSB 0 + +/* CR89-CR0x0059 */ +#define AB8500_CODEC_CR89_ANCIIRCOEFF_MSB 0 + +/* CR90-CR0x005A */ +#define AB8500_CODEC_CR90_ANCIIRCOEFF_LSB 0 + +/* CR91-CR0x005B */ +#define AB8500_CODEC_CR91_ANCWARPDEL_MSB 0 + +/* CR92-CR0x005C */ +#define AB8500_CODEC_CR92_ANCWARPDEL_LSB 0 + +/* CR93-CR0x005D */ +#define AB8500_CODEC_CR93_ANCFIRPEAK_MSB 0 + +/* CR94-CR0x005E */ +#define AB8500_CODEC_CR94_ANCFIRPEAK_LSB 0 + +/* CR95-CR0x005F */ +#define AB8500_CODEC_CR95_ANCIIRPEAK_MSB 0 + +/* CR96-CR0x0060 */ +#define AB8500_CODEC_CR96_ANCIIRPEAK_LSB 0 + +/* CR97-CR0x0061 */ +#define AB8500_CODEC_CR97_STFIR_SET 7 +#define AB8500_CODEC_CR97_STFIR_ADDR 0 + +/* CR98-CR0x0062 */ +#define AB8500_CODEC_CR98_STFIR_COEFF_MSB 0 + +/* CR99-CR0x0063 */ +#define AB8500_CODEC_CR99_STFIR_COEFF_LSB 0 + +/* CR100-CR0x0064 */ +#define AB8500_CODEC_CR100_ENSTFIRS 2 +#define AB8500_CODEC_CR100_STFIRSTOIF1 1 +#define AB8500_CODEC_CR100_STFIR_BUSY 0 + +/* CR101-CR0x0065 */ +#define AB8500_CODEC_CR101_HSOFFSTMASK 7 +#define AB8500_CODEC_CR101_FIFOFULLMASK 6 +#define AB8500_CODEC_CR101_FIFOEMPTYMASK 5 +#define AB8500_CODEC_CR101_DASATMASK 4 +#define AB8500_CODEC_CR101_ADSATMASK 3 +#define AB8500_CODEC_CR101_ADDSPMASK 2 +#define AB8500_CODEC_CR101_DADSPMASK 1 +#define AB8500_CODEC_CR101_FIRSIDMASK 0 + +/* CR102-CR0x0066 */ +#define AB8500_CODEC_CR102_IT_HSOFFST 7 +#define AB8500_CODEC_CR102_IT_FIFOFULL 6 +#define AB8500_CODEC_CR102_IT_FIFOEMPTY 5 +#define AB8500_CODEC_CR102_IT_DASAT 4 +#define AB8500_CODEC_CR102_IT_ADSAT 3 +#define AB8500_CODEC_CR102_IT_ADDSP 2 +#define AB8500_CODEC_CR102_IT_DADSP 1 +#define AB8500_CODEC_CR102_IT_FIRSID 0 + +/* CR103-CR0x0067 */ +#define AB8500_CODEC_CR103_VSSREADYMASK 7 +#define AB8500_CODEC_CR103_SHORTHSLMASK 2 +#define AB8500_CODEC_CR103_SHORTHSRMASK 1 +#define AB8500_CODEC_CR103_SHORTEARMASK 0 + +/* CR104-CR0x0068 */ +#define AB8500_CODEC_CR104_IT_VSSREADY 7 +#define AB8500_CODEC_CR104_IT_SHORTHSL 2 +#define AB8500_CODEC_CR104_IT_SHORTHSR 1 +#define AB8500_CODEC_CR104_IT_SHORTEAR 0 + +/* CR105-CR0x0069 */ +#define AB8500_CODEC_CR105_BFIFOMASK 7 +#define AB8500_CODEC_CR105_BFIFOINT 0 + +/* CR106-CR0x006A */ +#define AB8500_CODEC_CR106_BFIFOTX 0 + +/* CR107-CR0x006B */ +#define AB8500_CODEC_CR107_BFIFOEXSL 5 +#define AB8500_CODEC_CR107_PREBITCLK0 2 +#define AB8500_CODEC_CR107_BFIFOMAST 1 +#define AB8500_CODEC_CR107_BFIFORUN 0 + +/* CR108-CR0x006C */ +#define AB8500_CODEC_CR108_BFIFOFRAMESW 0 + +/* CR109-CR0x006D */ +#define AB8500_CODEC_CR109_BFIFOWAKEUP 0 + +/* CR110-CR0x006E */ +#define AB8500_CODEC_CR110_BFIFOSAMPLE 0 + +/* CR111-CR0x006F */ +#define AB8500_CODEC_CR111_AUD_IP_REV 0 + +/* For SetVolume API*/ +#define AB8500_CODEC_MAX_VOLUME 100 + +/* Analog MIC1 & MIC2 */ +#define AB8500_CODEC_MIC_VOLUME_MAX 31 +#define AB8500_CODEC_MIC_VOLUME_MEDIUM 15 +#define AB8500_CODEC_MIC_VOLUME_MIN 0 + +/* Line-in */ +#define AB8500_CODEC_LINEIN_VOLUME_MAX 15 +#define AB8500_CODEC_LINEIN_VOLUME_MEDIUM 7 +#define AB8500_CODEC_LINEIN_VOLUME_MIN 0 + +/* HeadSet */ +#define AB8500_CODEC_HEADSET_VOLUME_MAX 13 +#define AB8500_CODEC_HEADSET_VOLUME_MEDIUM 6 +#define AB8500_CODEC_HEADSET_VOLUME_MIN 0 + +/* HeadSet Digital */ +#define AB8500_CODEC_HEADSET_D_VOLUME_MAX 0 +#define AB8500_CODEC_HEADSET_D_VOLUME_MEDIUM 7 +#define AB8500_CODEC_HEADSET_D_VOLUME_MIN 15 +#define AB8500_CODEC_HEADSET_D_VOLUME_0DB 8 + +/* Digital AD Path */ +#define AB8500_CODEC_AD_D_VOLUME_MAX 0 +#define AB8500_CODEC_AD_D_VOLUME_MEDIUM 31 +#define AB8500_CODEC_AD_D_VOLUME_MIN 63 + +/* Digital DA Path */ +#define AB8500_CODEC_DA_D_VOLUME_MAX 0 +#define AB8500_CODEC_DA_D_VOLUME_MEDIUM 31 +#define AB8500_CODEC_DA_D_VOLUME_MIN 63 + +/* EarPiece Digital */ +#define AB8500_CODEC_EARPIECE_D_VOLUME_MAX 0 +#define AB8500_CODEC_EARPIECE_D_VOLUME_MEDIUM 7 +#define AB8500_CODEC_EARPIECE_D_VOLUME_MIN 15 + +/* AD1 loopback to HFL & HFR Digital */ +#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MAX 0 +#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MEDIUM 31 +#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MIN 63 + +/* Line-in to HSL & HSR */ +#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX 0 +#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MEDIUM 9 +#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN 18 +#define AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN 19 + +/* Vibrator */ +#define AB8500_CODEC_VIBRATOR_VOLUME_MAX 100 +#define AB8500_CODEC_VIBRATOR_VOLUME_MEDIUM 50 +#define AB8500_CODEC_VIBRATOR_VOLUME_MIN 0 + +/* CR0 - 7 */ +typedef enum { + AB8500_CODEC_CR0_POWERUP_OFF, + AB8500_CODEC_CR0_POWERUP_ON +} t_ab8500_codec_cr0_powerup; + +/* CR0 - 3 */ +typedef enum { + AB8500_CODEC_CR0_ENAANA_OFF, + AB8500_CODEC_CR0_ENAANA_ON +} t_ab8500_codec_cr0_enaana; + +/* CR1 - 7 */ +typedef enum { + AB8500_CODEC_CR1_SWRESET_DISABLED, + AB8500_CODEC_CR1_SWRESET_ENABLED +} t_ab8500_codec_cr1_swreset; + +/* CR2 - 7 */ +typedef enum { + AB8500_CODEC_CR2_ENAD1_DISABLED, + AB8500_CODEC_CR2_ENAD1_ENABLED +} t_ab8500_codec_cr2_enad1; + +/* CR2 - 6 */ +typedef enum { + AB8500_CODEC_CR2_ENAD2_DISABLED, + AB8500_CODEC_CR2_ENAD2_ENABLED +} t_ab8500_codec_cr2_enad2; + +/* CR2 - 5 */ +typedef enum { + AB8500_CODEC_CR2_ENAD3_DISABLED, + AB8500_CODEC_CR2_ENAD3_ENABLED +} t_ab8500_codec_cr2_enad3; + +/* CR2 - 4 */ +typedef enum { + AB8500_CODEC_CR2_ENAD4_DISABLED, + AB8500_CODEC_CR2_ENAD4_ENABLED +} t_ab8500_codec_cr2_enad4; + +/* CR2 - 3 */ +typedef enum { + AB8500_CODEC_CR2_ENAD5_DISABLED, + AB8500_CODEC_CR2_ENAD5_ENABLED +} t_ab8500_codec_cr2_enad5; + +/* CR2 - 2 */ +typedef enum { + AB8500_CODEC_CR2_ENAD6_DISABLED, + AB8500_CODEC_CR2_ENAD6_ENABLED +} t_ab8500_codec_cr2_enad6; + +/* CR3 - 7 */ +typedef enum { + AB8500_CODEC_CR3_ENDA1_DISABLED, + AB8500_CODEC_CR3_ENDA1_ENABLED +} t_ab8500_codec_cr3_enda1; + +/* CR3 - 6 */ +typedef enum { + AB8500_CODEC_CR3_ENDA2_DISABLED, + AB8500_CODEC_CR3_ENDA2_ENABLED +} t_ab8500_codec_cr3_enda2; + +/* CR3 - 5 */ +typedef enum { + AB8500_CODEC_CR3_ENDA3_DISABLED, + AB8500_CODEC_CR3_ENDA3_ENABLED +} t_ab8500_codec_cr3_enda3; + +/* CR3 - 4 */ +typedef enum { + AB8500_CODEC_CR3_ENDA4_DISABLED, + AB8500_CODEC_CR3_ENDA4_ENABLED +} t_ab8500_codec_cr3_enda4; + +/* CR3 - 3 */ +typedef enum { + AB8500_CODEC_CR3_ENDA5_DISABLED, + AB8500_CODEC_CR3_ENDA5_ENABLED +} t_ab8500_codec_cr3_enda5; + +/* CR3 - 2 */ +typedef enum { + AB8500_CODEC_CR3_ENDA6_DISABLED, + AB8500_CODEC_CR3_ENDA6_ENABLED +} t_ab8500_codec_cr3_enda6; + +/* CR4 - 7 */ +typedef enum { + AB8500_CODEC_CR4_LOWPOWHS_NORMAL, + AB8500_CODEC_CR4_LOWPOWHS_LP +} t_ab8500_codec_cr4_lowpowhs; + +/* CR4 - 6:5 */ +typedef enum { + AB8500_CODEC_CR4_LOWPOWDACHS_NORMAL, + AB8500_CODEC_CR4_LOWPOWDACHS_DRIVERS_LP, + AB8500_CODEC_CR4_LOWPOWDACHS_LP, + AB8500_CODEC_CR4_LOWPOWDACHS_BOTH_LP +} t_ab8500_codec_cr4_lowpowdachs; + +/* CR4 - 4 */ +typedef enum { + AB8500_CODEC_CR4_LOWPOWEAR_NORMAL, + AB8500_CODEC_CR4_LOWPOWEAR_LP +} t_ab8500_codec_cr4_lowpowear; + +/* CR4 - 3:2 */ +typedef enum { + AB8500_CODEC_CR4_EAR_SEL_CM_0_95V, + AB8500_CODEC_CR4_EAR_SEL_CM_1_1V, + AB8500_CODEC_CR4_EAR_SEL_CM_1_27V, + AB8500_CODEC_CR4_EAR_SEL_CM_1_58V +} t_ab8500_codec_cr4_ear_sel_cm; + +/* CR4 - 1 */ +typedef enum { + AB8500_CODEC_CR4_HS_HP_EN_FILTER_DISABLED, + AB8500_CODEC_CR4_HS_HP_EN_FILTER_ENABLED +} t_ab8500_codec_cr4_hs_hp_en; + +/* CR5 - 7 */ +typedef enum { + AB8500_CODEC_CR5_ENMIC1_DISABLED, + AB8500_CODEC_CR5_ENMIC1_ENABLED +} t_ab8500_codec_cr5_enmic1; + +/* CR5 - 6 */ +typedef enum { + AB8500_CODEC_CR5_ENMIC2_DISABLED, + AB8500_CODEC_CR5_ENMIC2_ENABLED +} t_ab8500_codec_cr5_enmic2; + +/* CR5 - 5 */ +typedef enum { + AB8500_CODEC_CR5_ENLINL_DISABLED, + AB8500_CODEC_CR5_ENLINL_ENABLED +} t_ab8500_codec_cr5_enlinl; + +/* CR5 - 4 */ +typedef enum { + AB8500_CODEC_CR5_ENLINR_DISABLED, + AB8500_CODEC_CR5_ENLINR_ENABLED +} t_ab8500_codec_cr5_enlinr; + +/* CR5 - 3 */ +typedef enum { + AB8500_CODEC_CR5_MUTMIC1_DISABLED, + AB8500_CODEC_CR5_MUTMIC1_ENABLED +} t_ab8500_codec_cr5_mutmic1; + +/* CR5 - 2 */ +typedef enum { + AB8500_CODEC_CR5_MUTMIC2_DISABLED, + AB8500_CODEC_CR5_MUTMIC2_ENABLED +} t_ab8500_codec_cr5_mutmic2; + +/* CR5 - 1 */ +typedef enum { + AB8500_CODEC_CR5_MUTLINL_DISABLED, + AB8500_CODEC_CR5_MUTLINL_ENABLED +} t_ab8500_codec_cr5_mutlinl; + +/* CR5 - 0 */ +typedef enum { + AB8500_CODEC_CR5_MUTLINR_DISABLED, + AB8500_CODEC_CR5_MUTLINR_ENABLED +} t_ab8500_codec_cr5_mutlinr; + +/* CR6 - 7 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC1_DISABLED, + AB8500_CODEC_CR6_ENDMIC1_ENABLED +} t_ab8500_codec_cr6_endmic1; + +/* CR6 - 6 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC2_DISABLED, + AB8500_CODEC_CR6_ENDMIC2_ENABLED +} t_ab8500_codec_cr6_endmic2; + +/* CR6 - 5 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC3_DISABLED, + AB8500_CODEC_CR6_ENDMIC3_ENABLED +} t_ab8500_codec_cr6_endmic3; + +/* CR6 - 4 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC4_DISABLED, + AB8500_CODEC_CR6_ENDMIC4_ENABLED +} t_ab8500_codec_cr6_endmic4; + +/* CR6 - 3 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC5_DISABLED, + AB8500_CODEC_CR6_ENDMIC5_ENABLED +} t_ab8500_codec_cr6_endmic5; + +/* CR6 - 2 */ +typedef enum { + AB8500_CODEC_CR6_ENDMIC6_DISABLED, + AB8500_CODEC_CR6_ENDMIC6_ENABLED +} t_ab8500_codec_cr6_endmic6; + +/* CR7 - 7 */ +typedef enum { + AB8500_CODEC_CR7_MIC1SEL_MIC1A, + AB8500_CODEC_CR7_MIC1SEL_MIC1B +} t_ab8500_codec_cr7_mic1sel; + +/* CR7 - 6 */ +typedef enum { + AB8500_CODEC_CR7_LINRSEL_MIC2, + AB8500_CODEC_CR7_LINRSEL_LINR +} t_ab8500_codec_cr7_linrsel; + +/* CR7 - 5 */ +typedef enum { + AB8500_CODEC_CR7_ENDRVHSL_DISABLED, + AB8500_CODEC_CR7_ENDRVHSL_ENABLED +} t_ab8500_codec_cr7_endrvhsl; + +/* CR7 - 4 */ +typedef enum { + AB8500_CODEC_CR7_ENDRVHSR_DISABLED, + AB8500_CODEC_CR7_ENDRVHSR_ENABLED +} t_ab8500_codec_cr7_endrvhsr; + +/* CR7 - 2 */ +typedef enum { + AB8500_CODEC_CR7_ENADCMIC_DISABLED, + AB8500_CODEC_CR7_ENADCMIC_ENABLED +} t_ab8500_codec_cr7_enadcmic; + +/* CR7 - 1 */ +typedef enum { + AB8500_CODEC_CR7_ENADCLINL_DISABLED, + AB8500_CODEC_CR7_ENADCLINL_ENABLED +} t_ab8500_codec_cr7_enadclinl; + +/* CR7 - 0 */ +typedef enum { + AB8500_CODEC_CR7_ENADCLINR_DISABLED, + AB8500_CODEC_CR7_ENADCLINR_ENABLED +} t_ab8500_codec_cr7_enadclinr; + +/* CR8 - 7 */ +typedef enum { + AB8500_CODEC_CR8_CP_DIS_PLDWN_ENABLED, + AB8500_CODEC_CR8_CP_DIS_PLDWN_DISABLED +} t_ab8500_codec_cr8_cp_dis_pldwn; + +/* CR8 - 6 */ +typedef enum { + AB8500_CODEC_CR8_ENEAR_DISABLED, + AB8500_CODEC_CR8_ENEAR_ENABLED +} t_ab8500_codec_cr8_enear; + +/* CR8 - 5 */ +typedef enum { + AB8500_CODEC_CR8_ENHSL_DISABLED, + AB8500_CODEC_CR8_ENHSL_ENABLED +} t_ab8500_codec_cr8_enhsl; + +/* CR8 - 4 */ +typedef enum { + AB8500_CODEC_CR8_ENHSR_DISABLED, + AB8500_CODEC_CR8_ENHSR_ENABLED +} t_ab8500_codec_cr8_enhsr; + +/* CR8 - 3 */ +typedef enum { + AB8500_CODEC_CR8_ENHFL_DISABLED, + AB8500_CODEC_CR8_ENHFL_ENABLED +} t_ab8500_codec_cr8_enhfl; + +/* CR8 - 2 */ +typedef enum { + AB8500_CODEC_CR8_ENHFR_DISABLED, + AB8500_CODEC_CR8_ENHFR_ENABLED +} t_ab8500_codec_cr8_enhfr; + +/* CR8 - 1 */ +typedef enum { + AB8500_CODEC_CR8_ENVIBL_DISABLED, + AB8500_CODEC_CR8_ENVIBL_ENABLED +} t_ab8500_codec_cr8_envibl; + +/* CR8 - 0 */ +typedef enum { + AB8500_CODEC_CR8_ENVIBR_DISABLED, + AB8500_CODEC_CR8_ENVIBR_ENABLED +} t_ab8500_codec_cr8_envibr; + +/* CR9 - 6 */ +typedef enum { + AB8500_CODEC_CR9_ENDACEAR_DISABLED, + AB8500_CODEC_CR9_ENDACEAR_ENABLED +} t_ab8500_codec_cr9_endacear; + +/* CR9 - 5 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHSL_DISABLED, + AB8500_CODEC_CR9_ENDACHSL_ENABLED +} t_ab8500_codec_cr9_endachsl; + +/* CR9 - 4 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHSR_DISABLED, + AB8500_CODEC_CR9_ENDACHSR_ENABLED +} t_ab8500_codec_cr9_endachsr; + +/* CR9 - 3 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHFL_DISABLED, + AB8500_CODEC_CR9_ENDACHFL_ENABLED +} t_ab8500_codec_cr9_endachfl; + +/* CR9 - 2 */ +typedef enum { + AB8500_CODEC_CR9_ENDACHFR_DISABLED, + AB8500_CODEC_CR9_ENDACHFR_ENABLED +} t_ab8500_codec_cr9_endachfr; + +/* CR9 - 1 */ +typedef enum { + AB8500_CODEC_CR9_ENDACVIBL_DISABLED, + AB8500_CODEC_CR9_ENDACVIBL_ENABLED +} t_ab8500_codec_cr9_endacvibl; + +/* CR9 - 0 */ +typedef enum { + AB8500_CODEC_CR9_ENDACVIBR_DISABLED, + AB8500_CODEC_CR9_ENDACVIBR_ENABLED +} t_ab8500_codec_cr9_endacvibr; + +/* CR10 - 6 */ +typedef enum { + AB8500_CODEC_CR10_MUTEEAR_DISABLED, + AB8500_CODEC_CR10_MUTEEAR_ENABLED +} t_ab8500_codec_cr10_muteear; + +/* CR10 - 5 */ +typedef enum { + AB8500_CODEC_CR10_MUTEHSL_DISABLED, + AB8500_CODEC_CR10_MUTEHSL_ENABLED +} t_ab8500_codec_cr10_mutehsl; + +/* CR10 - 4 */ +typedef enum { + AB8500_CODEC_CR10_MUTEHSR_DISABLED, + AB8500_CODEC_CR10_MUTEHSR_ENABLED +} t_ab8500_codec_cr10_mutehsr; + +/* CR11 - 7 */ +typedef enum { + AB8500_CODEC_CR11_ENSHORTPWD_DISABLED, + AB8500_CODEC_CR11_ENSHORTPWD_ENABLED +} t_ab8500_codec_cr11_enshortpwd; + +/* CR11 - 6 */ +typedef enum { + AB8500_CODEC_CR11_EARSHORTDIS_ENABLED, + AB8500_CODEC_CR11_EARSHORTDIS_DISABLED +} t_ab8500_codec_cr11_earshortdis; + +/* CR11 - 5 */ +typedef enum { + AB8500_CODEC_CR11_HSSHORTDIS_ENABLED, + AB8500_CODEC_CR11_HSSHORTDIS_DISABLED +} t_ab8500_codec_cr11_hsshortdis; + +/* CR11 - 4 */ +typedef enum { + AB8500_CODEC_CR11_HSPULLDEN_HIGH, + AB8500_CODEC_CR11_HSPULLDEN_DOWN +} t_ab8500_codec_cr11_hspullden; + +/* CR11 - 2 */ +typedef enum { + AB8500_CODEC_CR11_HSOSCEN_SYSTEMCLOCK, + AB8500_CODEC_CR11_HSOSCEN_LOCALOSC +} t_ab8500_codec_cr11_hsoscen; + +/* CR11 - 1 */ +typedef enum { + AB8500_CODEC_CR11_HSFADEN_FADING, + AB8500_CODEC_CR11_HSFADEN_IMMEDIATELY +} t_ab8500_codec_cr11_hsfaden; + +/* CR11 - 0 */ +typedef enum { + AB8500_CODEC_CR11_HSZCDDIS_ONZEROCROSS, + AB8500_CODEC_CR11_HSZCDDIS_WITHOUTZEROCROSS +} t_ab8500_codec_cr11_hszcddis; + +/* CR12 - 7 */ +typedef enum { + AB8500_CODEC_CR12_ENCPHS_DISABLED, + AB8500_CODEC_CR12_ENCPHS_ENABLED +} t_ab8500_codec_cr12_encphs; + +/* CR12 - 0 */ +typedef enum { + AB8500_CODEC_CR12_HSAUTOEN_DISABLED, + AB8500_CODEC_CR12_HSAUTOEN_ENABLED +} t_ab8500_codec_cr12_hsautoen; + +/* CR13 - 7:4 */ +typedef enum { + AB8500_CODEC_CR13_ENVDET_HTHRESH_25, + AB8500_CODEC_CR13_ENVDET_HTHRESH_50, + AB8500_CODEC_CR13_ENVDET_HTHRESH_100, + AB8500_CODEC_CR13_ENVDET_HTHRESH_150, + AB8500_CODEC_CR13_ENVDET_HTHRESH_200, + AB8500_CODEC_CR13_ENVDET_HTHRESH_250, + AB8500_CODEC_CR13_ENVDET_HTHRESH_300, + AB8500_CODEC_CR13_ENVDET_HTHRESH_350, + AB8500_CODEC_CR13_ENVDET_HTHRESH_400, + AB8500_CODEC_CR13_ENVDET_HTHRESH_450, + AB8500_CODEC_CR13_ENVDET_HTHRESH_500, + AB8500_CODEC_CR13_ENVDET_HTHRESH_550, + AB8500_CODEC_CR13_ENVDET_HTHRESH_600, + AB8500_CODEC_CR13_ENVDET_HTHRESH_650, + AB8500_CODEC_CR13_ENVDET_HTHRESH_700, + AB8500_CODEC_CR13_ENVDET_HTHRESH_750 +} t_ab8500_codec_cr13_envdet_hthresh; + +/* CR13 - 3:0 */ +typedef enum { + AB8500_CODEC_CR13_ENVDET_LTHRESH_25, + AB8500_CODEC_CR13_ENVDET_LTHRESH_50, + AB8500_CODEC_CR13_ENVDET_LTHRESH_100, + AB8500_CODEC_CR13_ENVDET_LTHRESH_150, + AB8500_CODEC_CR13_ENVDET_LTHRESH_200, + AB8500_CODEC_CR13_ENVDET_LTHRESH_250, + AB8500_CODEC_CR13_ENVDET_LTHRESH_300, + AB8500_CODEC_CR13_ENVDET_LTHRESH_350, + AB8500_CODEC_CR13_ENVDET_LTHRESH_400, + AB8500_CODEC_CR13_ENVDET_LTHRESH_450, + AB8500_CODEC_CR13_ENVDET_LTHRESH_500, + AB8500_CODEC_CR13_ENVDET_LTHRESH_550, + AB8500_CODEC_CR13_ENVDET_LTHRESH_600, + AB8500_CODEC_CR13_ENVDET_LTHRESH_650, + AB8500_CODEC_CR13_ENVDET_LTHRESH_700, + AB8500_CODEC_CR13_ENVDET_LTHRESH_750 +} t_ab8500_codec_cr13_envdet_lthresh; + +/* CR14 - 7 */ +typedef enum { + AB8500_CODEC_CR14_SMPSLVEN_HIGHVOLTAGE, + AB8500_CODEC_CR14_SMPSLVEN_LOWVOLTAGE +} t_ab8500_codec_cr14_smpslven; + +/* CR14 - 6 */ +typedef enum { + AB8500_CODEC_CR14_ENVDETSMPSEN_DISABLED, + AB8500_CODEC_CR14_ENVDETSMPSEN_ENABLED +} t_ab8500_codec_cr14_envdetsmpsen; + +/* CR14 - 5 */ +typedef enum { + AB8500_CODEC_CR14_CPLVEN_HIGHVOLTAGE, + AB8500_CODEC_CR14_CPLVEN_LOWVOLTAGE +} t_ab8500_codec_cr14_cplven; + +/* CR14 - 4 */ +typedef enum { + AB8500_CODEC_CR14_ENVDETCPEN_DISABLED, + AB8500_CODEC_CR14_ENVDETCPEN_ENABLED +} t_ab8500_codec_cr14_envdetcpen; + +/* CR14 - 3:0 */ +typedef enum { + AB8500_CODEC_CR14_ENVET_TIME_27USEC, + AB8500_CODEC_CR14_ENVET_TIME_53USEC, + AB8500_CODEC_CR14_ENVET_TIME_106USEC, + AB8500_CODEC_CR14_ENVET_TIME_212USEC, + AB8500_CODEC_CR14_ENVET_TIME_424USEC, + AB8500_CODEC_CR14_ENVET_TIME_848USEC, + AB8500_CODEC_CR14_ENVET_TIME_1MSEC, + AB8500_CODEC_CR14_ENVET_TIME_3MSEC, + AB8500_CODEC_CR14_ENVET_TIME_6MSEC, + AB8500_CODEC_CR14_ENVET_TIME_13MSEC, + AB8500_CODEC_CR14_ENVET_TIME_27MSEC, + AB8500_CODEC_CR14_ENVET_TIME_54MSEC, + AB8500_CODEC_CR14_ENVET_TIME_109MSEC, + AB8500_CODEC_CR14_ENVET_TIME_218MSEC, + AB8500_CODEC_CR14_ENVET_TIME_436MSEC, + AB8500_CODEC_CR14_ENVET_TIME_872MSEC, +} t_ab8500_codec_cr14_envet_time; + +/* CR15 - 7 */ +typedef enum { + AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH, + AB8500_CODEC_CR15_PWMTOVIBL_PWM +} t_ab8500_codec_cr15_pwmtovibl; + +/* CR15 - 6 */ +typedef enum { + AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH, + AB8500_CODEC_CR15_PWMTOVIBR_PWM +} t_ab8500_codec_cr15_pwmtovibr; + +/* CR15 - 5 */ +typedef enum { + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL, + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE +} t_ab8500_codec_cr15_pwmlctrl; + +/* CR15 - 4 */ +typedef enum { + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL, + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE +} t_ab8500_codec_cr15_pwmrctrl; + +/* CR15 - 3 */ +typedef enum { + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL, + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE +} t_ab8500_codec_cr15_pwmnlctrl; + +/* CR15 - 2 */ +typedef enum { + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL, + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE +} t_ab8500_codec_cr15_pwmplctrl; + +/* CR15 - 1 */ +typedef enum { + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL, + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE +} t_ab8500_codec_cr15_pwmnrctrl; + +/* CR15 - 0 */ +typedef enum { + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL, + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE +} t_ab8500_codec_cr15_pwmprctrl; + +/* CR16 - 7 */ +typedef enum { + AB8500_CODEC_CR16_PWMNLPOL_GNDVIB, + AB8500_CODEC_CR16_PWMNLPOL_VINVIB +} t_ab8500_codec_cr16_pwmnlpol; + +/* CR16 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr16_pwmnldutycycle; + +/* CR17 - 7 */ +typedef enum { + AB8500_CODEC_CR17_PWMPLPOL_GNDVIB, + AB8500_CODEC_CR17_PWMPLPOL_VINVIB +} t_ab8500_codec_cr17_pwmplpol; + +/* CR17 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr17_pwmpldutycycle; + +/* CR18 - 7 */ +typedef enum { + AB8500_CODEC_CR18_PWMNRPOL_GNDVIB, + AB8500_CODEC_CR18_PWMNRPOL_VINVIB +} t_ab8500_codec_cr18_pwmnrpol; + +/* CR18 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr18_pwmnrdutycycle; + +/* CR19 - 7 */ +typedef enum { + AB8500_CODEC_CR19_PWMPRPOL_GNDVIB, + AB8500_CODEC_CR19_PWMPRPOL_VINVIB +} t_ab8500_codec_cr19_pwmprpol; + +/* CR19 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr19_pwmprdutycycle; + +/* CR20 - 7 */ +typedef enum { + AB8500_CODEC_CR20_EN_SE_MIC1_DIFFERENTIAL, + AB8500_CODEC_CR20_EN_SE_MIC1_SINGLE +} t_ab8500_codec_cr20_en_se_mic1; + +/* CR20 - 6 */ +typedef enum { + AB8500_CODEC_CR20_LOW_POW_MIC1_NORMAL, + AB8500_CODEC_CR20_LOW_POW_MIC1_LOW_POWER +} t_ab8500_codec_cr20_low_pow_mic1; + +/* CR20 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr20_mic1_gain; + +/* CR21 - 7 */ +typedef enum { + AB8500_CODEC_CR21_EN_SE_MIC2_DIFFERENTIAL, + AB8500_CODEC_CR21_EN_SE_MIC2_SINGLE +} t_ab8500_codec_cr21_en_se_mic2; + +/* CR21 - 6 */ +typedef enum { + AB8500_CODEC_CR21_LOW_POW_MIC2_NORMAL, + AB8500_CODEC_CR21_LOW_POW_MIC2_LOW_POWER +} t_ab8500_codec_cr21_low_pow_mic2; + +/* CR21 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr21_mic2_gain; + +/* CR22 - 7:4 */ +typedef t_uint8 t_ab8500_codec_cr22_hsl_gain; + +/* CR22 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr22_hsr_gain; + +/* CR23 - 7:4 */ +typedef t_uint8 t_ab8500_codec_cr23_linl_gain; + +/* CR23 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr23_linr_gain; + +/* CR24 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr24_lintohsl_gain; + +/* CR25 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr25_lintohsr_gain; + +/* CR26 - 7 */ +typedef enum { + AB8500_CODEC_CR26_AD1NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD1NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad1nh; + +/* CR26 - 6 */ +typedef enum { + AB8500_CODEC_CR26_AD2NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD2NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad2nh; + +/* CR26 - 5 */ +typedef enum { + AB8500_CODEC_CR26_AD3NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD3NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad3nh; + +/* CR26 - 4 */ +typedef enum { + AB8500_CODEC_CR26_AD4NH_FILTER_ENABLED, + AB8500_CODEC_CR26_AD4NH_FILTER_DISABLED +} t_ab8500_codec_cr26_ad4nh; + +/* CR26 - 3 */ +typedef enum { + AB8500_CODEC_CR26_AD1_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD1_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad1_voice; + +/* CR26 - 2 */ +typedef enum { + AB8500_CODEC_CR26_AD2_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD2_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad2_voice; + +/* CR26 - 1 */ +typedef enum { + AB8500_CODEC_CR26_AD3_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD3_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad3_voice; + +/* CR26 - 0 */ +typedef enum { + AB8500_CODEC_CR26_AD4_VOICE_AUDIOFILTER, + AB8500_CODEC_CR26_AD4_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr26_ad4_voice; + +/* CR27 - 7 */ +typedef enum { + AB8500_CODEC_CR27_EN_MASTGEN_DISABLED, + AB8500_CODEC_CR27_EN_MASTGEN_ENABLED +} t_ab8500_codec_cr27_en_mastgen; + +/* CR27 - 6:5 */ +/* In ab8500_codec.h */ + +/* CR27 - 4 */ +typedef enum { + AB8500_CODEC_CR27_ENFS_BITCLK1_DISABLED, + AB8500_CODEC_CR27_ENFS_BITCLK1_ENABLED +} t_ab8500_codec_cr27_enfs_bitclk1; + +/* CR27 - 2:1 */ +/* In ab8500_codec.h */ + +/* CR27 - 0 */ +typedef enum { + AB8500_CODEC_CR27_ENFS_BITCLK0_DISABLED, + AB8500_CODEC_CR27_ENFS_BITCLK0_ENABLED +} t_ab8500_codec_cr27_enfs_bitclk0; + +/* CR28 - 6 */ +typedef enum { + AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE, + AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE +} t_ab8500_codec_cr28_fsync0p; + +/* CR28 - 5 */ +typedef enum { + AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE, + AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE +} t_ab8500_codec_cr28_bitclk0p; + +/* CR28 - 4 */ +typedef enum { + AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED, + AB8500_CODEC_CR28_IF0DEL_DELAYED +} t_ab8500_codec_cr28_if0del; + +/* CR28 - 3:2 */ +typedef enum { + AB8500_CODEC_CR28_IF0FORMAT_DISABLED, + AB8500_CODEC_CR28_IF0FORMAT_TDM, + AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED +} t_ab8500_codec_cr28_if0format; + +/* CR28 - 1:0 */ +/* In ab8500_codec.h */ + +/* CR29 - 7 */ +typedef enum { + AB8500_CODEC_CR29_IF0DATOIF1AD_NOTSENT, + AB8500_CODEC_CR29_IF0DATOIF1AD_SENT +} t_ab8500_codec_cr29_if0datoif1ad; + +/* CR29 - 6 */ +typedef enum { + AB8500_CODEC_CR29_IF0CKTOIF1CK_NOTSENT, + AB8500_CODEC_CR29_IF0CKTOIF1CK_SENT +} t_ab8500_codec_cr29_if0cktoif1ck; + +/* CR29 - 5 */ +typedef enum { + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_INPUT, + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_OUTPUT +} t_ab8500_codec_cr29_if1master; + +/* CR29 - 3 */ +typedef enum { + AB8500_CODEC_CR29_IF1DATOIF0AD_NOTSENT, + AB8500_CODEC_CR29_IF1DATOIF0AD_SENT +} t_ab8500_codec_cr29_if1datoif0ad; + +/* CR29 - 2 */ +typedef enum { + AB8500_CODEC_CR29_IF1CKTOIF0CK_NOTSENT, + AB8500_CODEC_CR29_IF1CKTOIF0CK_SENT +} t_ab8500_codec_cr29_if1cktoif0ck; + +/* CR29 - 1 */ +typedef enum { + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_INPUT, + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_OUTPUT +} t_ab8500_codec_cr29_if0master; + +/* CR29 - 0 */ +typedef enum { + AB8500_CODEC_CR29_IF0BFIFOEN_NORMAL_MODE, + AB8500_CODEC_CR29_IF0BFIFOEN_BURST_MODE +} t_ab8500_codec_cr29_if0bfifoen; + +/* CR30 - 6 */ +typedef enum { + AB8500_CODEC_CR30_FSYNC1P_RISING_EDGE, + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE +} t_ab8500_codec_cr30_fsync1p; + +/* CR30 - 5 */ +typedef enum { + AB8500_CODEC_CR30_BITCLK1P_RISING_EDGE, + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE +} t_ab8500_codec_cr30_bitclk1p; + +/* CR30 - 4 */ +typedef enum { + AB8500_CODEC_CR30_IF1DEL_NOT_DELAYED, + AB8500_CODEC_CR30_IF1DEL_DELAYED +} t_ab8500_codec_cr30_if1del; + +/* CR30 - 3:2 */ +typedef enum { + AB8500_CODEC_CR30_IF1FORMAT_DISABLED, + AB8500_CODEC_CR30_IF1FORMAT_TDM, + AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED +} t_ab8500_codec_cr30_if1format; + +/* CR30 - 1:0 */ +/* In ab8500_codec.h */ + +/* CR31:46 - 7:4 or 3:0 */ +/* In ab8500_codec.h */ + +/* CR47:50 - 7/6/5/4/3/2/1/0 */ +typedef enum { + AB8500_CODEC_CR47_TO_CR50_HIZ_SL_LOW_IMPEDANCE, + AB8500_CODEC_CR47_TO_CR50_HIZ_SL_HIGH_IMPEDANCE, +} t_ab8500_codec_cr47_to_cr50_hiz_sl; + +/* CR51 - 7 */ +typedef enum { + AB8500_CODEC_CR51_DA12_VOICE_AUDIOFILTER, + AB8500_CODEC_CR51_DA12_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr51_da12_voice; + +/* CR51 - 6 */ +typedef enum { + AB8500_CODEC_CR51_SWAPDA12_34_NORMAL, + AB8500_CODEC_CR51_SWAPDA12_34_SWAPPED +} t_ab8500_codec_cr51_swapda12_34; + +/* CR51 - 5 */ +typedef enum { + AB8500_CODEC_CR51_SLDAI7TOSLADO1_NOT_LOOPEDBACK, + AB8500_CODEC_CR51_SLDAI7TOSLADO1_LOOPEDBACK +} t_ab8500_codec_cr51_sldai7toslado1; + +/* CR51:58 - 4:0 */ +/* In ab8500_codec.h */ + +/* CR52 - 5 */ +typedef enum { + AB8500_CODEC_CR52_SLDAI8TOSLADO2_NOT_LOOPEDBACK, + AB8500_CODEC_CR52_SLDAI8TOSLADO2_LOOPEDBACK +} t_ab8500_codec_cr52_sldai8toslado2; + +/* CR53 - 7 */ +typedef enum { + AB8500_CODEC_CR53_DA34_VOICE_AUDIOFILTER, + AB8500_CODEC_CR53_DA34_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr53_da34_voice; + +/* CR53 - 5 */ +typedef enum { + AB8500_CODEC_CR53_SLDAI7TOSLADO3_NOT_LOOPEDBACK, + AB8500_CODEC_CR53_SLDAI7TOSLADO3_LOOPEDBACK +} t_ab8500_codec_cr53_sldai7toslado3; + +/* CR54 - 5 */ +typedef enum { + AB8500_CODEC_CR54_SLDAI8TOSLADO4_NOT_LOOPEDBACK, + AB8500_CODEC_CR54_SLDAI8TOSLADO4_LOOPEDBACK +} t_ab8500_codec_cr54_sldai8toslado4; + +/* CR55 - 7 */ +typedef enum { + AB8500_CODEC_CR55_DA56_VOICE_AUDIOFILTER, + AB8500_CODEC_CR55_DA56_VOICE_LOWLATENCYFILTER +} t_ab8500_codec_cr55_da56_voice; + +/* CR55 - 5 */ +typedef enum { + AB8500_CODEC_CR55_SLDAI7TOSLADO5_NOT_LOOPEDBACK, + AB8500_CODEC_CR55_SLDAI7TOSLADO5_LOOPEDBACK +} t_ab8500_codec_cr55_sldai7toslado5; + +/* CR56 - 5 */ +typedef enum { + AB8500_CODEC_CR56_SLDAI8TOSLADO6_NOT_LOOPEDBACK, + AB8500_CODEC_CR56_SLDAI8TOSLADO6_LOOPEDBACK +} t_ab8500_codec_cr56_sldai8toslado6; + +/* CR57 - 5 */ +typedef enum { + AB8500_CODEC_CR57_SLDAI8TOSLADO7_NOT_LOOPEDBACK, + AB8500_CODEC_CR57_SLDAI8TOSLADO7_LOOPEDBACK +} t_ab8500_codec_cr57_sldai8toslado7; + +/* CR58 - 5 */ +typedef enum { + AB8500_CODEC_CR58_SLDAI7TOSLADO8_NOT_LOOPEDBACK, + AB8500_CODEC_CR58_SLDAI7TOSLADO8_LOOPEDBACK +} t_ab8500_codec_cr58_sldai7toslado8; + +/* CR59 - 7 */ +typedef enum { + AB8500_CODEC_CR59_PARLHF_INDEPENDENT, + AB8500_CODEC_CR59_PARLHF_BRIDGED +} t_ab8500_codec_cr59_parlhf; + +/* CR59 - 6 */ +typedef enum { + AB8500_CODEC_CR59_PARLVIB_INDEPENDENT, + AB8500_CODEC_CR59_PARLVIB_BRIDGED +} t_ab8500_codec_cr59_parlvib; + +/* CR59 - 3 */ +typedef enum { + AB8500_CODEC_CR59_CLASSDVIB1_SWAPEN_DISABLED, + AB8500_CODEC_CR59_CLASSDVIB1_SWAPEN_ENABLED +} t_ab8500_codec_cr59_classdvib1_swapen; + +/* CR59 - 2 */ +typedef enum { + AB8500_CODEC_CR59_CLASSDVIB2_SWAPEN_DISABLED, + AB8500_CODEC_CR59_CLASSDVIB2_SWAPEN_ENABLED +} t_ab8500_codec_cr59_classdvib2_swapen; + +/* CR59 - 1 */ +typedef enum { + AB8500_CODEC_CR59_CLASSDHFL_SWAPEN_DISABLED, + AB8500_CODEC_CR59_CLASSDHFL_SWAPEN_ENABLED +} t_ab8500_codec_cr59_classdhfl_swapen; + +/* CR59 - 0 */ +typedef enum { + AB8500_CODEC_CR59_CLASSDHFR_SWAPEN_DISABLED, + AB8500_CODEC_CR59_CLASSDHFR_SWAPEN_ENABLED +} t_ab8500_codec_cr59_classdhfr_swapen; + +/* CR60 - 7:4 */ +typedef enum { + AB8500_CODEC_CR60_CLASSD_FIRBYP_ALL_ENABLED = 0, + AB8500_CODEC_CR60_CLASSD_FIRBYP_LEFT_HF_BYPASSED = 1, + AB8500_CODEC_CR60_CLASSD_FIRBYP_RIGHT_HF_BYPASSED = 2, + AB8500_CODEC_CR60_CLASSD_FIRBYP_VIBRA1_BYPASSED = 4, + AB8500_CODEC_CR60_CLASSD_FIRBYP_VIBRA2_BYPASSED = 8 +} t_ab8500_codec_cr60_classd_firbyp; + +/* CR60 - 3:0 */ +typedef enum { + AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_DISABLED = 0, + AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_LEFT_HF = 1, + AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_RIGHT_HF = 2, + AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_VIBRA1 = 4, + AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_VIBRA2 = 8 +} t_ab8500_codec_cr60_classd_highvolen; + +/* CR61 - 7:4 */ +typedef t_uint8 t_ab8500_codec_cr61_classddith_hpgain; + +/* CR61 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr61_classddith_wgain; + +/* CR62 - Read Only */ +/* CR62 - 5 */ +typedef enum { + AB8500_CODEC_CR62_DMIC1SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC1SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic1sinc3; + +/* CR62 - 4 */ +typedef enum { + AB8500_CODEC_CR62_DMIC2SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC2SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic2sinc3; + +/* CR62 - 3 */ +typedef enum { + AB8500_CODEC_CR62_DMIC3SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC3SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic3sinc3; + +/* CR62 - 2 */ +typedef enum { + AB8500_CODEC_CR62_DMIC4SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC4SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic4sinc3; + +/* CR62 - 1 */ +typedef enum { + AB8500_CODEC_CR62_DMIC5SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC5SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic5sinc3; + +/* CR62 - 0 */ +typedef enum { + AB8500_CODEC_CR62_DMIC6SINC3_SINC5_SELECTED, + AB8500_CODEC_CR62_DMIC6SINC3_SINC3_SELECTED +} t_ab8500_codec_cr62_dmic6sinc3; + +/* CR63 - 7 */ +typedef enum { + AB8500_CODEC_CR63_DATOHSLEN_DISABLED, + AB8500_CODEC_CR63_DATOHSLEN_ENABLED +} t_ab8500_codec_cr63_datohslen; + +/* CR63 - 6 */ +typedef enum { + AB8500_CODEC_CR63_DATOHSREN_DISABLED, + AB8500_CODEC_CR63_DATOHSREN_ENABLED +} t_ab8500_codec_cr63_datohsren; + +/* CR63 - 5 */ +typedef enum { + AB8500_CODEC_CR63_AD1SEL_LINLADL_SELECTED, + AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED +} t_ab8500_codec_cr63_ad1sel; + +/* CR63 - 4 */ +typedef enum { + AB8500_CODEC_CR63_AD2SEL_LINRADR_SELECTED, + AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED +} t_ab8500_codec_cr63_ad2sel; + +/* CR63 - 3 */ +typedef enum { + AB8500_CODEC_CR63_AD3SEL_ADMO_SELECTED, + AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED +} t_ab8500_codec_cr63_ad3sel; + +/* CR63 - 2 */ +typedef enum { + AB8500_CODEC_CR63_AD5SEL_AMADR_SELECTED, + AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED +} t_ab8500_codec_cr63_ad5sel; + +/* CR63 - 1 */ +typedef enum { + AB8500_CODEC_CR63_AD6SEL_ADMO_SELECTED, + AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED +} t_ab8500_codec_cr63_ad6sel; + +/* CR63 - 0 */ +typedef enum { + AB8500_CODEC_CR63_ANCSEL_NOT_MIXED_IN_EAR, + AB8500_CODEC_CR63_ANCSEL_MIXED_IN_EAR +} t_ab8500_codec_cr63_ancsel; + +/* CR64 - 7 */ +typedef enum { + AB8500_CODEC_CR64_DATOHFREN_NOT_MIXED_TO_HFR, + AB8500_CODEC_CR64_DATOHFREN_MIXED_TO_HFR +} t_ab8500_codec_cr64_datohfren; + +/* CR64 - 6 */ +typedef enum { + AB8500_CODEC_CR64_DATOHFLEN_NOT_MIXED_TO_HFL, + AB8500_CODEC_CR64_DATOHFLEN_MIXED_TO_HFL +} t_ab8500_codec_cr64_datohflen; + +/* CR64 - 5 */ +typedef enum { + AB8500_CODEC_CR64_HFRSEL_DA4_MIXED_TO_HFR, + AB8500_CODEC_CR64_HFRSEL_ANC_MIXED_TO_HFR +} t_ab8500_codec_cr64_hfrsel; + +/* CR64 - 4 */ +typedef enum { + AB8500_CODEC_CR64_HFLSEL_DA3_MIXED_TO_HFL, + AB8500_CODEC_CR64_HFLSEL_ANC_MIXED_TO_HFL +} t_ab8500_codec_cr64_hflsel; + +/* CR64 - 3:2 */ +typedef enum { + AB8500_CODEC_CR64_STFIR1SEL_AD_OUT1_SELECTED, + AB8500_CODEC_CR64_STFIR1SEL_AD_OUT3_SELECTED, + AB8500_CODEC_CR64_STFIR1SEL_DA_IN1_SELECTED +} t_ab8500_codec_cr64_stfir1sel; + +/* CR64 - 1:0 */ +typedef enum { + AB8500_CODEC_CR64_STFIR2SEL_AD_OUT2_SELECTED, + AB8500_CODEC_CR64_STFIR2SEL_AD_OUT4_SELECTED, + AB8500_CODEC_CR64_STFIR2SEL_DA_IN2_SELECTED +} t_ab8500_codec_cr64_stfir2sel; + +/* CR65 - 6 */ +typedef enum { + AB8500_CODEC_CR65_FADEDIS_AD1_ENABLED, + AB8500_CODEC_CR65_FADEDIS_AD1_DISABLED +} t_ab8500_codec_cr65_fadedis_ad1; + +/* CR65 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr65_ad1gain; + +/* CR66 - 6 */ +typedef enum { + AB8500_CODEC_CR66_FADEDIS_AD2_ENABLED, + AB8500_CODEC_CR66_FADEDIS_AD2_DISABLED +} t_ab8500_codec_cr66_fadedis_ad2; + +/* CR66 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr66_ad2gain; + +/* CR67 - 6 */ +typedef enum { + AB8500_CODEC_CR67_FADEDIS_AD3_ENABLED, + AB8500_CODEC_CR67_FADEDIS_AD3_DISABLED +} t_ab8500_codec_cr67_fadedis_ad3; + +/* CR67 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr67_ad3gain; + +/* CR68 - 6 */ +typedef enum { + AB8500_CODEC_CR68_FADEDIS_AD4_ENABLED, + AB8500_CODEC_CR68_FADEDIS_AD4_DISABLED +} t_ab8500_codec_cr68_fadedis_ad4; + +/* CR68 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr68_ad4gain; + +/* CR69 - 6 */ +typedef enum { + AB8500_CODEC_CR69_FADEDIS_AD5_ENABLED, + AB8500_CODEC_CR69_FADEDIS_AD5_DISABLED +} t_ab8500_codec_cr69_fadedis_ad5; + +/* CR69 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr69_ad5gain; + +/* CR70 - 6 */ +typedef enum { + AB8500_CODEC_CR70_FADEDIS_AD6_ENABLED, + AB8500_CODEC_CR70_FADEDIS_AD6_DISABLED +} t_ab8500_codec_cr70_fadedis_ad6; + +/* CR70 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr70_ad6gain; + +/* CR71 - 6 */ +typedef enum { + AB8500_CODEC_CR71_FADEDIS_DA1_ENABLED, + AB8500_CODEC_CR71_FADEDIS_DA1_DISABLED +} t_ab8500_codec_cr71_fadedis_da1; + +/* CR71 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr71_da1gain; + +/* CR72 - 6 */ +typedef enum { + AB8500_CODEC_CR72_FADEDIS_DA2_ENABLED, + AB8500_CODEC_CR72_FADEDIS_DA2_DISABLED +} t_ab8500_codec_cr72_fadedis_da2; + +/* CR72 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr72_da2gain; + +/* CR73 - 6 */ +typedef enum { + AB8500_CODEC_CR73_FADEDIS_DA3_ENABLED, + AB8500_CODEC_CR73_FADEDIS_DA3_DISABLED +} t_ab8500_codec_cr73_fadedis_da3; + +/* CR73 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr73_da3gain; + +/* CR74 - 6 */ +typedef enum { + AB8500_CODEC_CR74_FADEDIS_DA4_ENABLED, + AB8500_CODEC_CR74_FADEDIS_DA4_DISABLED +} t_ab8500_codec_cr74_fadedis_da4; + +/* CR74 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr74_da4gain; + +/* CR75 - 6 */ +typedef enum { + AB8500_CODEC_CR75_FADEDIS_DA5_ENABLED, + AB8500_CODEC_CR75_FADEDIS_DA5_DISABLED +} t_ab8500_codec_cr75_fadedis_da5; + +/* CR75 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr75_da5gain; + +/* CR76 - 6 */ +typedef enum { + AB8500_CODEC_CR76_FADEDIS_DA6_ENABLED, + AB8500_CODEC_CR76_FADEDIS_DA6_DISABLED +} t_ab8500_codec_cr76_fadedis_da6; + +/* CR76 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr76_da6gain; + +/* CR77 - 6 */ +typedef enum { + AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_ENABLED, + AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_DISABLED +} t_ab8500_codec_cr77_fadedis_ad1l; + +/* CR77 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr77_ad1lbgain_to_hfl; + +/* CR78 - 6 */ +typedef enum { + AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_ENABLED, + AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_DISABLED +} t_ab8500_codec_cr78_fadedis_ad2l; + +/* CR78 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr78_ad2lbgain_to_hfr; + +/* CR79 - 7 */ +typedef enum { + AB8500_CODEC_CR79_HSSINC1_SINC3_CHOOSEN, + AB8500_CODEC_CR79_HSSINC1_SINC1_CHOOSEN +} t_ab8500_codec_cr79_hssinc1; + +/* CR79 - 4 */ +typedef enum { + AB8500_CODEC_CR79_FADEDIS_HSL_ENABLED, + AB8500_CODEC_CR79_FADEDIS_HSL_DISABLED +} t_ab8500_codec_cr79_fadedis_hsl; + +/* CR79 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr79_hsldgain; + +/* CR80 - 7:6 */ +typedef enum { + AB8500_CODEC_CR80_FADE_SPEED_1MS, + AB8500_CODEC_CR80_FADE_SPEED_4MS, + AB8500_CODEC_CR80_FADE_SPEED_8MS, + AB8500_CODEC_CR80_FADE_SPEED_16MS, +} t_ab8500_codec_cr80_fade_speed; + +/* CR80 - 4 */ +typedef enum { + AB8500_CODEC_CR80_FADEDIS_HSR_ENABLED, + AB8500_CODEC_CR80_FADEDIS_HSR_DISABLED +} t_ab8500_codec_cr80_fadedis_hsr; + +/* CR80 - 3:0 */ +typedef t_uint8 t_ab8500_codec_cr80_hsrdgain; + +/* CR81 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr81_stfir1gain; + +/* CR82 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr82_stfir2gain; + +/* CR83 - 2 */ +typedef enum { + AB8500_CODEC_CR83_ENANC_DISABLED, + AB8500_CODEC_CR83_ENANC_ENABLED +} t_ab8500_codec_cr83_enanc; + +/* CR83 - 1 */ +typedef enum { + AB8500_CODEC_CR83_ANCIIRINIT_NOT_STARTED, + AB8500_CODEC_CR83_ANCIIRINIT_STARTED +} t_ab8500_codec_cr83_anciirinit; + +/* CR83 - 0 */ +typedef enum { + AB8500_CODEC_CR83_ANCFIRUPDATE_RESETTED, + AB8500_CODEC_CR83_ANCFIRUPDATE_NOT_RESETTED +} t_ab8500_codec_cr83_ancfirupdate; + +/* CR84 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr84_ancinshift; + +/* CR85 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr85_ancfiroutshift; + +/* CR86 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr86_ancshiftout; + +/* CR87 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr87_ancfircoeff_msb; + +/* CR88 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr88_ancfircoeff_lsb; + +/* CR89 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr89_anciircoeff_msb; + +/* CR90 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr90_anciircoeff_lsb; + +/* CR91 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr91_ancwarpdel_msb; + +/* CR92 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr92_ancwarpdel_lsb; + +/* CR93 - Read Only */ +/* CR93 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr93_ancfirpeak_msb; + +/* CR94 - Read Only */ +/* CR94 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr94_ancfirpeak_lsb; + +/* CR95 - Read Only */ +/* CR95 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr95_anciirpeak_msb; + +/* CR96 - Read Only */ +/* CR96 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr96_anciirpeak_lsb; + +/* CR97 - 7 */ +typedef enum { + AB8500_CODEC_CR97_STFIR_SET_LAST_NOT_APPLIED, + AB8500_CODEC_CR97_STFIR_SET_LAST_APPLIED +} t_ab8500_codec_cr97_stfir_set; + +/* CR97 - 6:0 */ +typedef t_uint8 t_ab8500_codec_cr97_stfir_addr; + +/* CR98 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr98_stfir_coeff_msb; + +/* CR99 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr99_stfir_coeff_lsb; + +/* CR100 - 2 */ +typedef enum { + AB8500_CODEC_CR100_ENSTFIRS_DISABLED, + AB8500_CODEC_CR100_ENSTFIRS_ENABLED +} t_ab8500_codec_cr100_enstfirs; + +/* CR100 - 1 */ +typedef enum { + AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF0_DATA_RATE, + AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF1_DATA_RATE +} t_ab8500_codec_cr100_stfirstoif1; + +/* CR100 - 0 */ +typedef enum { + AB8500_CODEC_CR100_STFIR_BUSY_READY, + AB8500_CODEC_CR100_STFIR_BUSY_NOT_READY +} t_ab8500_codec_cr100_stfir_busy; + +/* CR101 - 7 */ +typedef enum { + AB8500_CODEC_CR101_HSOFFST_MASK_MASKED, + AB8500_CODEC_CR101_HSOFFST_MASK_ENABLED +} t_ab8500_codec_cr101_hsoffst_mask; + +/* CR101 - 6 */ +typedef enum { + AB8500_CODEC_CR101_FIFOFULL_MASK_MASKED, + AB8500_CODEC_CR101_FIFOFULL_MASK_ENABLED +} t_ab8500_codec_cr101_fifofull_mask; + +/* CR101 - 5 */ +typedef enum { + AB8500_CODEC_CR101_FIFOEMPTY_MASK_MASKED, + AB8500_CODEC_CR101_FIFOEMPTY_MASK_ENABLED +} t_ab8500_codec_cr101_fifoempty_mask; + +/* CR101 - 4 */ +typedef enum { + AB8500_CODEC_CR101_DASAT_MASK_MASKED, + AB8500_CODEC_CR101_DASAT_MASK_ENABLED +} t_ab8500_codec_cr101_dasat_mask; + +/* CR101 - 3 */ +typedef enum { + AB8500_CODEC_CR101_ADSAT_MASK_MASKED, + AB8500_CODEC_CR101_ADSAT_MASK_ENABLED +} t_ab8500_codec_cr101_adsat_mask; + +/* CR101 - 2 */ +typedef enum { + AB8500_CODEC_CR101_ADDSP_MASK_MASKED, + AB8500_CODEC_CR101_ADDSP_MASK_ENABLED +} t_ab8500_codec_cr101_addsp_mask; + +/* CR101 - 1 */ +typedef enum { + AB8500_CODEC_CR101_DADSP_MASK_MASKED, + AB8500_CODEC_CR101_DADSP_MASK_ENABLED +} t_ab8500_codec_cr101_dadsp_mask; + +/* CR101 - 0 */ +typedef enum { + AB8500_CODEC_CR101_FIRSID_MASK_MASKED, + AB8500_CODEC_CR101_FIRSID_MASK_ENABLED +} t_ab8500_codec_cr101_firsid_mask; + +/* CR102 - Read Only */ +/* CR102 - 7 */ +typedef enum { + AB8500_CODEC_CR102_IT_HSOFFST_ON, + AB8500_CODEC_CR102_IT_HSOFFST_OFF +} t_ab8500_codec_cr102_it_hsoffst; + +/* CR102 - 6 */ +typedef enum { + AB8500_CODEC_CR102_IT_FIFOFULL_NOT_FULL, + AB8500_CODEC_CR102_IT_FIFOFULL_FULL +} t_ab8500_codec_cr102_it_fifofull; + +/* CR102 - 5 */ +typedef enum { + AB8500_CODEC_CR102_IT_FIFOEMPTY_NOT_EMPTY, + AB8500_CODEC_CR102_IT_FIFOEMPTY_EMPTY +} t_ab8500_codec_cr102_it_fifoempty; + +/* CR102 - 4 */ +typedef enum { + AB8500_CODEC_CR102_IT_DASAT_NO_SATURATION, + AB8500_CODEC_CR102_IT_DASAT_SATURATION +} t_ab8500_codec_cr102_it_dasat; + +/* CR102 - 3 */ +typedef enum { + AB8500_CODEC_CR102_IT_ADSAT_NO_SATURATION, + AB8500_CODEC_CR102_IT_ADSAT_SATURATION +} t_ab8500_codec_cr102_it_adsat; + +/* CR102 - 2 */ +typedef enum { + AB8500_CODEC_CR102_IT_ADDSP_NO_SATURATION, + AB8500_CODEC_CR102_IT_ADDSP_SATURATION +} t_ab8500_codec_cr102_it_addsp; + +/* CR102 - 1 */ +typedef enum { + AB8500_CODEC_CR102_IT_DADSP_NO_SATURATION, + AB8500_CODEC_CR102_IT_DADSP_SATURATION +} t_ab8500_codec_cr102_it_dadsp; + +/* CR102 - 0 */ +typedef enum { + AB8500_CODEC_CR102_IT_FIRSID_NO_SATURATION, + AB8500_CODEC_CR102_IT_FIRSID_SATURATION +} t_ab8500_codec_cr102_it_firsid; + +/* CR103 - 7 */ +typedef enum { + AB8500_CODEC_CR103_VSSREADY_MASK_MASKED, + AB8500_CODEC_CR103_VSSREADY_MASK_ENABLED +} t_ab8500_codec_cr103_vssready_mask; + +/* CR103 - 2 */ +typedef enum { + AB8500_CODEC_CR103_SHORTHSL_MASK_MASKED, + AB8500_CODEC_CR103_SHORTHSL_MASK_ENABLED +} t_ab8500_codec_cr103_shorthsl_mask; + +/* CR103 - 1 */ +typedef enum { + AB8500_CODEC_CR103_SHORTHSR_MASK_MASKED, + AB8500_CODEC_CR103_SHORTHSR_MASK_ENABLED +} t_ab8500_codec_cr103_shorthsr_mask; + +/* CR103 - 0 */ +typedef enum { + AB8500_CODEC_CR103_SHORTEAR_MASK_MASKED, + AB8500_CODEC_CR103_SHORTEAR_MASK_ENABLED +} t_ab8500_codec_cr103_shortear_mask; + +/* CR104 - Read Only */ +/* CR104 - 7 */ +typedef enum { + AB8500_CODEC_CR104_IT_VSSREADY_NOT_READY, + AB8500_CODEC_CR104_IT_VSSREADY_READY +} t_ab8500_codec_cr104_it_vssready; + +/* CR104 - 2 */ +typedef enum { + AB8500_CODEC_CR104_IT_SHORTHSL_NOT_DETECTED, + AB8500_CODEC_CR104_IT_SHORTHSL_DETECTED +} t_ab8500_codec_cr104_it_shorthsl; + +/* CR104 - 1 */ +typedef enum { + AB8500_CODEC_CR104_IT_SHORTHSR_NOT_DETECTED, + AB8500_CODEC_CR104_IT_SHORTHSR_DETECTED +} t_ab8500_codec_cr104_it_shorthsr; + +/* CR104 - 0 */ +typedef enum { + AB8500_CODEC_CR104_IT_SHORTEAR_NOT_DETECTED, + AB8500_CODEC_CR104_IT_SHORTEAR_DETECTED +} t_ab8500_codec_cr104_it_shortear; + +/* CR105 - 7 */ +/* In ab8500_codec.h */ + +/* CR105 - 5:0 */ +/* In ab8500_codec.h */ + +/* CR106 - 7:0 */ +/* In ab8500_codec.h */ + +/* CR107 - 7:0 */ +/* In ab8500_codec.h */ + +/* CR108 - 7:0 */ +/* In ab8500_codec.h */ + +/* CR109 - 7:0 */ +/* In ab8500_codec.h */ + +/* CR110 - Read Only */ +/* CR110 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr110_bfifosamples; + +/* CR111 - Read Only */ +/* CR111 - 4:0 */ +typedef t_uint8 t_ab8500_codec_cr111_aud_ip_rev; + +/* CR27 - 6:5 */ +typedef enum { + AB8500_CODEC_CR27_IF1_BITCLK_OSR_32, + AB8500_CODEC_CR27_IF1_BITCLK_OSR_64, + AB8500_CODEC_CR27_IF1_BITCLK_OSR_128, + AB8500_CODEC_CR27_IF1_BITCLK_OSR_256 +} t_ab8500_codec_cr27_if1_bitclk_osr; + +/* CR27 - 2:1 */ +typedef enum { + AB8500_CODEC_CR27_IF0_BITCLK_OSR_32, + AB8500_CODEC_CR27_IF0_BITCLK_OSR_64, + AB8500_CODEC_CR27_IF0_BITCLK_OSR_128, + AB8500_CODEC_CR27_IF0_BITCLK_OSR_256 +} t_ab8500_codec_cr27_if0_bitclk_osr; + +/* CR28 - 1:0 */ +typedef enum { + AB8500_CODEC_CR28_IF0WL_16BITS, + AB8500_CODEC_CR28_IF0WL_20BITS, + AB8500_CODEC_CR28_IF0WL_24BITS, + AB8500_CODEC_CR28_IF0WL_32BITS +} t_ab8500_codec_cr28_if0wl; + +/* CR30 - 1:0 */ +typedef enum { + AB8500_CODEC_CR30_IF1WL_16BITS, + AB8500_CODEC_CR30_IF1WL_20BITS, + AB8500_CODEC_CR30_IF1WL_24BITS, + AB8500_CODEC_CR30_IF1WL_32BITS +} t_ab8500_codec_cr30_if1wl; + +/* CR105 - 7 */ +typedef enum { + AB8500_CODEC_CR105_BFIFOMSK_AD_DATA0_UNMASKED, + AB8500_CODEC_CR105_BFIFOMSK_AD_DATA0_MASKED +} t_ab8500_codec_cr105_bfifomsk; + +/* CR105 - 5:0 */ +typedef t_uint8 t_ab8500_codec_cr105_bfifoint; + +/* CR106 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr106_bfifotx; + +/* CR107 - 7:5 */ +typedef enum { + AB8500_CODEC_CR107_BFIFOEXSL_0_EXTRA_SLOT, + AB8500_CODEC_CR107_BFIFOEXSL_1_EXTRA_SLOT, + AB8500_CODEC_CR107_BFIFOEXSL_2_EXTRA_SLOT, + AB8500_CODEC_CR107_BFIFOEXSL_3_EXTRA_SLOT, + AB8500_CODEC_CR107_BFIFOEXSL_4_EXTRA_SLOT, + AB8500_CODEC_CR107_BFIFOEXSL_5_EXTRA_SLOT, + AB8500_CODEC_CR107_BFIFOEXSL_6_EXTRA_SLOT, +} t_ab8500_codec_cr107_bfifoexsl; + +/* CR107 - 4:2 */ +typedef enum { + AB8500_CODEC_CR107_PREBITCLK0_0_EXTRA_CLK, + AB8500_CODEC_CR107_PREBITCLK0_1_EXTRA_CLK, + AB8500_CODEC_CR107_PREBITCLK0_2_EXTRA_CLK, + AB8500_CODEC_CR107_PREBITCLK0_3_EXTRA_CLK, + AB8500_CODEC_CR107_PREBITCLK0_4_EXTRA_CLK, + AB8500_CODEC_CR107_PREBITCLK0_5_EXTRA_CLK, + AB8500_CODEC_CR107_PREBITCLK0_6_EXTRA_CLK, + AB8500_CODEC_CR107_PREBITCLK0_7_EXTRA_CLK +} t_ab8500_codec_cr107_prebitclk0; + +/* CR107 - 1 */ +typedef enum { + AB8500_CODEC_CR107_BFIFOMAST_SLAVE_MODE, + AB8500_CODEC_CR107_BFIFOMAST_MASTER_MODE +} t_ab8500_codec_cr107_bfifomast; + +/* CR107 - 0 */ +typedef enum { + AB8500_CODEC_CR107_BFIFORUN_STOPPED, + AB8500_CODEC_CR107_BFIFORUN_RUNNING +} t_ab8500_codec_cr107_bfiforun; + +/* CR108 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr108_bfifoframsw; + +/* CR109 - 7:0 */ +typedef t_uint8 t_ab8500_codec_cr109_bfifowakeup; + +typedef enum { + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT4, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT5, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT6, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT7, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT8, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_ZEROS, + AB8500_CODEC_CR31_TO_CR46_SLOT_IS_TRISTATE = 15, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED +} t_ab8500_codec_cr31_to_cr46_ad_data_allocation; + +typedef enum { + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT00, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT01, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT02, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT03, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT04, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT05, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT06, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT07, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT08, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT09, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT10, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT11, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT12, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT13, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT14, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT15, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT16, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT17, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT18, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT19, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT20, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT21, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT22, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT23, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT24, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT25, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT26, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT27, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT28, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT29, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT30, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT31, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT_UNDEFINED +} t_ab8500_codec_cr51_to_cr58_sltoda; + +/*configuration structure for AB8500 Codec*/ +typedef struct { + /* CR0 */ + t_ab8500_codec_cr0_powerup cr0_powerup; + t_ab8500_codec_cr0_enaana cr0_enaana; + + /* CR1 */ + t_ab8500_codec_cr1_swreset cr1_swreset; + + /* CR2 */ + t_ab8500_codec_cr2_enad1 cr2_enad1; + t_ab8500_codec_cr2_enad2 cr2_enad2; + t_ab8500_codec_cr2_enad3 cr2_enad3; + t_ab8500_codec_cr2_enad4 cr2_enad4; + t_ab8500_codec_cr2_enad5 cr2_enad5; + t_ab8500_codec_cr2_enad6 cr2_enad6; + + /* CR3 */ + t_ab8500_codec_cr3_enda1 cr3_enda1; + t_ab8500_codec_cr3_enda2 cr3_enda2; + t_ab8500_codec_cr3_enda3 cr3_enda3; + t_ab8500_codec_cr3_enda4 cr3_enda4; + t_ab8500_codec_cr3_enda5 cr3_enda5; + t_ab8500_codec_cr3_enda6 cr3_enda6; + + /* CR4 */ + t_ab8500_codec_cr4_lowpowhs cr4_lowpowhs; + t_ab8500_codec_cr4_lowpowdachs cr4_lowpowdachs; + t_ab8500_codec_cr4_lowpowear cr4_lowpowear; + t_ab8500_codec_cr4_ear_sel_cm cr4_ear_sel_cm; + t_ab8500_codec_cr4_hs_hp_en cr4_hs_hp_en; + + /* CR5 */ + t_ab8500_codec_cr5_enmic1 cr5_enmic1; + t_ab8500_codec_cr5_enmic2 cr5_enmic2; + t_ab8500_codec_cr5_enlinl cr5_enlinl; + t_ab8500_codec_cr5_enlinr cr5_enlinr; + t_ab8500_codec_cr5_mutmic1 cr5_mutmic1; + t_ab8500_codec_cr5_mutmic2 cr5_mutmic2; + t_ab8500_codec_cr5_mutlinl cr5_mutlinl; + t_ab8500_codec_cr5_mutlinr cr5_mutlinr; + + /* CR6 */ + t_ab8500_codec_cr6_endmic1 cr6_endmic1; + t_ab8500_codec_cr6_endmic2 cr6_endmic2; + t_ab8500_codec_cr6_endmic3 cr6_endmic3; + t_ab8500_codec_cr6_endmic4 cr6_endmic4; + t_ab8500_codec_cr6_endmic5 cr6_endmic5; + t_ab8500_codec_cr6_endmic6 cr6_endmic6; + + /* CR7 */ + t_ab8500_codec_cr7_mic1sel cr7_mic1sel; + t_ab8500_codec_cr7_linrsel cr7_linrsel; + t_ab8500_codec_cr7_endrvhsl cr7_endrvhsl; + t_ab8500_codec_cr7_endrvhsr cr7_endrvhsr; + t_ab8500_codec_cr7_enadcmic cr7_enadcmic; + t_ab8500_codec_cr7_enadclinl cr7_enadclinl; + t_ab8500_codec_cr7_enadclinr cr7_enadclinr; + + /* CR8 */ + t_ab8500_codec_cr8_cp_dis_pldwn cr8_cp_dis_pldwn; + t_ab8500_codec_cr8_enear cr8_enear; + t_ab8500_codec_cr8_enhsl cr8_enhsl; + t_ab8500_codec_cr8_enhsr cr8_enhsr; + t_ab8500_codec_cr8_enhfl cr8_enhfl; + t_ab8500_codec_cr8_enhfr cr8_enhfr; + t_ab8500_codec_cr8_envibl cr8_envibl; + t_ab8500_codec_cr8_envibr cr8_envibr; + + /* CR9 */ + t_ab8500_codec_cr9_endacear cr9_endacear; + t_ab8500_codec_cr9_endachsl cr9_endachsl; + t_ab8500_codec_cr9_endachsr cr9_endachsr; + t_ab8500_codec_cr9_endachfl cr9_endachfl; + t_ab8500_codec_cr9_endachfr cr9_endachfr; + t_ab8500_codec_cr9_endacvibl cr9_endacvibl; + t_ab8500_codec_cr9_endacvibr cr9_endacvibr; + + /* CR10 */ + t_ab8500_codec_cr10_muteear cr10_muteear; + t_ab8500_codec_cr10_mutehsl cr10_mutehsl; + t_ab8500_codec_cr10_mutehsr cr10_mutehsr; + + /* CR11 */ + t_ab8500_codec_cr11_enshortpwd cr11_enshortpwd; + t_ab8500_codec_cr11_earshortdis cr11_earshortdis; + t_ab8500_codec_cr11_hsshortdis cr11_hsshortdis; + t_ab8500_codec_cr11_hspullden cr11_hspullden; + t_ab8500_codec_cr11_hsoscen cr11_hsoscen; + t_ab8500_codec_cr11_hsfaden cr11_hsfaden; + t_ab8500_codec_cr11_hszcddis cr11_hszcddis; + + /* CR12 */ + t_ab8500_codec_cr12_encphs cr12_encphs; + t_ab8500_codec_cr12_hsautoen cr12_hsautoen; + + /* CR13 */ + t_ab8500_codec_cr13_envdet_hthresh cr13_envdet_hthresh; + t_ab8500_codec_cr13_envdet_lthresh cr13_envdet_lthresh; + + /* CR14 */ + t_ab8500_codec_cr14_smpslven cr14_smpslven; + t_ab8500_codec_cr14_envdetsmpsen cr14_envdetsmpsen; + t_ab8500_codec_cr14_cplven cr14_cplven; + t_ab8500_codec_cr14_envdetcpen cr14_envdetcpen; + t_ab8500_codec_cr14_envet_time cr14_envet_time; + + /* CR15 */ + t_ab8500_codec_cr15_pwmtovibl cr15_pwmtovibl; + t_ab8500_codec_cr15_pwmtovibr cr15_pwmtovibr; + t_ab8500_codec_cr15_pwmlctrl cr15_pwmlctrl; + t_ab8500_codec_cr15_pwmrctrl cr15_pwmrctrl; + t_ab8500_codec_cr15_pwmnlctrl cr15_pwmnlctrl; + t_ab8500_codec_cr15_pwmplctrl cr15_pwmplctrl; + t_ab8500_codec_cr15_pwmnrctrl cr15_pwmnrctrl; + t_ab8500_codec_cr15_pwmprctrl cr15_pwmprctrl; + + /* CR16 */ + t_ab8500_codec_cr16_pwmnlpol cr16_pwmnlpol; + t_ab8500_codec_cr16_pwmnldutycycle cr16_pwmnldutycycle; + + /* CR17 */ + t_ab8500_codec_cr17_pwmplpol cr17_pwmplpol; + t_ab8500_codec_cr17_pwmpldutycycle cr17_pwmpldutycycle; + + /* CR18 */ + t_ab8500_codec_cr18_pwmnrpol cr18_pwmnrpol; + t_ab8500_codec_cr18_pwmnrdutycycle cr18_pwmnrdutycycle; + + /* CR19 */ + t_ab8500_codec_cr19_pwmprpol cr19_pwmprpol; + t_ab8500_codec_cr19_pwmprdutycycle cr19_pwmprdutycycle; + + /* CR20 */ + t_ab8500_codec_cr20_en_se_mic1 cr20_en_se_mic1; + t_ab8500_codec_cr20_low_pow_mic1 cr20_low_pow_mic1; + t_ab8500_codec_cr20_mic1_gain cr20_mic1_gain; + + /* CR21 */ + t_ab8500_codec_cr21_en_se_mic2 cr21_en_se_mic2; + t_ab8500_codec_cr21_low_pow_mic2 cr21_low_pow_mic2; + t_ab8500_codec_cr21_mic2_gain cr21_mic2_gain; + + /* CR22 */ + t_ab8500_codec_cr22_hsl_gain cr22_hsl_gain; + t_ab8500_codec_cr22_hsr_gain cr22_hsr_gain; + + /* CR23 */ + t_ab8500_codec_cr23_linl_gain cr23_linl_gain; + t_ab8500_codec_cr23_linr_gain cr23_linr_gain; + + /* CR24 */ + t_ab8500_codec_cr24_lintohsl_gain cr24_lintohsl_gain; + + /* CR25 */ + t_ab8500_codec_cr25_lintohsr_gain cr25_lintohsr_gain; + + /* CR26 */ + t_ab8500_codec_cr26_ad1nh cr26_ad1nh; + t_ab8500_codec_cr26_ad2nh cr26_ad2nh; + t_ab8500_codec_cr26_ad3nh cr26_ad3nh; + t_ab8500_codec_cr26_ad4nh cr26_ad4nh; + t_ab8500_codec_cr26_ad1_voice cr26_ad1_voice; + t_ab8500_codec_cr26_ad2_voice cr26_ad2_voice; + t_ab8500_codec_cr26_ad3_voice cr26_ad3_voice; + t_ab8500_codec_cr26_ad4_voice cr26_ad4_voice; + + /* CR27 */ + t_ab8500_codec_cr27_en_mastgen cr27_en_mastgen; + t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr; + t_ab8500_codec_cr27_enfs_bitclk1 cr27_enfs_bitclk1; + t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr; + t_ab8500_codec_cr27_enfs_bitclk0 cr27_enfs_bitclk0; + + /* CR28 */ + t_ab8500_codec_cr28_fsync0p cr28_fsync0p; + t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p; + t_ab8500_codec_cr28_if0del cr28_if0del; + t_ab8500_codec_cr28_if0format cr28_if0format; + t_ab8500_codec_cr28_if0wl cr28_if0wl; + + /* CR29 */ + t_ab8500_codec_cr29_if0datoif1ad cr29_if0datoif1ad; + t_ab8500_codec_cr29_if0cktoif1ck cr29_if0cktoif1ck; + t_ab8500_codec_cr29_if1master cr29_if1master; + t_ab8500_codec_cr29_if1datoif0ad cr29_if1datoif0ad; + t_ab8500_codec_cr29_if1cktoif0ck cr29_if1cktoif0ck; + t_ab8500_codec_cr29_if0master cr29_if0master; + t_ab8500_codec_cr29_if0bfifoen cr29_if0bfifoen; + + /* CR30 */ + t_ab8500_codec_cr30_fsync1p cr30_fsync1p; + t_ab8500_codec_cr30_bitclk1p cr30_bitclk1p; + t_ab8500_codec_cr30_if1del cr30_if1del; + t_ab8500_codec_cr30_if1format cr30_if1format; + t_ab8500_codec_cr30_if1wl cr30_if1wl; + + /* CR31 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot1; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot0; + + /* CR32 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot3; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot2; + + /* CR33 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot5; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot4; + + /* CR34 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot7; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot6; + + /* CR35 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot9; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot8; + + /* CR36 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot11; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot10; + + /* CR37 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot13; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot12; + + /* CR38 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot15; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot14; + + /* CR39 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot17; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot16; + + /* CR40 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot19; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot18; + + /* CR41 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot21; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot20; + + /* CR42 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot23; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot22; + + /* CR43 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot25; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot24; + + /* CR44 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot27; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot26; + + /* CR45 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot29; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot28; + + /* CR46 */ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot31; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot30; + + /* CR47 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl7; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl6; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl5; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl4; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl3; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl2; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl1; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl0; + + /* CR48 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl15; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl14; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl13; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl12; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl11; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl10; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl9; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl8; + + /* CR49 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl23; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl22; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl21; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl20; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl19; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl18; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl17; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl16; + + /* CR50 */ + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl31; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl30; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl29; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl28; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl27; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl26; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl25; + t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl24; + + /* CR51 */ + t_ab8500_codec_cr51_da12_voice cr51_da12_voice; + t_ab8500_codec_cr51_swapda12_34 cr51_swapda12_34; + t_ab8500_codec_cr51_sldai7toslado1 cr51_sldai7toslado1; + t_ab8500_codec_cr51_to_cr58_sltoda cr51_sltoda1; + + /* CR52 */ + t_ab8500_codec_cr52_sldai8toslado2 cr52_sldai8toslado2; + t_ab8500_codec_cr51_to_cr58_sltoda cr52_sltoda2; + + /* CR53 */ + t_ab8500_codec_cr53_da34_voice cr53_da34_voice; + t_ab8500_codec_cr53_sldai7toslado3 cr53_sldai7toslado3; + t_ab8500_codec_cr51_to_cr58_sltoda cr53_sltoda3; + + /* CR54 */ + t_ab8500_codec_cr54_sldai8toslado4 cr54_sldai8toslado4; + t_ab8500_codec_cr51_to_cr58_sltoda cr54_sltoda4; + + /* CR55 */ + t_ab8500_codec_cr55_da56_voice cr55_da56_voice; + t_ab8500_codec_cr55_sldai7toslado5 cr55_sldai7toslado5; + t_ab8500_codec_cr51_to_cr58_sltoda cr55_sltoda5; + + /* CR56 */ + t_ab8500_codec_cr56_sldai8toslado6 cr56_sldai8toslado6; + t_ab8500_codec_cr51_to_cr58_sltoda cr56_sltoda6; + + /* CR57 */ + t_ab8500_codec_cr57_sldai8toslado7 cr57_sldai8toslado7; + t_ab8500_codec_cr51_to_cr58_sltoda cr57_sltoda7; + + /* CR58 */ + t_ab8500_codec_cr58_sldai7toslado8 cr58_sldai7toslado8; + t_ab8500_codec_cr51_to_cr58_sltoda cr58_sltoda8; + + /* CR59 */ + t_ab8500_codec_cr59_parlhf cr59_parlhf; + t_ab8500_codec_cr59_parlvib cr59_parlvib; + t_ab8500_codec_cr59_classdvib1_swapen cr59_classdvib1_swapen; + t_ab8500_codec_cr59_classdvib2_swapen cr59_classdvib2_swapen; + t_ab8500_codec_cr59_classdhfl_swapen cr59_classdhfl_swapen; + t_ab8500_codec_cr59_classdhfr_swapen cr59_classdhfr_swapen; + + /* CR60 */ + t_ab8500_codec_cr60_classd_firbyp cr60_classd_firbyp; + t_ab8500_codec_cr60_classd_highvolen cr60_classd_highvolen; + + /* CR61 */ + t_ab8500_codec_cr61_classddith_hpgain cr61_classddith_hpgain; + t_ab8500_codec_cr61_classddith_wgain cr61_classddith_wgain; + + /* CR62 */ + t_ab8500_codec_cr62_dmic1sinc3 cr62_dmic1sinc3; + t_ab8500_codec_cr62_dmic2sinc3 cr62_dmic2sinc3; + t_ab8500_codec_cr62_dmic3sinc3 cr62_dmic3sinc3; + t_ab8500_codec_cr62_dmic4sinc3 cr62_dmic4sinc3; + t_ab8500_codec_cr62_dmic5sinc3 cr62_dmic5sinc3; + t_ab8500_codec_cr62_dmic6sinc3 cr62_dmic6sinc3; + + /* CR63 */ + t_ab8500_codec_cr63_datohslen cr63_datohslen; + t_ab8500_codec_cr63_datohsren cr63_datohsren; + t_ab8500_codec_cr63_ad1sel cr63_ad1sel; + t_ab8500_codec_cr63_ad2sel cr63_ad2sel; + t_ab8500_codec_cr63_ad3sel cr63_ad3sel; + t_ab8500_codec_cr63_ad5sel cr63_ad5sel; + t_ab8500_codec_cr63_ad6sel cr63_ad6sel; + t_ab8500_codec_cr63_ancsel cr63_ancsel; + + /* CR64 */ + t_ab8500_codec_cr64_datohfren cr64_datohfren; + t_ab8500_codec_cr64_datohflen cr64_datohflen; + t_ab8500_codec_cr64_hfrsel cr64_hfrsel; + t_ab8500_codec_cr64_hflsel cr64_hflsel; + t_ab8500_codec_cr64_stfir1sel cr64_stfir1sel; + t_ab8500_codec_cr64_stfir2sel cr64_stfir2sel; + + /* CR65 */ + t_ab8500_codec_cr65_fadedis_ad1 cr65_fadedis_ad1; + t_ab8500_codec_cr65_ad1gain cr65_ad1gain; + + /* CR66 */ + t_ab8500_codec_cr66_fadedis_ad2 cr66_fadedis_ad2; + t_ab8500_codec_cr66_ad2gain cr66_ad2gain; + + /* CR67 */ + t_ab8500_codec_cr67_fadedis_ad3 cr67_fadedis_ad3; + t_ab8500_codec_cr67_ad3gain cr67_ad3gain; + + /* CR68 */ + t_ab8500_codec_cr68_fadedis_ad4 cr68_fadedis_ad4; + t_ab8500_codec_cr68_ad4gain cr68_ad4gain; + + /* CR69 */ + t_ab8500_codec_cr69_fadedis_ad5 cr69_fadedis_ad5; + t_ab8500_codec_cr69_ad5gain cr69_ad5gain; + + /* CR70 */ + t_ab8500_codec_cr70_fadedis_ad6 cr70_fadedis_ad6; + t_ab8500_codec_cr70_ad6gain cr70_ad6gain; + + /* CR71 */ + t_ab8500_codec_cr71_fadedis_da1 cr71_fadedis_da1; + t_ab8500_codec_cr71_da1gain cr71_da1gain; + + /* CR72 */ + t_ab8500_codec_cr72_fadedis_da2 cr72_fadedis_da2; + t_ab8500_codec_cr72_da2gain cr72_da2gain; + + /* CR73 */ + t_ab8500_codec_cr73_fadedis_da3 cr73_fadedis_da3; + t_ab8500_codec_cr73_da3gain cr73_da3gain; + + /* CR74 */ + t_ab8500_codec_cr74_fadedis_da4 cr74_fadedis_da4; + t_ab8500_codec_cr74_da4gain cr74_da4gain; + + /* CR75 */ + t_ab8500_codec_cr75_fadedis_da5 cr75_fadedis_da5; + t_ab8500_codec_cr75_da5gain cr75_da5gain; + + /* CR76 */ + t_ab8500_codec_cr76_fadedis_da6 cr76_fadedis_da6; + t_ab8500_codec_cr76_da6gain cr76_da6gain; + + /* CR77 */ + t_ab8500_codec_cr77_fadedis_ad1l cr77_fadedis_ad1l; + t_ab8500_codec_cr77_ad1lbgain_to_hfl cr77_ad1lbgain_to_hfl; + + /* CR78 */ + t_ab8500_codec_cr78_fadedis_ad2l cr78_fadedis_ad2l; + t_ab8500_codec_cr78_ad2lbgain_to_hfr cr78_ad2lbgain_to_hfr; + + /* CR79 */ + t_ab8500_codec_cr79_hssinc1 cr79_hssinc1; + t_ab8500_codec_cr79_fadedis_hsl cr79_fadedis_hsl; + t_ab8500_codec_cr79_hsldgain cr79_hsldgain; + + /* CR80 */ + t_ab8500_codec_cr80_fade_speed cr80_fade_speed; + t_ab8500_codec_cr80_fadedis_hsr cr80_fadedis_hsr; + t_ab8500_codec_cr80_hsrdgain cr80_hsrdgain; + + /* CR81 */ + t_ab8500_codec_cr81_stfir1gain cr81_stfir1gain; + + /* CR82 */ + t_ab8500_codec_cr82_stfir2gain cr82_stfir2gain; + + /* CR83 */ + t_ab8500_codec_cr83_enanc cr83_enanc; + t_ab8500_codec_cr83_anciirinit cr83_anciirinit; + t_ab8500_codec_cr83_ancfirupdate cr83_ancfirupdate; + + /* CR84 */ + t_ab8500_codec_cr84_ancinshift cr84_ancinshift; + + /* CR85 */ + t_ab8500_codec_cr85_ancfiroutshift cr85_ancfiroutshift; + + /* CR86 */ + t_ab8500_codec_cr86_ancshiftout cr86_ancshiftout; + + /* CR87 */ + t_ab8500_codec_cr87_ancfircoeff_msb cr87_ancfircoeff_msb; + + /* CR88 */ + t_ab8500_codec_cr88_ancfircoeff_lsb cr88_ancfircoeff_lsb; + + /* CR89 */ + t_ab8500_codec_cr89_anciircoeff_msb cr89_anciircoeff_msb; + + /* CR90 */ + t_ab8500_codec_cr90_anciircoeff_lsb cr90_anciircoeff_lsb; + + /* CR91 */ + t_ab8500_codec_cr91_ancwarpdel_msb cr91_ancwarpdel_msb; + + /* CR92 */ + t_ab8500_codec_cr92_ancwarpdel_lsb cr92_ancwarpdel_lsb; + + /* CR93 */ + t_ab8500_codec_cr93_ancfirpeak_msb cr93_ancfirpeak_msb; + + /* CR94 */ + t_ab8500_codec_cr94_ancfirpeak_lsb cr94_ancfirpeak_lsb; + + /* CR95 */ + t_ab8500_codec_cr95_anciirpeak_msb cr95_anciirpeak_msb; + + /* CR96 */ + t_ab8500_codec_cr96_anciirpeak_lsb cr96_anciirpeak_lsb; + + /* CR97 */ + t_ab8500_codec_cr97_stfir_set cr97_stfir_set; + t_ab8500_codec_cr97_stfir_addr cr97_stfir_addr; + + /* CR98 */ + t_ab8500_codec_cr98_stfir_coeff_msb cr98_stfir_coeff_msb; + + /* CR99 */ + t_ab8500_codec_cr99_stfir_coeff_lsb cr99_stfir_coeff_lsb; + + /* CR100 */ + t_ab8500_codec_cr100_enstfirs cr100_enstfirs; + t_ab8500_codec_cr100_stfirstoif1 cr100_stfirstoif1; + t_ab8500_codec_cr100_stfir_busy cr100_stfir_busy; + + /* CR101 */ + t_ab8500_codec_cr101_hsoffst_mask cr101_hsoffst_mask; + t_ab8500_codec_cr101_fifofull_mask cr101_fifofull_mask; + t_ab8500_codec_cr101_fifoempty_mask cr101_fifoempty_mask; + t_ab8500_codec_cr101_dasat_mask cr101_dasat_mask; + t_ab8500_codec_cr101_adsat_mask cr101_adsat_mask; + t_ab8500_codec_cr101_addsp_mask cr101_addsp_mask; + t_ab8500_codec_cr101_dadsp_mask cr101_dadsp_mask; + t_ab8500_codec_cr101_firsid_mask cr101_firsid_mask; + + /* CR102 */ + t_ab8500_codec_cr102_it_hsoffst cr102_it_hsoffst; + t_ab8500_codec_cr102_it_fifofull cr102_it_fifofull; + t_ab8500_codec_cr102_it_fifoempty cr102_it_fifoempty; + t_ab8500_codec_cr102_it_dasat cr102_it_dasat; + t_ab8500_codec_cr102_it_adsat cr102_it_adsat; + t_ab8500_codec_cr102_it_addsp cr102_it_addsp; + t_ab8500_codec_cr102_it_dadsp cr102_it_dadsp; + t_ab8500_codec_cr102_it_firsid cr102_it_firsid; + + /* CR103 */ + t_ab8500_codec_cr103_vssready_mask cr103_vssready_mask; + t_ab8500_codec_cr103_shorthsl_mask cr103_shorthsl_mask; + t_ab8500_codec_cr103_shorthsr_mask cr103_shorthsr_mask; + t_ab8500_codec_cr103_shortear_mask cr103_shortear_mask; + + /* CR104 */ + t_ab8500_codec_cr104_it_vssready cr104_it_vssready; + t_ab8500_codec_cr104_it_shorthsl cr104_it_shorthsl; + t_ab8500_codec_cr104_it_shorthsr cr104_it_shorthsr; + t_ab8500_codec_cr104_it_shortear cr104_it_shortear; + + /* CR105 */ + t_ab8500_codec_cr105_bfifomsk cr105_bfifomsk; + t_ab8500_codec_cr105_bfifoint cr105_bfifoint; + + /* CR106 */ + t_ab8500_codec_cr106_bfifotx cr106_bfifotx; + + /* CR107 */ + t_ab8500_codec_cr107_bfifoexsl cr107_bfifoexsl; + t_ab8500_codec_cr107_prebitclk0 cr107_prebitclk0; + t_ab8500_codec_cr107_bfifomast cr107_bfifomast; + t_ab8500_codec_cr107_bfiforun cr107_bfiforun; + + /* CR108 */ + t_ab8500_codec_cr108_bfifoframsw cr108_bfifoframsw; + + /* CR109 */ + t_ab8500_codec_cr109_bfifowakeup cr109_bfifowakeup; + + /* CR110 */ + t_ab8500_codec_cr110_bfifosamples cr110_bfifosamples; + + /* CR111 */ + t_ab8500_codec_cr111_aud_ip_rev cr111_aud_ip_rev; + +} t_ab8500_codec_configuration; + +typedef enum { + AB8500_CODEC_DIRECTION_IN, + AB8500_CODEC_DIRECTION_OUT, + AB8500_CODEC_DIRECTION_INOUT +} t_ab8500_codec_direction; + +typedef enum { + AB8500_CODEC_AUDIO_INTERFACE_0, + AB8500_CODEC_AUDIO_INTERFACE_1 +} t_ab8500_codec_audio_interface; + +typedef enum { + AB8500_CODEC_MODE_HIFI, + AB8500_CODEC_MODE_VOICE, + AB8500_CODEC_MODE_MANUAL_SETTING +} t_ab8500_codec_mode; + +typedef enum { + AB8500_CODEC_DEST_HEADSET, + AB8500_CODEC_DEST_EARPIECE, + AB8500_CODEC_DEST_HANDSFREE, + AB8500_CODEC_DEST_VIBRATOR_L, + AB8500_CODEC_DEST_VIBRATOR_R, + AB8500_CODEC_DEST_FM_TX, + AB8500_CODEC_DEST_ALL +} t_ab8500_codec_dest; + +typedef enum { + AB8500_CODEC_SRC_LINEIN, + AB8500_CODEC_SRC_MICROPHONE_1A, + AB8500_CODEC_SRC_MICROPHONE_1B, + AB8500_CODEC_SRC_MICROPHONE_2, + AB8500_CODEC_SRC_D_MICROPHONE_1, + AB8500_CODEC_SRC_D_MICROPHONE_2, + AB8500_CODEC_SRC_D_MICROPHONE_3, + AB8500_CODEC_SRC_D_MICROPHONE_4, + AB8500_CODEC_SRC_D_MICROPHONE_5, + AB8500_CODEC_SRC_D_MICROPHONE_6, + AB8500_CODEC_SRC_D_MICROPHONE_12, + AB8500_CODEC_SRC_D_MICROPHONE_34, + AB8500_CODEC_SRC_D_MICROPHONE_56, + AB8500_CODEC_SRC_FM_RX, + AB8500_CODEC_SRC_ALL +} t_ab8500_codec_src; + +typedef struct { + t_uint8 slave_address_of_ab8500_codec; + t_ab8500_codec_direction ab8500_codec_direction; + t_ab8500_codec_mode ab8500_codec_mode_in; + t_ab8500_codec_mode ab8500_codec_mode_out; + t_ab8500_codec_audio_interface audio_interface; + t_ab8500_codec_src ab8500_codec_src; + t_ab8500_codec_dest ab8500_codec_dest; + t_uint8 in_left_volume; + t_uint8 in_right_volume; + t_uint8 out_left_volume; + t_uint8 out_right_volume; + + t_ab8500_codec_configuration ab8500_codec_configuration; +} t_ab8500_codec_system_context; + +#endif /* _AB8500_CODECP_H_ */ + +/* End of file AB8500_CODECP.h */ diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h b/arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h new file mode 100644 index 00000000000..a5b8a57f341 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h @@ -0,0 +1,329 @@ +/*****************************************************************************/ +/** +* © ST-Ericsson, 2009 - All rights reserved +* Reproduction and Communication of this document is strictly prohibited +* unless specifically authorized in writing by ST-Ericsson +* +* \brief Public header file for AB8500 Codec +* \author ST-Ericsson +*/ +/*****************************************************************************/ + +#ifndef _AB8500_CODEC_V1_0_H_ +#define _AB8500_CODEC_V1_0_H_ + +/*--------------------------------------------------------------------- + * Includes + *--------------------------------------------------------------------*/ +#include "hcl_defs.h" +#include "debug.h" +#include +/*--------------------------------------------------------------------- + * Define + *--------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { + AB8500_CODEC_OK, + AB8500_CODEC_ERROR, + AB8500_CODEC_UNSUPPORTED_FEATURE, + AB8500_CODEC_INVALID_PARAMETER, + AB8500_CODEC_CONFIG_NOT_COHERENT, + AB8500_CODEC_TRANSACTION_FAILED + } t_ab8500_codec_error; + + typedef enum { + AB8500_CODEC_SRC_STATE_DISABLE, + AB8500_CODEC_SRC_STATE_ENABLE + } t_ab8500_codec_src_state; + + typedef enum { + AB8500_CODEC_DEST_STATE_DISABLE, + AB8500_CODEC_DEST_STATE_ENABLE + } t_ab8500_codec_dest_state; + + typedef enum { + AB8500_CODEC_MASTER_MODE_DISABLE, + AB8500_CODEC_MASTER_MODE_ENABLE + } t_ab8500_codec_master_mode; + + typedef enum { + AB8500_CODEC_SLOT0, + AB8500_CODEC_SLOT1, + AB8500_CODEC_SLOT2, + AB8500_CODEC_SLOT3, + AB8500_CODEC_SLOT4, + AB8500_CODEC_SLOT5, + AB8500_CODEC_SLOT6, + AB8500_CODEC_SLOT7, + AB8500_CODEC_SLOT8, + AB8500_CODEC_SLOT9, + AB8500_CODEC_SLOT10, + AB8500_CODEC_SLOT11, + AB8500_CODEC_SLOT12, + AB8500_CODEC_SLOT13, + AB8500_CODEC_SLOT14, + AB8500_CODEC_SLOT15, + AB8500_CODEC_SLOT16, + AB8500_CODEC_SLOT17, + AB8500_CODEC_SLOT18, + AB8500_CODEC_SLOT19, + AB8500_CODEC_SLOT20, + AB8500_CODEC_SLOT21, + AB8500_CODEC_SLOT22, + AB8500_CODEC_SLOT23, + AB8500_CODEC_SLOT24, + AB8500_CODEC_SLOT25, + AB8500_CODEC_SLOT26, + AB8500_CODEC_SLOT27, + AB8500_CODEC_SLOT28, + AB8500_CODEC_SLOT29, + AB8500_CODEC_SLOT30, + AB8500_CODEC_SLOT31, + AB8500_CODEC_SLOT_UNDEFINED + } t_ab8500_codec_slot; + + typedef enum { + AB8500_CODEC_DA_CHANNEL_NUMBER_1, + AB8500_CODEC_DA_CHANNEL_NUMBER_2, + AB8500_CODEC_DA_CHANNEL_NUMBER_3, + AB8500_CODEC_DA_CHANNEL_NUMBER_4, + AB8500_CODEC_DA_CHANNEL_NUMBER_5, + AB8500_CODEC_DA_CHANNEL_NUMBER_6, + AB8500_CODEC_DA_CHANNEL_NUMBER_7, + AB8500_CODEC_DA_CHANNEL_NUMBER_8, + AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED + } t_ab8500_codec_da_channel_number; + + typedef struct { + t_ab8500_codec_cr105_bfifomsk cr105_bfifomsk; + t_ab8500_codec_cr105_bfifoint cr105_bfifoint; + t_ab8500_codec_cr106_bfifotx cr106_bfifotx; + t_ab8500_codec_cr107_bfifoexsl cr107_bfifoexsl; + t_ab8500_codec_cr107_prebitclk0 cr107_prebitclk0; + t_ab8500_codec_cr107_bfifomast cr107_bfifomast; + t_ab8500_codec_cr107_bfiforun cr107_bfiforun; + t_ab8500_codec_cr108_bfifoframsw cr108_bfifoframsw; + t_ab8500_codec_cr109_bfifowakeup cr109_bfifowakeup; + } t_ab8500_codec_burst_fifo_config; + + typedef struct { + t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr; + t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr; + t_ab8500_codec_cr28_if0wl cr28_if0wl; + t_ab8500_codec_cr30_if1wl cr30_if1wl; + t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p; + t_ab8500_codec_cr28_if0del cr28_if0del; + } t_ab8500_codec_tdm_config; + +/************************************************************/ +/*--------------------------------------------------------------------- + * Exported APIs + *--------------------------------------------------------------------*/ +/* Initialization */ + t_ab8500_codec_error AB8500_CODEC_Init(IN t_uint8 + slave_address_of_codec); + t_ab8500_codec_error AB8500_CODEC_Reset(void); + +/* Audio Codec basic configuration */ + t_ab8500_codec_error AB8500_CODEC_SetModeAndDirection(IN + t_ab8500_codec_direction + ab8500_codec_direction, + IN + t_ab8500_codec_mode + ab8500_codec_mode_in, + IN + t_ab8500_codec_mode + ab8500_codec_mode_out, + IN + t_ab8500_codec_tdm_config + const *const + p_tdm_config); + t_ab8500_codec_error AB8500_CODEC_SelectInput(IN t_ab8500_codec_src + ab8500_codec_src); + t_ab8500_codec_error AB8500_CODEC_SelectOutput(IN t_ab8500_codec_dest + ab8500_codec_dest); + +/* Burst FIFO configuration */ + t_ab8500_codec_error AB8500_CODEC_ConfigureBurstFifo(IN + t_ab8500_codec_burst_fifo_config + const *const + p_burst_fifo_config); + t_ab8500_codec_error AB8500_CODEC_EnableBurstFifo(void); + t_ab8500_codec_error AB8500_CODEC_DisableBurstFifo(void); + +/* Audio Codec Master mode configuration */ + t_ab8500_codec_error AB8500_CODEC_SetMasterMode(IN + t_ab8500_codec_master_mode + mode); + +/* APIs to be implemented by user */ + t_ab8500_codec_error AB8500_CODEC_Write(IN t_uint8 register_offset, + IN t_uint8 count, + IN t_uint8 * p_data); + t_ab8500_codec_error AB8500_CODEC_Read(IN t_uint8 register_offset, + IN t_uint8 count, + IN t_uint8 * p_dummy_data, + IN t_uint8 * p_data); + +/* Volume Management */ + t_ab8500_codec_error AB8500_CODEC_SetSrcVolume(IN t_ab8500_codec_src + src_device, + IN t_uint8 + in_left_volume, + IN t_uint8 + in_right_volume); + t_ab8500_codec_error AB8500_CODEC_SetDestVolume(IN t_ab8500_codec_dest + dest_device, + IN t_uint8 + out_left_volume, + IN t_uint8 + out_right_volume); + +/* Power management */ + t_ab8500_codec_error AB8500_CODEC_PowerDown(void); + t_ab8500_codec_error AB8500_CODEC_PowerUp(void); + +/* Interface Management */ + t_ab8500_codec_error AB8500_CODEC_SelectInterface(IN + t_ab8500_codec_audio_interface + audio_interface); + t_ab8500_codec_error AB8500_CODEC_GetInterface(OUT + t_ab8500_codec_audio_interface + * p_audio_interface); + +/* Slot Allocation */ + t_ab8500_codec_error AB8500_CODEC_ADSlotAllocation(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); + t_ab8500_codec_error AB8500_CODEC_DASlotAllocation(IN + t_ab8500_codec_da_channel_number + channel_number, + IN + t_ab8500_codec_cr51_to_cr58_sltoda + slot); + +/* Loopback Management */ + t_ab8500_codec_error AB8500_CODEC_SetAnalogLoopback(IN t_uint8 + out_left_volume, + IN t_uint8 + out_right_volume); + t_ab8500_codec_error AB8500_CODEC_RemoveAnalogLoopback(void); + +/* Bypass Management */ + t_ab8500_codec_error AB8500_CODEC_EnableBypassMode(void); + t_ab8500_codec_error AB8500_CODEC_DisableBypassMode(void); + +/* Power Control Management */ + t_ab8500_codec_error AB8500_CODEC_SrcPowerControl(IN t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state); + t_ab8500_codec_error AB8500_CODEC_DestPowerControl(IN + t_ab8500_codec_dest + dest_device, + t_ab8500_codec_dest_state + state); + +/* Version Management */ + t_ab8500_codec_error AB8500_CODEC_GetVersion(OUT t_version * p_version); + +#if 0 +/* Debug management */ + t_ab8500_codec_error AB8500_CODEC_SetDbgLevel(IN t_dbg_level dbg_level); + t_ab8500_codec_error AB8500_CODEC_GetDbgLevel(OUT t_dbg_level * + p_dbg_level); +#endif + +/* +** following is added by $kardad$ +*/ + +/* duplicate copy of enum from msp.h */ +/* for MSPConfiguration.in_clock_freq parameter to select msp clock freq */ + typedef enum { + CODEC_MSP_INPUT_FREQ_1MHZ = 1024, + CODEC_MSP_INPUT_FREQ_2MHZ = 2048, + CODEC_MSP_INPUT_FREQ_3MHZ = 3072, + CODEC_MSP_INPUT_FREQ_4MHZ = 4096, + CODEC_MSP_INPUT_FREQ_5MHZ = 5760, + CODEC_MSP_INPUT_FREQ_6MHZ = 6144, + CODEC_MSP_INPUT_FREQ_8MHZ = 8192, + CODEC_MSP_INPUT_FREQ_11MHZ = 11264, + CODEC_MSP_INPUT_FREQ_12MHZ = 12288, + CODEC_MSP_INPUT_FREQ_16MHZ = 16384, + CODEC_MSP_INPUT_FREQ_22MHZ = 22579, + CODEC_MSP_INPUT_FREQ_24MHZ = 24576, + CODEC_MSP_INPUT_FREQ_48MHZ = 49152 + } codec_msp_in_clock_freq_type; + +/* msp clock source internal/external for srg_clock_sel */ + typedef enum { + CODEC_MSP_APB_CLOCK = 0, + CODEC_MSP_SCK_CLOCK = 2, + CODEC_MSP_SCK_SYNC_CLOCK = 3 + } codec_msp_srg_clock_sel_type; + +/* Sample rate supported by Codec */ + + typedef enum { + CODEC_FREQUENCY_DONT_CHANGE = -100, + CODEC_SAMPLING_FREQ_RESET = -1, + CODEC_SAMPLING_FREQ_MINLIMIT = 7, + CODEC_SAMPLING_FREQ_8KHZ = 8, /*default */ + CODEC_SAMPLING_FREQ_11KHZ = 11, + CODEC_SAMPLING_FREQ_12KHZ = 12, + CODEC_SAMPLING_FREQ_16KHZ = 16, + CODEC_SAMPLING_FREQ_22KHZ = 22, + CODEC_SAMPLING_FREQ_24KHZ = 24, + CODEC_SAMPLING_FREQ_32KHZ = 32, + CODEC_SAMPLING_FREQ_44KHZ = 44, + CODEC_SAMPLING_FREQ_48KHZ = 48, + CODEC_SAMPLING_FREQ_64KHZ = 64, /*the frequencies below this line are not supported in stw5094A */ + CODEC_SAMPLING_FREQ_88KHZ = 88, + CODEC_SAMPLING_FREQ_96KHZ = 96, + CODEC_SAMPLING_FREQ_128KHZ = 128, + CODEC_SAMPLING_FREQ_176KHZ = 176, + CODEC_SAMPLING_FREQ_192KHZ = 192, + CODEC_SAMPLING_FREQ_MAXLIMIT = 193 + } t_codec_sample_frequency; + +#define RESET -1 +#define DEFAULT -100 +/***********************************************************/ +/* +** following stuff is added to compile code without debug print support $kardad$ +*/ + +#define DBGEXIT(cr) +#define DBGEXIT0(cr) +#define DBGEXIT1(cr,ch,p1) +#define DBGEXIT2(cr,ch,p1,p2) +#define DBGEXIT3(cr,ch,p1,p2,p3) +#define DBGEXIT4(cr,ch,p1,p2,p3,p4) +#define DBGEXIT5(cr,ch,p1,p2,p3,p4,p5) +#define DBGEXIT6(cr,ch,p1,p2,p3,p4,p5,p6) + +#define DBGENTER() +#define DBGENTER0() +#define DBGENTER1(ch,p1) +#define DBGENTER2(ch,p1,p2) +#define DBGENTER3(ch,p1,p2,p3) +#define DBGENTER4(ch,p1,p2,p3,p4) +#define DBGENTER5(ch,p1,p2,p3,p4,p5) +#define DBGENTER6(ch,p1,p2,p3,p4,p5,p6) + +#define DBGPRINT(dbg_level,dbg_string) +#define DBGPRINTHEX(dbg_level,dbg_string,uint32) +#define DBGPRINTDEC(dbg_level,dbg_string,uint32) +/***********************************************************/ + +#ifdef __cplusplus +} /* allow C++ to use these headers */ +#endif /* __cplusplus */ +#endif /* _AB8500_CODEC_H_ */ +/* End of file ab8500_codec.h*/ diff --git a/arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h b/arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h new file mode 100644 index 00000000000..0575bbdb730 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h @@ -0,0 +1,284 @@ +/* Header file for u8500 audiocodec specific data structures, enums + * and private & public functions. + * Author: Deepak Karda + * Copyright (C) 2009 ST-Ericsson Pvt. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _U8500_ACODEC_AB8500_H_ +#define _U8500_ACODEC_AB8500_H_ + +#include +#include + +#ifdef CONFIG_U8500_AB8500_CUT10 +#include +//#include +#else /*CONFIG_U8500_4500_ED */ +#include +#include +#endif + +#define NUMBER_OUTPUT_DEVICE 5 +#define NUMBER_INPUT_DEVICE 13 +#define NUMBER_LOOPBACK_STATE 2 +#define NUMBER_SWITCH_STATE 2 +#define NUMBER_POWER_STATE 2 +#define NUMBER_TDM_MODE_STATE 2 +#define NUMBER_DIRECT_RENDERING_STATE 2 +#define NUMBER_PCM_RENDERING_STATE 3 + +#define CODEC_MUTE 0x20 +#define DEFAULT_VOLUME 0x64 +#define DEFAULT_GAIN 0x32 +#define VOL_MAX 0x64 +#define VOL_MIN 0x00 +#define DEFAULT_OUTPUT_DEVICE AB8500_CODEC_DEST_HEADSET +#define DEFAULT_INPUT_DEVICE AB8500_CODEC_SRC_D_MICROPHONE_1 +#define DEFAULT_LOOPBACK_STATE DISABLE +#define DEFAULT_SWITCH_STATE DISABLE +#define DEFAULT_TDM8_CH_MODE_STATE DISABLE +#define DEFAULT_DIRECT_RENDERING_STATE DISABLE +#define DEFAULT_BURST_FIFO_STATE RENDERING_DISABLE +#define DEFAULT_FM_PLAYBACK_STATE RENDERING_DISABLE +#define DEFAULT_FM_TX_STATE RENDERING_DISABLE + +#define MIN_RATE_PLAYBACK 48000 +#define MAX_RATE_PLAYBACK 48000 +#define MIN_RATE_CAPTURE 48000 +#define MAX_RATE_CAPTURE 48000 +#define MAX_NO_OF_RATES 1 + +#define ALSA_MSP_BT_NUM 0 +#define ALSA_MSP_PCM_NUM 1 +#define ALSA_MSP_HDMI_NUM 2 + +#define I2S_CLIENT_MSP0 0 +#define I2S_CLIENT_MSP1 1 +#define I2S_CLIENT_MSP2 2 + +typedef enum { + DISABLE, + ENABLE +} t_u8500_bool_state; + +typedef enum { + RENDERING_DISABLE, + RENDERING_ENABLE, + RENDERING_PENDING +} t_u8500_pmc_rendering_state; + +typedef enum { + ACODEC_CONFIG_REQUIRED, + ACODEC_CONFIG_NOT_REQUIRED +} t_u8500_acodec_config_need; + +typedef enum { + CLASSICAL_MODE, + TDM_8_CH_MODE +} t_u8500_mode; + +typedef struct { + unsigned int left_volume; + unsigned int right_volume; + unsigned int mute_state; + t_u8500_bool_state power_state; +} u8500_io_dev_config_t; + +typedef enum { + NO_USER = 0, + USER_ALSA = 2, /*To make it equivalent to user id for MSP */ + USER_SAA, +} t_acodec_user; + +typedef struct { + u8500_io_dev_config_t output_config[NUMBER_OUTPUT_DEVICE]; + u8500_io_dev_config_t input_config[NUMBER_INPUT_DEVICE]; + //t_acodec_user user; + t_acodec_user cur_user; +} t_u8500_codec_system_context; + +typedef enum { + T_CODEC_SAMPLING_FREQ_48KHZ = 48, +} acodec_sample_frequency; + +struct acodec_configuration { + t_ab8500_codec_direction direction; + acodec_sample_frequency input_frequency; + acodec_sample_frequency output_frequency; + codec_msp_srg_clock_sel_type mspClockSel; + codec_msp_in_clock_freq_type mspInClockFreq; + u32 channels; + t_acodec_user user; + t_u8500_acodec_config_need acodec_config_need; + t_u8500_bool_state direct_rendering_mode; + t_u8500_bool_state tdm8_ch_mode; + t_u8500_bool_state digital_loopback; + void (*handler) (void *data); + void *tx_callback_data; + void *rx_callback_data; +}; + +typedef enum { + ACODEC_DISABLE_ALL, + ACODEC_DISABLE_TRANSMIT, + ACODEC_DISABLE_RECEIVE, +} t_acodec_disable; + +struct i2sdrv_data { + struct i2s_device *i2s; + spinlock_t i2s_lock; + /* buffer is NULL unless this device is open (users > 0) */ + int flag; + u32 tx_status; + u32 rx_status; +}; + +#define MAX_I2S_CLIENTS 3 //0=BT, 1=ACODEC, 2=HDMI + +/*extern t_ab8500_codec_error u8500_acodec_set_volume(int input_vol_left, + int input_vol_right, + int output_vol_left, + int output_vol_right, t_acodec_user user);*/ + +extern t_ab8500_codec_error u8500_acodec_open(int client_id, int stream_id); +//extern t_ab8500_codec_error u8500_acodec_pause_transfer(void); +//extern t_ab8500_codec_error u8500_acodec_unpause_transfer(void); +extern t_ab8500_codec_error u8500_acodec_send_data(int client_id, void *data, + size_t bytes, int dma_flag); +extern t_ab8500_codec_error u8500_acodec_receive_data(int client_id, void *data, + size_t bytes, + int dma_flag); +extern t_ab8500_codec_error u8500_acodec_close(int client_id, + t_acodec_disable flag); +extern t_ab8500_codec_error u8500_acodec_tx_rx_data(int client_id, + void *tx_data, + size_t tx_bytes, + void *rx_data, + size_t rx_bytes, + int dma_flag); + +extern t_ab8500_codec_error u8500_acodec_set_output_volume(t_ab8500_codec_dest + dest_device, + int left_volume, + int right_volume, + t_acodec_user user); + +extern t_ab8500_codec_error u8500_acodec_get_output_volume(t_ab8500_codec_dest + dest_device, + int *p_left_volume, + int *p_right_volume, + t_acodec_user user); + +extern t_ab8500_codec_error u8500_acodec_set_input_volume(t_ab8500_codec_src + src_device, + int left_volume, + int right_volume, + t_acodec_user user); + +extern t_ab8500_codec_error u8500_acodec_get_input_volume(t_ab8500_codec_src + src_device, + int *p_left_volume, + int *p_right_volume, + t_acodec_user user); + +extern t_ab8500_codec_error u8500_acodec_toggle_analog_lpbk(t_u8500_bool_state + lpbk_state, + t_acodec_user user); + +extern t_ab8500_codec_error u8500_acodec_toggle_digital_lpbk(t_u8500_bool_state + lpbk_state, + t_ab8500_codec_dest + dest_device, + t_ab8500_codec_src + src_device, + t_acodec_user user, + t_u8500_bool_state + tdm8_ch_mode); + +extern t_ab8500_codec_error +u8500_acodec_toggle_playback_mute_control(t_ab8500_codec_dest dest_device, + t_u8500_bool_state mute_state, + t_acodec_user user); +extern t_ab8500_codec_error +u8500_acodec_toggle_capture_mute_control(t_ab8500_codec_src src_device, + t_u8500_bool_state mute_state, + t_acodec_user user); + +extern t_ab8500_codec_error u8500_acodec_enable_audio_mode(struct + acodec_configuration + *acodec_config); +/*extern t_ab8500_codec_error u8500_acodec_enable_voice_mode(struct acodec_configuration *acodec_config);*/ + +extern t_ab8500_codec_error u8500_acodec_select_input(t_ab8500_codec_src + input_device, + t_acodec_user user, + t_u8500_mode mode); +extern t_ab8500_codec_error u8500_acodec_select_output(t_ab8500_codec_dest + output_device, + t_acodec_user user, + t_u8500_mode mode); + +extern t_ab8500_codec_error u8500_acodec_allocate_ad_slot(t_ab8500_codec_src + input_device, + t_u8500_mode mode); +extern t_ab8500_codec_error u8500_acodec_unallocate_ad_slot(t_ab8500_codec_src + input_device, + t_u8500_mode mode); +extern t_ab8500_codec_error u8500_acodec_allocate_da_slot(t_ab8500_codec_dest + output_device, + t_u8500_mode mode); +extern t_ab8500_codec_error u8500_acodec_unallocate_da_slot(t_ab8500_codec_dest + output_device, + t_u8500_mode mode); + +extern t_ab8500_codec_error u8500_acodec_set_src_power_cntrl(t_ab8500_codec_src + input_device, + t_u8500_bool_state + pwr_state); +extern t_ab8500_codec_error +u8500_acodec_set_dest_power_cntrl(t_ab8500_codec_dest output_device, + t_u8500_bool_state pwr_state); + +extern t_u8500_bool_state u8500_acodec_get_src_power_state(t_ab8500_codec_src + input_device); +extern t_u8500_bool_state u8500_acodec_get_dest_power_state(t_ab8500_codec_dest + output_device); +extern t_ab8500_codec_error +u8500_acodec_set_burst_mode_fifo(t_u8500_pmc_rendering_state fifo_state); + +extern t_ab8500_codec_error u8500_acodec_unsetuser(t_acodec_user user); +extern t_ab8500_codec_error u8500_acodec_setuser(t_acodec_user user); + +extern void codec_power_init(void); +extern void u8500_acodec_powerdown(void); + +//t_ab8500_codec_error acodec_msp_enable(t_touareg_codec_sample_frequency freq,int channels, t_acodec_user user); + +#define TRG_CODEC_ADDRESS_ON_SPI_BUS (0x0D) + +extern int ab8500_write(u8 block, u32 adr, u8 data); +extern int ab8500_read(u8 block, u32 adr); + +#if 0 +#define FUNC_ENTER() printk("\n -Enter : %s",__FUNCTION__) +#define FUNC_EXIT() printk("\n -Exit : %s",__FUNCTION__) +#else +#define FUNC_ENTER() +#define FUNC_EXIT() +#endif +#endif /*END OF HEADSER FILE */ diff --git a/sound/Kconfig b/sound/Kconfig index 261a03c8a20..fafe6f58eeb 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -23,6 +23,46 @@ menuconfig SOUND and read ; the module will be called soundcore. +# added for U8500 audio codec device +config U8500_ACODEC + tristate "U8500 audio codec generic module (used both by SAA and ALSA)" + depends on STM_MSP_I2S + default Y + help + Say Y here if you have a U8500 based device + and want to use its audio codec chip. + + To compile this driver as a module, choose M here: the module + will be called u8500mod_acodec. + +choice + prompt "Audio codec type" + depends on U8500_ACODEC + default U8500_AB8500_ED + + config U8500_AB8500_ED + bool "U8500 ab8500 v0 audio codec" + + config U8500_AB8500_CUT10 + bool "U8500 ab8500 v1.x audio codec" + +endchoice + +choice + prompt "Driver mode" + depends on U8500_ACODEC + default U8500_ACODEC_DMA + + config U8500_ACODEC_DMA + bool "DMA mode" + + config U8500_ACODEC_POLL + bool "Polling mode" + + config U8500_ACODEC_INTR + bool "Interrupt mode" +endchoice + if SOUND config SOUND_OSS_CORE diff --git a/sound/Makefile b/sound/Makefile index ce9132b1c39..b5963c8b70d 100644 --- a/sound/Makefile +++ b/sound/Makefile @@ -16,4 +16,11 @@ ifeq ($(CONFIG_SND),y) obj-y += last.o endif +obj-$(CONFIG_U8500_ACODEC) += u8500mod_acodec.o +ifeq ($(CONFIG_U8500_AB8500_CUT10),y) + u8500mod_acodec-objs := u8500_acodec_ab8500.o ab8500_codec_v1_0.o +else + u8500mod_acodec-objs := u8500_acodec_ab8500.o ab8500_codec.o +endif + soundcore-objs := sound_core.o diff --git a/sound/ab8500_codec.c b/sound/ab8500_codec.c new file mode 100644 index 00000000000..fd4975bbdce --- /dev/null +++ b/sound/ab8500_codec.c @@ -0,0 +1,6697 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: ST-Ericsson + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + + /*---------------------------------------------------------------------------- + * Includes + *---------------------------------------------------------------------------*/ +#include +#include + +/*--------------------------------------------------------------------------* + * debug stuff * + *--------------------------------------------------------------------------*/ +#ifdef __DEBUG +#define MY_DEBUG_LEVEL_VAR_NAME myDebugLevel_AB8500_CODEC +#define MY_DEBUG_ID myDebugID_AB8500_CODEC +PRIVATE t_dbg_level MY_DEBUG_LEVEL_VAR_NAME = DEBUG_LEVEL0; +PRIVATE t_dbg_id MY_DEBUG_ID = AB8500_CODEC_HCL_DBG_ID; +#endif + +/*--------------------------------------------------------------------------* + * Global data for interrupt mode management * + *--------------------------------------------------------------------------*/ +PRIVATE t_ab8500_codec_system_context g_ab8500_codec_system_context; + +/*--------------------------------------------------------------------------* + * Default Values * + *--------------------------------------------------------------------------*/ +#define AB8500_CODEC_DEFAULT_SLAVE_ADDRESS_OF_CODEC 0xD +#define AB8500_CODEC_DEFAULT_DIRECTION AB8500_CODEC_DIRECTION_OUT + +#define AB8500_CODEC_DEFAULT_MODE_IN AB8500_CODEC_MODE_VOICE +#define AB8500_CODEC_DEFAULT_MODE_OUT AB8500_CODEC_MODE_VOICE + +#define AB8500_CODEC_DEFAULT_INPUT_SRC AB8500_CODEC_SRC_MICROPHONE_1A +#define AB8500_CODEC_DEFAULT_OUTPUT_DEST AB8500_CODEC_DEST_HEADSET + +#define AB8500_CODEC_DEFAULT_VOLUME_LEFT_IN 75 +#define AB8500_CODEC_DEFAULT_VOLUME_RIGHT_IN 75 +#define AB8500_CODEC_DEFAULT_VOLUME_LEFT_OUT 75 +#define AB8500_CODEC_DEFAULT_VOLUME_RIGHT_OUT 75 + +/*--------------------------------------------------------------------- + * PRIVATE APIs + *--------------------------------------------------------------------*/ +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch1(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch2(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch3(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch4(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch1(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state); +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch2(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state); +PRIVATE t_ab8500_codec_error ab8500_codec_SetModeAndDirectionUpdateCR(void); +PRIVATE t_ab8500_codec_error ab8500_codec_SetSrcVolumeUpdateCR(void); +PRIVATE t_ab8500_codec_error ab8500_codec_SetDestVolumeUpdateCR(void); +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionIN(void); +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionOUT(void); +PRIVATE t_ab8500_codec_error ab8500_codec_DestPowerControlUpdateCR(void); + +/********************************************************************************************/ +/* Name: ab8500_codec_SingleWrite */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_SingleWrite(t_uint8 register_offset, + t_uint8 data) +{ + return (t_ab8500_codec_error) (AB8500_CODEC_Write + (register_offset, 0x01, &data)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_SingleRead */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_SingleRead(t_uint8 register_offset, + t_uint8 data) +{ + t_uint8 dummy_data = 0xAA; + + return (t_ab8500_codec_error) (AB8500_CODEC_Read + (register_offset, 0x01, &dummy_data, + &data)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR0 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR0(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr0_powerup, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR0_POWERUP); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr0_enaana, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR0_ENAANA); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR0, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR1 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR1(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr1_swreset, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR1_SWRESET); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR1, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR2 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR2(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr2_enad1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR2_ENAD1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr2_enad2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR2_ENAD2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr2_enad3, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR2_ENAD3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr2_enad4, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR2_ENAD4); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr2_enad5, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR2_ENAD5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr2_enad6, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR2_ENAD6); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR2, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR3 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR3(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr3_enda1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR3_ENDA1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr3_enda2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR3_ENDA2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr3_enda3, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR3_ENDA3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr3_enda4, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR3_ENDA4); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr3_enda5, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR3_ENDA5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr3_enda6, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR3_ENDA6); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR3, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR4 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR4(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr4_lowpowhs, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR4_LOWPOWHS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr4_lowpowdachs, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR4_LOWPOWDACHS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr4_lowpowear, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR4_LOWPOWEAR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr4_ear_sel_cm, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR4_EAR_SEL_CM); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr4_hs_hp_dis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR4_HS_HP_DIS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr4_ear_hp_dis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR4_EAR_HP_DIS); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR4, value)); +} +#endif + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR5 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR5(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_enmic1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_ENMIC1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_enmic2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_ENMIC2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_enlinl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_ENLINL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_enlinr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_ENLINR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_mutmic1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_MUTMIC1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_mutmic2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_MUTMIC2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_mutlinl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_MUTELINL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr5_mutlinr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR5_MUTELINR); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR5, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR6 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR6(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr6_endmic1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR6_ENDMIC1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr6_endmic2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR6_ENDMIC2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr6_endmic3, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR6_ENDMIC3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr6_endmic4, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR6_ENDMIC4); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr6_endmic5, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR6_ENDMIC5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr6_endmic6, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR6_ENDMIC6); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR6, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR7 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR7(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr7_mic1sel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR7_MIC1SEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr7_linrsel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR7_LINRSEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr7_endrvhsl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR7_ENDRVHSL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr7_endrvhsr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR7_ENDRVHSR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr7_enadcmic, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR7_ENADCMIC); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr7_enadclinl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR7_ENADCLINL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr7_enadclinr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR7_ENADCLINR); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR7, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR8 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR8(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_cp_dis_pldwn, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_CP_DIS_PLDWN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_enear, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_ENEAR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_enhsl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_ENHSL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_enhsr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_ENHSR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_enhfl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_ENHFL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_enhfr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_ENHFR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_envibl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_ENVIBL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr8_envibr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR8_ENVIBR); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR8, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR9 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR9(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr9_endacear, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR9_ENADACEAR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr9_endachsl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR9_ENADACHSL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr9_endachsr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR9_ENADACHSR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr9_endachfl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR9_ENADACHFL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr9_endachfr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR9_ENADACHFR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr9_endacvibl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR9_ENADACVIBL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr9_endacvibr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR9_ENADACVIBR); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR9, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR10 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR10(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr10_muteear, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR10_MUTEEAR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr10_mutehsl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR10_MUTEHSL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr10_mutehsr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR10_MUTEHSR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr10_mutehfl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR10_MUTEHFL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr10_mutehfr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR10_MUTEHFR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr10_mutevibl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR10_MUTEVIBL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr10_mutevibr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR10_MUTEVIBR); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR10, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR11 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR11(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_earshortpwd, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_ENSHORTPWD); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_earshortdis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_EARSHORTDIS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_hslshortdis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_HSLSHORTDIS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_hsrshortdis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_HSRSHORTDIS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_hflshortdis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_HFLSHORTDIS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_hfrshortdis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_HFRSHORTDIS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_viblshortdis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_VIBLSHORTDIS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr11_vibrshortdis, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR11_VIBRSHORTDIS); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR11, value)); +} + +#endif + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR12 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR12(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr12_encphs, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR12_ENCPHS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr12_hsautotime, + AB8500_CODEC_MASK_THREE_BITS, AB8500_CODEC_CR12_HSAUTOTIME); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr12_hsautoensel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR12_HSAUTOENSEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr12_hsautoen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR12_HSAUTOEN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR12, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR13 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR13(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr13_envdet_hthresh, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR13_ENVDET_HTHRESH); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr13_envdet_lthresh, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR13_ENVDET_LTHRESH); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR13, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR14 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR14(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr14_smpslven, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR14_SMPSLVEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr14_envdetsmpsen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR14_ENVDETSMPSEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr14_cplven, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR14_CPLVEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr14_envdetcpen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR14_ENVDETCPEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr14_envet_time, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR14_ENVDET_TIME); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR14, value)); +} +#endif + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR15 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR15(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmtovibl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMTOVIBL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmtovibr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMTOVIBR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmlctrl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMLCTRL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmrctrl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMRCTRL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmnlctrl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMNLCTRL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmplctrl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMPLCTRL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmnrctrl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMNRCTRL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr15_pwmprctrl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR15_PWMPRCTRL); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR15, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR16 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR16(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr16_pwmnlpol, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR16_PWMNLPOL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr16_pwmnldutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, AB8500_CODEC_CR16_PWMNLDUTYCYCLE); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR16, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR17 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR17(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr17_pwmplpol, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR17_PWMPLPOL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr17_pwmpldutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, AB8500_CODEC_CR17_PWMLPDUTYCYCLE); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR17, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR18 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR18(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr18_pwmnrpol, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR18_PWMNRPOL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr18_pwmnrdutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, AB8500_CODEC_CR18_PWMNRDUTYCYCLE); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR18, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR19 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR19(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr19_pwmprpol, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR19_PWMPRPOL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr19_pwmprdutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, AB8500_CODEC_CR19_PWMRPDUTYCYCLE); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR19, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR20 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR20(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr20_en_se_mic1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR20_EN_SE_MIC1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr20_mic1_gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR20_MIC1_GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR20, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR21 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR21(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr21_en_se_mic2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR21_EN_SE_MIC2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr21_mic2_gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR21_MIC2_GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR21, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR22 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR22(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr22_hsl_gain, + AB8500_CODEC_MASK_THREE_BITS, AB8500_CODEC_CR22_HSL_GAIN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr22_linl_gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR22_LINL_GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR22, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR23 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR23(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr23_hsr_gain, + AB8500_CODEC_MASK_THREE_BITS, AB8500_CODEC_CR23_HSR_GAIN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr23_linr_gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR23_LINR_GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR23, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR24 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR24(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr24_lintohsl_gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR24_LINTOHSL_GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR24, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR25 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR25(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr25_lintohsr_gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR25_LINTOHSR_GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR25, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR26 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR26(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad1nh, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD1NH); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad2nh, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD2NH); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad3nh, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD3NH); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad4nh, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD4NH); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad1_voice, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD1_VOICE); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad2_voice, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD2_VOICE); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad3_voice, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD3_VOICE); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr26_ad4_voice, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR26_AD4_VOICE); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR26, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR27 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR27(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr27_en_mastgen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR27_EN_MASTGEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr27_if1_bitclk_osr, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR27_IF1_BITCLK_OSR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr27_enfs_bitclk1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR27_ENFS_BITCLK1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr27_if0_bitclk_osr, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR27_IF0_BITCLK_OSR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr27_enfs_bitclk0, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR27_ENFS_BITCLK0); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR27, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR28 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR28(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr28_fsync0p, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR28_FSYNC0P); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr28_bitclk0p, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR28_BITCLK0P); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr28_if0del, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR28_IF0DEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr28_if0format, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR28_IF0FORMAT); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr28_if0wl, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR28_IF0WL); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR28, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR29 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR29(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr29_if0datoif1ad, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR29_IF0DATOIF1AD); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr29_if0cktoif1ck, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR29_IF0CKTOIF1CK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr29_if1master, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR29_IF1MASTER); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr29_if1datoif0ad, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR29_IF1DATOIF0AD); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr29_if1cktoif0ck, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR29_IF1CKTOIF0CK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr29_if0master, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR29_IF0MASTER); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr29_if0bfifoen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR29_IF0BFIFOEN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR29, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR30 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR30(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr30_fsync1p, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR30_FSYNC1P); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr30_bitclk1p, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR30_BITCLK1P); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr30_if1del, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR30_IF1DEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr30_if1format, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR30_IF1FORMAT); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr30_if1wl, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR30_IF1WL); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR30, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR31 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR31(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr31_adotoslot1, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR31_ADOTOSLOT1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr31_adotoslot0, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR31_ADOTOSLOT0); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR31, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR32 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR32(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr32_adotoslot3, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR32_ADOTOSLOT3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr32_adotoslot2, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR32_ADOTOSLOT2); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR32, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR33 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR33(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr33_adotoslot5, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR33_ADOTOSLOT5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr33_adotoslot4, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR33_ADOTOSLOT4); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR33, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR34 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR34(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr34_adotoslot7, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR34_ADOTOSLOT7); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr34_adotoslot6, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR34_ADOTOSLOT6); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR34, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR35 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR35(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr35_adotoslot9, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR35_ADOTOSLOT9); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr35_adotoslot8, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR35_ADOTOSLOT8); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR35, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR36 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR36(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr36_adotoslot11, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR36_ADOTOSLOT11); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr36_adotoslot10, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR36_ADOTOSLOT10); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR36, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR37 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR37(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr37_adotoslot13, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR37_ADOTOSLOT13); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr37_adotoslot12, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR37_ADOTOSLOT12); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR37, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR38 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR38(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr38_adotoslot15, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR38_ADOTOSLOT15); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr38_adotoslot14, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR38_ADOTOSLOT14); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR38, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR39 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR39(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr39_adotoslot17, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR39_ADOTOSLOT17); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr39_adotoslot16, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR39_ADOTOSLOT16); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR39, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR40 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR40(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr40_adotoslot19, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR40_ADOTOSLOT19); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr40_adotoslot18, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR40_ADOTOSLOT18); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR40, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR41 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR41(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr41_adotoslot21, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR41_ADOTOSLOT21); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr41_adotoslot20, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR41_ADOTOSLOT20); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR41, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR42 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR42(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr42_adotoslot23, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR42_ADOTOSLOT23); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr42_adotoslot22, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR42_ADOTOSLOT22); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR42, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR43 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR43(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr43_adotoslot25, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR43_ADOTOSLOT25); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr43_adotoslot24, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR43_ADOTOSLOT24); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR43, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR44 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR44(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr44_adotoslot27, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR44_ADOTOSLOT27); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr44_adotoslot26, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR44_ADOTOSLOT26); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR44, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR45 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR45(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr45_adotoslot29, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR45_ADOTOSLOT29); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr45_adotoslot28, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR45_ADOTOSLOT28); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR45, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR46 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR46(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr46_adotoslot31, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR46_ADOTOSLOT31); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr46_adotoslot30, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR46_ADOTOSLOT30); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR46, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR47 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR47(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl7, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL7); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl6, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL6); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl5, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl4, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL4); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl3, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr47_hiz_sl0, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR47_HIZ_SL0); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR47, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR48 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR48(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl15, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL15); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl14, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL14); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl13, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL13); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl12, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL12); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl11, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL11); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl10, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL10); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl9, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL9); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr48_hiz_sl8, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR48_HIZ_SL8); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR48, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR49 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR49(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl23, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL23); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl22, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL22); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl21, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL21); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl20, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL20); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl19, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL19); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl18, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL18); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl17, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL17); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr49_hiz_sl16, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR49_HIZ_SL16); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR49, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR50 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR50(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl31, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL31); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl30, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL30); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl29, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL29); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl28, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL28); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl27, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL27); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl26, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL26); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl25, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL25); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr50_hiz_sl24, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR50_HIZ_SL24); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR50, value)); +} + +#endif + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR51 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR51(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr51_da12_voice, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR51_DA12_VOICE); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr51_sldai1toslado1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR51_SLDAI1TOSLADO1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr51_sltoda1, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR51_SLTODA1); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR51, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR52 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR52(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr52_sldai2toslado2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR52_SLDAI1TOSLADO2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr52_sltoda2, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR52_SLTODA2); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR52, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR53 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR53(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr53_da34_voice, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR53_DA34_VOICE); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr53_sldai3toslado3, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR53_SLDAI1TOSLADO3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr53_sltoda3, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR53_SLTODA3); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR53, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR54 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR54(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr54_sldai4toslado4, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR54_SLDAI1TOSLADO4); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr54_sltoda4, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR54_SLTODA4); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR54, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR55 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR55(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr55_da56_voice, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR55_DA56_VOICE); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr55_sldai5toslado5, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR55_SLDAI1TOSLADO5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr55_sltoda5, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR55_SLTODA5); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR55, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR56 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR56(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr56_sldai6toslado7, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR56_SLDAI1TOSLADO6); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr56_sltoda6, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR56_SLTODA6); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR56, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR57 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR57(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr57_bfifull_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR57_BFIFULL_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr57_bfiempt_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR57_BFIEMPT_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr57_dachan_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR57_DACHAN_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr57_gain_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR57_GAIN_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr57_dspad_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR57_DSPAD_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr57_dspda_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR57_DSPDA_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr57_stfir_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR57_STFIR_MSK); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR57, value)); +} + +/* CR58 is Read Only */ +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR59 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR59(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_vssready_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_VSSREADY_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_shrtvibl_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_SHRTVIBL_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_shrtvibr_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_SHRTVIBR_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_shrthfl_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_SHRTHFL_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_shrthfr_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_SHRTHFR_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_shrthsl_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_SHRTHSL_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_shrthsr_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_SHRTHSR_MSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr59_shrtear_msk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR59_SHRTEAR_MSK); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR59, value)); +} + +/* CR60 is Read Only */ +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR61 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR61(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + /* 5 bits are Read Only */ + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr61_fade_speed, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR61_FADE_SPEED); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR61, value)); +} +#endif +/* CR62 is Read Only */ +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR63 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR63(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_datohslen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_DATOHSLEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_datohsren, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_DATOHSREN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_ad1sel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_AD1SEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_ad2sel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_AD2SEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_ad3sel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_AD3SEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_ad5sel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_AD5SEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_ad6sel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_AD6SEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr63_ancsel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR63_ANCSEL); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR63, value)); +} + +#if 0 +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR64 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR64(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr64_datohfren, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR64_DATOHFREN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr64_datohflen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR64_DATOHFLEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr64_hfrsel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR64_HFRSEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr64_hflsel, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR64_HFLSEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr64_stfir1sel, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR64_STFIR1SEL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr64_stfir2sel, + AB8500_CODEC_MASK_TWO_BITS, AB8500_CODEC_CR64_STFIR2SEL); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR64, value)); +} + +#endif + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR65 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR65(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr65_fadedis_ad1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR65_FADEDIS_AD1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr65_ad1gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR65_AD1GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR65, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR66 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR66(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr66_fadedis_ad2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR66_FADEDIS_AD2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr66_ad2gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR66_AD2GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR66, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR67 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR67(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr67_fadedis_ad3, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR67_FADEDIS_AD3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr67_ad3gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR67_AD3GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR67, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR68 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR68(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr68_fadedis_ad4, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR68_FADEDIS_AD4); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr68_ad4gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR68_AD4GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR68, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR69 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR69(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr69_fadedis_ad5, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR69_FADEDIS_AD5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr69_ad5gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR69_AD5GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR69, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR70 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR70(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr70_fadedis_ad6, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR70_FADEDIS_AD6); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr70_ad6gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR70_AD6GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR70, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR71 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR71(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr71_fadedis_da1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR71_FADEDIS_DA1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr71_da1gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR71_DA1GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR71, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR72 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR72(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr72_fadedis_da2, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR72_FADEDIS_DA2); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr72_da2gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR72_DA2GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR72, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR73 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR73(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr73_fadedis_da3, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR73_FADEDIS_DA3); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr73_da3gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR73_DA3GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR73, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR74 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR74(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr74_fadedis_da4, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR74_FADEDIS_DA4); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr74_da4gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR74_DA4GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR74, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR75 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR75(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr75_fadedis_da5, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR75_FADEDIS_DA5); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr75_da5gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR75_DA5GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR75, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR76 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR76(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr76_fadedis_da6, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR76_FADEDIS_DA6); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr76_da6gain, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR76_DA6GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR76, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR77 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR77(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr77_fadedis_ad1l, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR77_FADEDIS_AD1L); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr77_ad1lbgain_to_hfl, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR77_AD1LBGAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR77, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR78 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR78(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr78_fadedis_ad2l, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR78_FADEDIS_AD2L); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr78_ad2lbgain_to_hfr, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR78_AD2LBGAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR78, value)); +} +#endif + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR79 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR79(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr79_hssinc1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR79_HSSINC1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr79_fadedis_hsl, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR79_FADEDIS_HSL); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr79_hsldgain, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR79_HSLDGAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR79, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR80 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR80(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr80_fadedis_hsr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR80_FADEDIS_HSR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr80_hsrdgain, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR80_HSRDGAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR80, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR81 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR81(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr81_stfir1gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR81_STFIR1GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR81, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR82 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR82(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr82_stfir2gain, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR82_STFIR2GAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR82, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR83 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR83(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr83_enanc, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR83_ENANC); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr83_anciirinit, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR83_ANCIIRINIT); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr83_ancfirupdate, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR83_ANCFIRUPDATE); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR83, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR84 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR84(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr84_ancinshift, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR84_ANCINSHIFT); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR84, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR85 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR85(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr85_ancfiroutshift, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR85_ANCFIROUTSHIFT); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR85, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR86 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR86(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr86_ancshiftout, + AB8500_CODEC_MASK_FIVE_BITS, AB8500_CODEC_CR86_ANCSHIFTOUT); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR86, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR87 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR87(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr87_ancfircoeff_msb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR87_ANCFIRCOEFF_MSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR87, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR88 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR88(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr88_ancfircoeff_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR88_ANCFIRCOEFF_LSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR88, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR89 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR89(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr89_anciircoeff_msb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR89_ANCIIRCOEFF_MSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR89, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR90 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR90(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr90_anciircoeff_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR90_ANCIIRCOEFF_LSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR90, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR91 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR91(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr91_ancwarpdel_msb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR91_ANCWARPDEL_MSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR91, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR92 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR92(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr92_ancwarpdel_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR92_ANCWARPDEL_LSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR92, value)); +} + +/* CR93 is Read Only */ +/* CR94 is Read Only */ +/* CR95 is Read Only */ +/* CR96 is Read Only */ +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR97 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR97(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr97_stfir_set, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR97_STFIR_SET); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr97_stfir_addr, + AB8500_CODEC_MASK_SEVEN_BITS, AB8500_CODEC_CR97_STFIR_ADDR); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR97, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR98 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR98(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr98_stfir_coeff_msb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR98_STFIR_COEFF_MSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR98, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR99 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR99(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr99_stfir_coeff_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR99_STFIR_COEFF_LSB); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR99, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR100 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR100(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr100_enstfirs, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR100_ENSTFIRS); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr100_stfirstoif1, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR100_STFIRSTOIF1); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr100_stfir_busy, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR100_STFIR_BUSY); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR100, value)); +} + +#endif +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR101 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR101(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr101_parlhf, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR101_PARLHF); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr101_parlvib, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR101_PARLVIB); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr101_classd_viblswapen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR101_CLASSDVIBLSWAPEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr101_classd_vibrswapen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR101_CLASSDVIBRSWAPEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr101_classd_hflswapen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR101_CLASSDHFLSWAPEN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr101_classd_hfrswapen, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR101_CLASSDHFRSWAPEN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR101, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR102 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR102(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr102_classd_firbyp, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR102_CLASSD_FIRBYP); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr102_classd_highvolen, + AB8500_CODEC_MASK_FOUR_BITS, AB8500_CODEC_CR102_CLASSD_HIGHVOLEN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR102, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR103 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR103(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr103_classd_ditherhpgain, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR103_CLASSD_DITHERHPGAIN); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr103_classd_ditherwgain, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR103_CLASSD_DITHERWGAIN); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR103, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR104 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR104(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr104_bfifoint, + AB8500_CODEC_MASK_SIX_BITS, AB8500_CODEC_CR104_BFIFOINT); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR104, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR105 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR105(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr105_bfifotx, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR105_BFIFOTX); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR105, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR106 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR106(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr106_bfifofsext, + AB8500_CODEC_MASK_THREE_BITS, AB8500_CODEC_CR106_BFIFOFSEXT); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr106_bfifomsk, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR106_BFIFOMSK); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr106_bfifomstr, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR106_BFIFOMSTR); + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr106_bfifostrt, + AB8500_CODEC_MASK_ONE_BIT, AB8500_CODEC_CR106_BFIFOSTRT); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR106, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR107 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR107(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr107_bfifosampnr, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR107_BFIFOSAMPNR); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR107, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR108 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR108(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr108_bfifowakeup, + AB8500_CODEC_MASK_EIGHT_BITS, AB8500_CODEC_CR108_BFIFOWAKEUP); + + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR108, value)); +} + +/* CR109 is Read Only */ +/********************************************************************************************/ +/* Name: ab8500_codec_Reset() */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_Reset(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + p_ab8500_codec_configuration->cr1_swreset = + AB8500_CODEC_CR1_SWRESET_ENABLED; + + ab8500_codec_error = ab8500_codec_UpdateCR1(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirection(IN + t_ab8500_codec_direction + ab8500_codec_direction) +{ /*only IN or OUT must be passed (not INOUT) */ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + if (AB8500_CODEC_DIRECTION_IN == ab8500_codec_direction) { + ab8500_codec_error = ab8500_codec_ProgramDirectionIN(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + if (AB8500_CODEC_DIRECTION_OUT == ab8500_codec_direction) { + ab8500_codec_error = ab8500_codec_ProgramDirectionOUT(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetDirection(IN + t_ab8500_codec_direction + ab8500_codec_direction) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + switch (ab8500_codec_direction) { + case AB8500_CODEC_DIRECTION_IN: + ab8500_codec_error = + ab8500_codec_ProgramDirection(AB8500_CODEC_DIRECTION_IN); + break; + + case AB8500_CODEC_DIRECTION_OUT: + ab8500_codec_error = + ab8500_codec_ProgramDirection(AB8500_CODEC_DIRECTION_OUT); + break; + + case AB8500_CODEC_DIRECTION_INOUT: + ab8500_codec_error = + ab8500_codec_ProgramDirection(AB8500_CODEC_DIRECTION_IN); + if (AB8500_CODEC_OK == ab8500_codec_error) { + ab8500_codec_error = + ab8500_codec_ProgramDirection + (AB8500_CODEC_DIRECTION_OUT); + } + break; + } + + if (ab8500_codec_error != AB8500_CODEC_OK) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR5(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR6(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR7(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR8(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR9(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR10(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR12(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR15(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR63(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_Init */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Initialize the global variables & stores the slave address of codec. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* slave_address_of_ab8500_codec: Audio codec slave address */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* Returns AB8500_CODEC_OK */ +/* COMMENTS: */ +/* 1) Saves the supplied slave_address_of_codec in global variable */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_Init(IN t_uint8 + slave_address_of_ab8500_codec) +{ + DBGENTER1(" (%lx)", slave_address_of_ab8500_codec); + + g_ab8500_codec_system_context.slave_address_of_ab8500_codec = + slave_address_of_ab8500_codec; + + DBGEXIT(AB8500_CODEC_OK); + return (AB8500_CODEC_OK); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_Reset */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Reset the global variables and clear audiocodec settings to default. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_Reset(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + DBGENTER(); + + g_ab8500_codec_system_context.ab8500_codec_direction = + AB8500_CODEC_DEFAULT_DIRECTION; + g_ab8500_codec_system_context.ab8500_codec_mode_in = + AB8500_CODEC_DEFAULT_MODE_IN; + g_ab8500_codec_system_context.ab8500_codec_mode_out = + AB8500_CODEC_DEFAULT_MODE_OUT; + + g_ab8500_codec_system_context.ab8500_codec_src = + AB8500_CODEC_DEFAULT_INPUT_SRC; + g_ab8500_codec_system_context.ab8500_codec_dest = + AB8500_CODEC_DEFAULT_OUTPUT_DEST; + + g_ab8500_codec_system_context.in_left_volume = + AB8500_CODEC_DEFAULT_VOLUME_LEFT_IN; + g_ab8500_codec_system_context.in_right_volume = + AB8500_CODEC_DEFAULT_VOLUME_RIGHT_IN; + g_ab8500_codec_system_context.out_left_volume = + AB8500_CODEC_DEFAULT_VOLUME_LEFT_OUT; + g_ab8500_codec_system_context.out_right_volume = + AB8500_CODEC_DEFAULT_VOLUME_RIGHT_OUT; + + ab8500_codec_error = ab8500_codec_Reset(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetModeAndDirection */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Configures the whole audio codec to work in audio mode */ +/* (using I2S protocol). */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* direction: select the direction (IN, OUT or INOUT) */ +/* in_mode: codec mode for recording. If direction is OUT only, */ +/* this parameter is ignored. */ +/* out_mode: codec mode for playing. If direction is IN only, */ +/* this parameter is ignored. */ +/* p_tdm_config: TDM configuration required to be configured by user */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: The API may not allow setting */ +/* 2 different modes, in which case it should return this value. */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetModeAndDirection + (IN t_ab8500_codec_direction ab8500_codec_direction, + IN t_ab8500_codec_mode ab8500_codec_mode_in, + IN t_ab8500_codec_mode ab8500_codec_mode_out, + IN t_ab8500_codec_tdm_config const *const p_tdm_config) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + DBGENTER3(" (%lx %lx %lx)", ab8500_codec_direction, + ab8500_codec_mode_in, ab8500_codec_mode_out); + + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) { + if (AB8500_CODEC_DIRECTION_OUT == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == ab8500_codec_direction) { + p_ab8500_codec_configuration->cr3_enda1 = + AB8500_CODEC_CR3_ENDA1_ENABLED; + p_ab8500_codec_configuration->cr3_enda2 = + AB8500_CODEC_CR3_ENDA2_ENABLED; + p_ab8500_codec_configuration->cr3_enda3 = + AB8500_CODEC_CR3_ENDA3_ENABLED; + p_ab8500_codec_configuration->cr3_enda4 = + AB8500_CODEC_CR3_ENDA4_ENABLED; + p_ab8500_codec_configuration->cr3_enda5 = + AB8500_CODEC_CR3_ENDA5_ENABLED; + p_ab8500_codec_configuration->cr3_enda6 = + AB8500_CODEC_CR3_ENDA6_ENABLED; + + p_ab8500_codec_configuration->cr27_if1_bitclk_osr = + p_tdm_config->cr27_if1_bitclk_osr; + + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_out) { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } else { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_TDM; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } + } + + if (AB8500_CODEC_DIRECTION_IN == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == ab8500_codec_direction) { + p_ab8500_codec_configuration->cr2_enad1 = + AB8500_CODEC_CR2_ENAD1_ENABLED; + p_ab8500_codec_configuration->cr2_enad2 = + AB8500_CODEC_CR2_ENAD2_ENABLED; + p_ab8500_codec_configuration->cr2_enad3 = + AB8500_CODEC_CR2_ENAD3_ENABLED; + p_ab8500_codec_configuration->cr2_enad4 = + AB8500_CODEC_CR2_ENAD4_ENABLED; + p_ab8500_codec_configuration->cr2_enad5 = + AB8500_CODEC_CR2_ENAD5_ENABLED; + p_ab8500_codec_configuration->cr2_enad6 = + AB8500_CODEC_CR2_ENAD6_ENABLED; + + p_ab8500_codec_configuration->cr27_if1_bitclk_osr = + p_tdm_config->cr27_if1_bitclk_osr; + + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_in) { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } else { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_RISING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_NOT_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_TDM; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } + } + } else { + if (AB8500_CODEC_DIRECTION_OUT == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == ab8500_codec_direction) { + p_ab8500_codec_configuration->cr3_enda1 = + AB8500_CODEC_CR3_ENDA1_ENABLED; + p_ab8500_codec_configuration->cr3_enda2 = + AB8500_CODEC_CR3_ENDA2_ENABLED; + p_ab8500_codec_configuration->cr3_enda3 = + AB8500_CODEC_CR3_ENDA3_ENABLED; + p_ab8500_codec_configuration->cr3_enda4 = + AB8500_CODEC_CR3_ENDA4_ENABLED; + p_ab8500_codec_configuration->cr3_enda5 = + AB8500_CODEC_CR3_ENDA5_ENABLED; + p_ab8500_codec_configuration->cr3_enda6 = + AB8500_CODEC_CR3_ENDA6_ENABLED; + + p_ab8500_codec_configuration->cr27_if0_bitclk_osr = + p_tdm_config->cr27_if0_bitclk_osr; + + p_ab8500_codec_configuration->cr63_datohslen = + AB8500_CODEC_CR63_DATOHSLEN_ENABLED; + p_ab8500_codec_configuration->cr63_datohsren = + AB8500_CODEC_CR63_DATOHSREN_ENABLED; + + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_out) { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } else { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_TDM; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } + } + + if (AB8500_CODEC_DIRECTION_IN == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == ab8500_codec_direction) { + p_ab8500_codec_configuration->cr2_enad1 = + AB8500_CODEC_CR2_ENAD1_ENABLED; + p_ab8500_codec_configuration->cr2_enad2 = + AB8500_CODEC_CR2_ENAD2_ENABLED; + p_ab8500_codec_configuration->cr2_enad3 = + AB8500_CODEC_CR2_ENAD3_ENABLED; + p_ab8500_codec_configuration->cr2_enad4 = + AB8500_CODEC_CR2_ENAD4_ENABLED; + p_ab8500_codec_configuration->cr2_enad5 = + AB8500_CODEC_CR2_ENAD5_ENABLED; + p_ab8500_codec_configuration->cr2_enad6 = + AB8500_CODEC_CR2_ENAD6_ENABLED; + + p_ab8500_codec_configuration->cr26_ad1_voice = + AB8500_CODEC_CR26_AD1_VOICE_LOWLATENCYFILTER; + p_ab8500_codec_configuration->cr26_ad2_voice = + AB8500_CODEC_CR26_AD2_VOICE_LOWLATENCYFILTER; + p_ab8500_codec_configuration->cr26_ad3_voice = + AB8500_CODEC_CR26_AD3_VOICE_LOWLATENCYFILTER; + p_ab8500_codec_configuration->cr26_ad4_voice = + AB8500_CODEC_CR26_AD4_VOICE_LOWLATENCYFILTER; + + p_ab8500_codec_configuration->cr27_if0_bitclk_osr = + p_tdm_config->cr27_if0_bitclk_osr; + + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_in) { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } else { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_TDM; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } + } + } + + ab8500_codec_error = ab8500_codec_SetModeAndDirectionUpdateCR(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + g_ab8500_codec_system_context.ab8500_codec_direction = + ab8500_codec_direction; + g_ab8500_codec_system_context.ab8500_codec_mode_in = + ab8500_codec_mode_in; + g_ab8500_codec_system_context.ab8500_codec_mode_out = + ab8500_codec_mode_out; + + ab8500_codec_error = ab8500_codec_SetDirection(ab8500_codec_direction); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetSrcVolume */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Sets the record volumes. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* t_ab8500_codec_src: select source device for recording. */ +/* in_left_volume: record volume for left channel. */ +/* in_right_volume: record volume for right channel. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetSrcVolume + (IN t_ab8500_codec_src src_device, + IN t_uint8 in_left_volume, IN t_uint8 in_right_volume) { + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER3(" (%lx %lx %lx)", src_device, in_left_volume, + in_right_volume); + + if (in_left_volume > AB8500_CODEC_MAX_VOLUME) { + in_left_volume = AB8500_CODEC_MAX_VOLUME; + } + + if (in_right_volume > AB8500_CODEC_MAX_VOLUME) { + in_right_volume = AB8500_CODEC_MAX_VOLUME; + } + + g_ab8500_codec_system_context.in_left_volume = in_left_volume; + g_ab8500_codec_system_context.in_right_volume = in_right_volume; + + p_ab8500_codec_configuration->cr65_ad1gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr66_ad2gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr67_ad3gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr68_ad4gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr69_ad5gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr70_ad6gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + + /* Set mininimum volume if volume is zero */ + switch (src_device) { + case AB8500_CODEC_SRC_LINEIN: + p_ab8500_codec_configuration->cr22_linl_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr23_linr_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_right_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + break; + + case AB8500_CODEC_SRC_MICROPHONE_1A: + case AB8500_CODEC_SRC_MICROPHONE_1B: + p_ab8500_codec_configuration->cr20_mic1_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + break; + + case AB8500_CODEC_SRC_MICROPHONE_2: + p_ab8500_codec_configuration->cr21_mic2_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_1: + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_2: + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_3: + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_4: + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_5: + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_6: + break; + + case AB8500_CODEC_SRC_ALL: + p_ab8500_codec_configuration->cr22_linl_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr23_linr_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_right_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + + p_ab8500_codec_configuration->cr20_mic1_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + + p_ab8500_codec_configuration->cr21_mic2_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_SetSrcVolumeUpdateCR(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetDestVolume */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Sets the play volumes. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* out_left_volume: play volume for left channel. */ +/* out_right_volume: play volume for right channel. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetDestVolume + (IN t_ab8500_codec_dest dest_device, + IN t_uint8 out_left_volume, IN t_uint8 out_right_volume) { + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER3(" (%lx %lx %lx)", dest_device, out_left_volume, + out_right_volume); + + if (out_left_volume > AB8500_CODEC_MAX_VOLUME) { + out_left_volume = AB8500_CODEC_MAX_VOLUME; + } + + if (out_right_volume > AB8500_CODEC_MAX_VOLUME) { + out_right_volume = AB8500_CODEC_MAX_VOLUME; + } + + g_ab8500_codec_system_context.out_left_volume = out_left_volume; + g_ab8500_codec_system_context.out_right_volume = out_right_volume; + + p_ab8500_codec_configuration->cr71_da1gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr72_da2gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr73_da3gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr74_da4gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr75_da5gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr76_da6gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + + /* Set mininimum volume if volume is zero */ + switch (dest_device) { + case AB8500_CODEC_DEST_HEADSET: + p_ab8500_codec_configuration->cr22_hsl_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr23_hsr_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + + p_ab8500_codec_configuration->cr79_hsldgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + p_ab8500_codec_configuration->cr80_hsrdgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + break; + + case AB8500_CODEC_DEST_EARPIECE: + p_ab8500_codec_configuration->cr79_hsldgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + break; + + case AB8500_CODEC_DEST_HANDSFREE: + + p_ab8500_codec_configuration->cr101_parlhf = + AB8500_CODEC_CR101_PARLHF_INDEPENDENT; + p_ab8500_codec_configuration->cr101_parlvib = + AB8500_CODEC_CR101_PARLVIB_INDEPENDENT; + p_ab8500_codec_configuration->cr101_classd_viblswapen = + AB8500_CODEC_CR101_CLASSD_VIBLSWAPEN_DISABLED; + p_ab8500_codec_configuration->cr101_classd_vibrswapen = + AB8500_CODEC_CR101_CLASSD_VIBRSWAPEN_DISABLED; + p_ab8500_codec_configuration->cr101_classd_hflswapen = + AB8500_CODEC_CR101_CLASSD_HFLSWAPEN_DISABLED; + p_ab8500_codec_configuration->cr101_classd_hfrswapen = + AB8500_CODEC_CR101_CLASSD_HFRSWAPEN_DISABLED; + + p_ab8500_codec_configuration->cr102_classd_firbyp = + AB8500_CODEC_CR102_CLASSD_FIRBYP_ALL_ENABLED; + p_ab8500_codec_configuration->cr102_classd_highvolen = + AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_DISABLED; + + p_ab8500_codec_configuration->cr103_classd_ditherhpgain = 0x8; + p_ab8500_codec_configuration->cr103_classd_ditherwgain = 0x4; + + break; + + case AB8500_CODEC_DEST_VIBRATOR_L: + p_ab8500_codec_configuration->cr16_pwmnldutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN; + p_ab8500_codec_configuration->cr17_pwmpldutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_VIBRATOR_VOLUME_MAX - + AB8500_CODEC_VIBRATOR_VOLUME_MIN)) / 100; + break; + + case AB8500_CODEC_DEST_VIBRATOR_R: + p_ab8500_codec_configuration->cr18_pwmnrdutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN; + p_ab8500_codec_configuration->cr19_pwmprdutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_VIBRATOR_VOLUME_MAX - + AB8500_CODEC_VIBRATOR_VOLUME_MIN)) / 100; + break; + + case AB8500_CODEC_DEST_ALL: + p_ab8500_codec_configuration->cr22_hsl_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr23_hsr_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + + p_ab8500_codec_configuration->cr79_hsldgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_SetDestVolumeUpdateCR(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetMasterMode */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Set the Audio Codec in Master mode. */ +/* */ +/* ARGUMENTS */ +/* IN: t_codec_master_mode: Enable/disable master mode */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: Call this API after calling AB8500_CODEC_SetModeAndDirection() API*/ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetMasterMode(IN + t_ab8500_codec_master_mode + mode) +{ + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) { + + p_ab8500_codec_configuration->cr27_en_mastgen = + AB8500_CODEC_CR27_EN_MASTGEN_ENABLED; + p_ab8500_codec_configuration->cr27_enfs_bitclk1 = + AB8500_CODEC_CR27_ENFS_BITCLK1_ENABLED; + + if (AB8500_CODEC_MASTER_MODE_ENABLE == mode) { + p_ab8500_codec_configuration->cr29_if1master = + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_OUTPUT; + } else { + p_ab8500_codec_configuration->cr29_if1master = + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_INPUT; + } + + } else { + + p_ab8500_codec_configuration->cr27_en_mastgen = + AB8500_CODEC_CR27_EN_MASTGEN_ENABLED; + p_ab8500_codec_configuration->cr27_enfs_bitclk0 = + AB8500_CODEC_CR27_ENFS_BITCLK0_ENABLED; + + if (AB8500_CODEC_MASTER_MODE_ENABLE == mode) { + p_ab8500_codec_configuration->cr29_if0master = + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_OUTPUT; + } else { + p_ab8500_codec_configuration->cr29_if0master = + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_INPUT; + } + + } + + ab8500_codec_error = ab8500_codec_UpdateCR27(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR29(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SelectInput */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Select input source for recording. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* input_src: select input source for recording when several sources */ +/* are supported in codec. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If input_src provided is invalid */ +/* by the codec hardware in use. */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SelectInput(IN t_ab8500_codec_src + ab8500_codec_src) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER1(" (%lx)", ab8500_codec_src); + + g_ab8500_codec_system_context.ab8500_codec_src = ab8500_codec_src; + + ab8500_codec_error = + ab8500_codec_SetDirection(AB8500_CODEC_DIRECTION_IN); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SelectOutput */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Select output desination for playing. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* output_dest: select output destination for playing when several are */ +/* supported by codec hardware. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If output_src provided is invalid */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SelectOutput(IN t_ab8500_codec_dest + ab8500_codec_dest) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + g_ab8500_codec_system_context.ab8500_codec_dest = ab8500_codec_dest; + DBGENTER1(" (%lx)", ab8500_codec_dest); + + ab8500_codec_error = + ab8500_codec_SetDirection(AB8500_CODEC_DIRECTION_OUT); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_PowerDown */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Shuts the audio codec down completely. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* OUT: */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_PowerDown(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + g_ab8500_codec_system_context.ab8500_codec_configuration.cr0_powerup = + AB8500_CODEC_CR0_POWERUP_OFF; + + ab8500_codec_error = ab8500_codec_UpdateCR0(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_PowerUp */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Switch on the audio codec. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_PowerUp(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + DBGENTER(); + + /*g_ab8500_codec_system_context.ab8500_codec_configuration.cr1_swreset = AB8500_CODEC_CR1_SWRESET_ENABLED; Removed by kardad + ab8500_codec_error = ab8500_codec_UpdateCR1(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return(ab8500_codec_error); + } */ + + g_ab8500_codec_system_context.ab8500_codec_configuration.cr0_powerup = + AB8500_CODEC_CR0_POWERUP_ON; + g_ab8500_codec_system_context.ab8500_codec_configuration.cr0_enaana = + AB8500_CODEC_CR0_ENAANA_ON; + + ab8500_codec_error = ab8500_codec_UpdateCR0(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SelectInterface */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Select the Audio Interface 0 or 1. */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_audio_interface: The selected interface */ +/* */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_OK: Always. */ +/* REMARK: Call this API before using a function of the low level drivers */ +/* to select the interface that you want to configure */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SelectInterface(IN + t_ab8500_codec_audio_interface + audio_interface) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + + g_ab8500_codec_system_context.audio_interface = audio_interface; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_GetInterface */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Get the Audio Interface 0 or 1. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: p_audio_interface: Store the selected interface */ +/* RETURN: */ +/* AB8500_CODEC_OK: Always */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_GetInterface(OUT + t_ab8500_codec_audio_interface + * p_audio_interface) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + + *p_audio_interface = g_ab8500_codec_system_context.audio_interface; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetAnalogLoopback */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Sets Line-In to HeadSet loopback with the required gain. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* out_left_volume: play volume for left channel. */ +/* out_right_volume: play volume for right channel. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetAnalogLoopback(IN t_uint8 + out_left_volume, + IN t_uint8 + out_right_volume) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER2(" (%lx %lx)", out_left_volume, out_right_volume); + + if (out_left_volume > AB8500_CODEC_MAX_VOLUME) { + out_left_volume = AB8500_CODEC_MAX_VOLUME; + } + + if (out_right_volume > AB8500_CODEC_MAX_VOLUME) { + out_right_volume = AB8500_CODEC_MAX_VOLUME; + } + + g_ab8500_codec_system_context.out_left_volume = out_left_volume; + g_ab8500_codec_system_context.out_right_volume = out_right_volume; + + p_ab8500_codec_configuration->cr24_lintohsl_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX - + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr25_lintohsr_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX - + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN)) / 100; + + ab8500_codec_error = ab8500_codec_UpdateCR24(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR25(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_RemoveAnalogLoopback */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Remove Line-In to HeadSet loopback. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_RemoveAnalogLoopback(void) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER0(); + + p_ab8500_codec_configuration->cr24_lintohsl_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN; + p_ab8500_codec_configuration->cr25_lintohsr_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN; + + ab8500_codec_error = ab8500_codec_UpdateCR24(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR25(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_EnableBypassMode */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enables IF0 to IF1 path or vice versa */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_EnableBypassMode(void) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER0(); + + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) { + p_ab8500_codec_configuration->cr29_if1datoif0ad = + AB8500_CODEC_CR29_IF1DATOIF0AD_SENT; + p_ab8500_codec_configuration->cr29_if1cktoif0ck = + AB8500_CODEC_CR29_IF1CKTOIF0CK_SENT; + } else { + p_ab8500_codec_configuration->cr29_if0datoif1ad = + AB8500_CODEC_CR29_IF0DATOIF1AD_SENT; + p_ab8500_codec_configuration->cr29_if0cktoif1ck = + AB8500_CODEC_CR29_IF0CKTOIF1CK_SENT; + } + + ab8500_codec_error = ab8500_codec_UpdateCR29(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DisableBypassMode */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Disables IF0 to IF1 path or vice versa */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DisableBypassMode(void) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER0(); + + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) { + p_ab8500_codec_configuration->cr29_if1datoif0ad = + AB8500_CODEC_CR29_IF1DATOIF0AD_NOTSENT; + p_ab8500_codec_configuration->cr29_if1cktoif0ck = + AB8500_CODEC_CR29_IF1CKTOIF0CK_NOTSENT; + } else { + p_ab8500_codec_configuration->cr29_if0datoif1ad = + AB8500_CODEC_CR29_IF0DATOIF1AD_NOTSENT; + p_ab8500_codec_configuration->cr29_if0cktoif1ck = + AB8500_CODEC_CR29_IF0CKTOIF1CK_NOTSENT; + } + + ab8500_codec_error = ab8500_codec_UpdateCR29(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SrcPowerControl */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enables/Disables & UnMute/Mute the desired source */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* t_ab8500_codec_src: select source device for enabling/disabling. */ +/* t_ab8500_codec_src_state: Enable/Disable */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SrcPowerControl(IN t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state) +{ + t_ab8500_codec_error ab8500_codec_error; + + DBGENTER2(" (%lx %lx)", src_device, state); + + if (src_device <= AB8500_CODEC_SRC_D_MICROPHONE_2) { + ab8500_codec_error = + ab8500_codec_SrcPowerControlSwitch1(src_device, state); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else if (src_device <= AB8500_CODEC_SRC_ALL) { + ab8500_codec_error = + ab8500_codec_SrcPowerControlSwitch2(src_device, state); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else { + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR5(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR6(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR7(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR63(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DestPowerControl */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enables/Disables & UnMute/Mute the desired destination */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* t_ab8500_codec_dest: select destination device for enabling/disabling. */ +/* t_ab8500_codec_dest_state: Enable/Disable */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DestPowerControl(IN t_ab8500_codec_dest + dest_device, + t_ab8500_codec_dest_state + state) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER2(" (%lx %lx)", dest_device, state); + + switch (dest_device) { + case AB8500_CODEC_DEST_HEADSET: + + if (AB8500_CODEC_DEST_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + } else { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + } + break; + + case AB8500_CODEC_DEST_EARPIECE: + + if (AB8500_CODEC_DEST_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + } else { + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_DISABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + } + break; + + case AB8500_CODEC_DEST_HANDSFREE: + + if (AB8500_CODEC_DEST_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_DISABLED; + } else { + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_DISABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_ENABLED; + } + break; + + case AB8500_CODEC_DEST_VIBRATOR_L: + + if (AB8500_CODEC_DEST_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_DISABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + } else { + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_ENABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL; + } + break; + + case AB8500_CODEC_DEST_VIBRATOR_R: + + if (AB8500_CODEC_DEST_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_DISABLED; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + } else { + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_ENABLED; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL; + } + break; + + case AB8500_CODEC_DEST_ALL: + + if (AB8500_CODEC_DEST_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_DISABLED; + + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + } else { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_DISABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_DISABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_DISABLED; + + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_ENABLED; + + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL; + + } + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_DestPowerControlUpdateCR(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_GetVersion */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* This routine populates the pVersion structure with */ +/* the current version of HCL. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* p_version: this parameter is used to return current HCL version. */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_ERROR: if p_version is NULL. */ +/* AB8500_CODEC_OK: if successful */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_GetVersion(OUT t_version * p_version) +{ + DBGENTER1(" (%lx)", p_version); + if (p_version != NULL) { + p_version->minor = AB8500_CODEC_HCL_MINOR_ID; + p_version->major = AB8500_CODEC_HCL_MAJOR_ID; + p_version->version = AB8500_CODEC_HCL_VERSION_ID; + DBGEXIT0(AB8500_CODEC_OK); + return (AB8500_CODEC_OK); + } else { + DBGEXIT0(AB8500_CODEC_INVALID_PARAMETER); + return (AB8500_CODEC_INVALID_PARAMETER); + } +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetDbgLevel */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Set the debug level used by the debug module (mask-like value). */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* debug_level: debug level to be set */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_OK: always */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +/* +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetDbgLevel(IN t_dbg_level dbg_level) +{ + DBGENTER1(" (%d)", dbg_level); + dbg_level = dbg_level; +#ifdef __DEBUG + MY_DEBUG_LEVEL_VAR_NAME = dbg_level; +#endif + DBGEXIT(AB8500_CODEC_OK); + return(AB8500_CODEC_OK); +}*/ + +/****************************************************************************/ +/* NAME: AB8500_CODEC_GetDbgLevel */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Set the debug level used by the debug module (mask-like value). */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* p_dbg_level: this parameter is used to return debug level. */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_ERROR: if p_version is NULL. */ +/* AB8500_CODEC_OK: if successful */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +/* +PUBLIC t_ab8500_codec_error AB8500_CODEC_GetDbgLevel(OUT t_dbg_level *p_dbg_level) +{ + if (NULL == p_dbg_level) + { + DBGEXIT(AB8500_CODEC_INVALID_PARAMETER); + return(AB8500_CODEC_INVALID_PARAMETER); + } + +#ifdef __DEBUG + * p_dbg_level = MY_DEBUG_LEVEL_VAR_NAME; +#endif + DBGEXIT(AB8500_CODEC_OK); + return(AB8500_CODEC_OK); +} +*/ +/****************************************************************************/ +/* NAME: AB8500_CODEC_ADSlotAllocation */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* AD Data Allocation in slots. */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_slot: The slot to be allocated. */ +/* IN: t_ab8500_codec_cr31_to_cr46_ad_data_allocation: The value */ +/* to be allocated. */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If invalid slot number */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_ADSlotAllocation + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + DBGENTER2(" (%lx %lx)", ad_slot, value); + + if (ad_slot <= AB8500_CODEC_SLOT7) { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch1(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else if (ad_slot <= AB8500_CODEC_SLOT15) { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch2(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else if (ad_slot <= AB8500_CODEC_SLOT23) { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch3(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else if (ad_slot <= AB8500_CODEC_SLOT31) { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch4(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else { + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DASlotAllocation */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Allocate the Audio Interface slot for DA paths. */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_da_channel_number: Channel number 1/2/3/4/5/6 */ +/* IN: t_ab8500_codec_cr51_to_cr56_sltoda: Slot number */ +/* */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If invalid channel number */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DASlotAllocation + (IN t_ab8500_codec_da_channel_number channel_number, + IN t_ab8500_codec_cr51_to_cr56_sltoda slot) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + t_ab8500_codec_cr0_powerup ab8500_codec_cr0_powerup; + + DBGENTER2(" (%lx %lx)", channel_number, slot); + + p_ab8500_codec_configuration->cr51_da12_voice = + AB8500_CODEC_CR51_DA12_VOICE_LOWLATENCYFILTER; + + switch (channel_number) { + case AB8500_CODEC_DA_CHANNEL_NUMBER_1: + p_ab8500_codec_configuration->cr51_sltoda1 = slot; + break; + + case AB8500_CODEC_DA_CHANNEL_NUMBER_2: + p_ab8500_codec_configuration->cr52_sltoda2 = slot; + break; + + case AB8500_CODEC_DA_CHANNEL_NUMBER_3: + p_ab8500_codec_configuration->cr53_sltoda3 = slot; + break; + + case AB8500_CODEC_DA_CHANNEL_NUMBER_4: + p_ab8500_codec_configuration->cr54_sltoda4 = slot; + break; + + case AB8500_CODEC_DA_CHANNEL_NUMBER_5: + p_ab8500_codec_configuration->cr55_sltoda5 = slot; + break; + + case AB8500_CODEC_DA_CHANNEL_NUMBER_6: + p_ab8500_codec_configuration->cr56_sltoda6 = slot; + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_cr0_powerup = p_ab8500_codec_configuration->cr0_powerup; + + p_ab8500_codec_configuration->cr0_powerup = + AB8500_CODEC_CR0_POWERUP_OFF; + + ab8500_codec_error = ab8500_codec_UpdateCR0(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR51(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR52(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR53(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR54(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR55(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR56(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + p_ab8500_codec_configuration->cr0_powerup = ab8500_codec_cr0_powerup; + + ab8500_codec_error = ab8500_codec_UpdateCR0(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_ConfigureBurstFifo */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Configuration for Burst FIFO control */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_burst_fifo_config: structure for configuration of */ +/* burst FIFO */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If invalid parameter */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: If interface 1 selected */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +t_ab8500_codec_error AB8500_CODEC_ConfigureBurstFifo(IN + t_ab8500_codec_burst_fifo_config + const *const + p_burst_fifo_config) +{ + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER1(" (%lx)", p_burst_fifo_config); + + if (AB8500_CODEC_AUDIO_INTERFACE_0 == + g_ab8500_codec_system_context.audio_interface) { + if (AB8500_CODEC_CR27_EN_MASTGEN_ENABLED == + p_ab8500_codec_configuration->cr27_en_mastgen) { + p_ab8500_codec_configuration->cr104_bfifoint = + p_burst_fifo_config->cr104_bfifoint; + + p_ab8500_codec_configuration->cr105_bfifotx = + p_burst_fifo_config->cr105_bfifotx; + + p_ab8500_codec_configuration->cr106_bfifofsext = + p_burst_fifo_config->cr106_bfifofsext; + p_ab8500_codec_configuration->cr106_bfifomsk = + p_burst_fifo_config->cr106_bfifomsk; + p_ab8500_codec_configuration->cr106_bfifomstr = + p_burst_fifo_config->cr106_bfifomstr; + p_ab8500_codec_configuration->cr106_bfifostrt = + p_burst_fifo_config->cr106_bfifostrt; + + p_ab8500_codec_configuration->cr107_bfifosampnr = + p_burst_fifo_config->cr107_bfifosampnr; + + p_ab8500_codec_configuration->cr108_bfifowakeup = + p_burst_fifo_config->cr108_bfifowakeup; + + ab8500_codec_error = ab8500_codec_UpdateCR104(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR105(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR106(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR107(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR108(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else { + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else { + ab8500_codec_error = AB8500_CODEC_UNSUPPORTED_FEATURE; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_EnableBurstFifo */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enable the Burst FIFO for Interface 0 */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: If Interface 1 is selected */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_EnableBurstFifo(void) +{ + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + + if (AB8500_CODEC_AUDIO_INTERFACE_0 == + g_ab8500_codec_system_context.audio_interface) { + p_ab8500_codec_configuration->cr29_if0bfifoen = + AB8500_CODEC_CR29_IF0BFIFOEN_BURST_MODE; + + ab8500_codec_error = ab8500_codec_UpdateCR29(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else { + ab8500_codec_error = AB8500_CODEC_UNSUPPORTED_FEATURE; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DisableBurstFifo */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Disable the Burst FIFO for Interface 0 */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: If Interface 1 is selected */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DisableBurstFifo(void) +{ + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + + if (AB8500_CODEC_AUDIO_INTERFACE_0 == + g_ab8500_codec_system_context.audio_interface) { + p_ab8500_codec_configuration->cr29_if0bfifoen = + AB8500_CODEC_CR29_IF0BFIFOEN_NORMAL_MODE; + + ab8500_codec_error = ab8500_codec_UpdateCR29(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } else { + ab8500_codec_error = AB8500_CODEC_UNSUPPORTED_FEATURE; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch1 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (ad_slot) { + case AB8500_CODEC_SLOT0: + p_ab8500_codec_configuration->cr31_adotoslot0 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR31(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT1: + p_ab8500_codec_configuration->cr31_adotoslot1 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR31(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT2: + p_ab8500_codec_configuration->cr32_adotoslot2 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR32(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT3: + p_ab8500_codec_configuration->cr32_adotoslot3 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR32(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT4: + p_ab8500_codec_configuration->cr33_adotoslot4 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR33(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT5: + p_ab8500_codec_configuration->cr33_adotoslot5 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR33(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT6: + p_ab8500_codec_configuration->cr34_adotoslot6 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR34(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT7: + p_ab8500_codec_configuration->cr34_adotoslot7 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR34(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch2 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (ad_slot) { + case AB8500_CODEC_SLOT8: + p_ab8500_codec_configuration->cr35_adotoslot8 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR35(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT9: + p_ab8500_codec_configuration->cr35_adotoslot9 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR35(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT10: + p_ab8500_codec_configuration->cr36_adotoslot10 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR36(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT11: + p_ab8500_codec_configuration->cr36_adotoslot11 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR36(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT12: + p_ab8500_codec_configuration->cr37_adotoslot12 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR37(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT13: + p_ab8500_codec_configuration->cr37_adotoslot13 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR37(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT14: + p_ab8500_codec_configuration->cr38_adotoslot14 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR38(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT15: + p_ab8500_codec_configuration->cr38_adotoslot15 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR38(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch3 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (ad_slot) { + case AB8500_CODEC_SLOT16: + p_ab8500_codec_configuration->cr39_adotoslot16 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR39(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT17: + p_ab8500_codec_configuration->cr39_adotoslot17 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR39(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT18: + p_ab8500_codec_configuration->cr40_adotoslot18 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR40(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT19: + p_ab8500_codec_configuration->cr40_adotoslot19 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR40(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT20: + p_ab8500_codec_configuration->cr41_adotoslot20 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR41(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT21: + p_ab8500_codec_configuration->cr41_adotoslot21 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR41(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT22: + p_ab8500_codec_configuration->cr42_adotoslot22 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR42(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT23: + p_ab8500_codec_configuration->cr42_adotoslot23 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR42(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch4 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (ad_slot) { + case AB8500_CODEC_SLOT24: + p_ab8500_codec_configuration->cr43_adotoslot24 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR43(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT25: + p_ab8500_codec_configuration->cr43_adotoslot25 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR43(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT26: + p_ab8500_codec_configuration->cr44_adotoslot26 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR44(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT27: + p_ab8500_codec_configuration->cr44_adotoslot27 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR44(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT28: + p_ab8500_codec_configuration->cr45_adotoslot28 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR45(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT29: + p_ab8500_codec_configuration->cr45_adotoslot29 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR45(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT30: + p_ab8500_codec_configuration->cr46_adotoslot30 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR46(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + case AB8500_CODEC_SLOT31: + p_ab8500_codec_configuration->cr46_adotoslot31 = value; + + ab8500_codec_error = ab8500_codec_UpdateCR46(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch1(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (src_device) { + case AB8500_CODEC_SRC_LINEIN: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_LINR; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + } else { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_MIC2; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + } + break; + + case AB8500_CODEC_SRC_MICROPHONE_1A: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1A; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + } else { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_DISABLED; + } + break; + + case AB8500_CODEC_SRC_MICROPHONE_1B: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1B; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + } else { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_DISABLED; + } + break; + + case AB8500_CODEC_SRC_MICROPHONE_2: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_MIC2; + } else { + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_LINR; + } + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_1: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + + p_ab8500_codec_configuration->cr63_ad1sel = + AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED; + } else { + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + + p_ab8500_codec_configuration->cr63_ad1sel = + AB8500_CODEC_CR63_AD1SEL_LINLADL_SELECTED; + } + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_2: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + + p_ab8500_codec_configuration->cr63_ad2sel = + AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED; + } else { + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + + p_ab8500_codec_configuration->cr63_ad2sel = + AB8500_CODEC_CR63_AD2SEL_LINRADR_SELECTED; + } + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch2(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (src_device) { + case AB8500_CODEC_SRC_D_MICROPHONE_3: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + + p_ab8500_codec_configuration->cr63_ad3sel = + AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED; + } else { + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + + p_ab8500_codec_configuration->cr63_ad3sel = + AB8500_CODEC_CR63_AD3SEL_ADMO_SELECTED; + } + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_4: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + } else { + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + } + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_5: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + + p_ab8500_codec_configuration->cr63_ad5sel = + AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED; + } else { + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + + p_ab8500_codec_configuration->cr63_ad5sel = + AB8500_CODEC_CR63_AD5SEL_AMADR_SELECTED; + } + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_6: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + + p_ab8500_codec_configuration->cr63_ad6sel = + AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED; + } else { + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + + p_ab8500_codec_configuration->cr63_ad6sel = + AB8500_CODEC_CR63_AD6SEL_ADMO_SELECTED; + } + break; + + case AB8500_CODEC_SRC_ALL: + + if (AB8500_CODEC_SRC_STATE_ENABLE == state) { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + } else { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_DISABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + } + break; + case AB8500_CODEC_SRC_FM_RX: + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetModeAndDirectionUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + t_ab8500_codec_cr0_powerup ab8500_codec_cr0_powerup; + + ab8500_codec_cr0_powerup = p_ab8500_codec_configuration->cr0_powerup; + + p_ab8500_codec_configuration->cr0_powerup = + AB8500_CODEC_CR0_POWERUP_OFF; + + ab8500_codec_error = ab8500_codec_UpdateCR0(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR2(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR3(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR26(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR28(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR30(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR63(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + p_ab8500_codec_configuration->cr0_powerup = ab8500_codec_cr0_powerup; + + ab8500_codec_error = ab8500_codec_UpdateCR0(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetSrcVolumeUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + ab8500_codec_error = ab8500_codec_UpdateCR20(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR21(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR22(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR23(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR65(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR66(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR67(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR68(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR69(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR70(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetDestVolumeUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + ab8500_codec_error = ab8500_codec_UpdateCR16(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR17(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR18(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR19(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR22(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR23(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR71(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR72(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR73(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR74(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR75(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR76(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR79(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR80(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR101(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR102(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR103(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionIN(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (g_ab8500_codec_system_context.ab8500_codec_src) { + case AB8500_CODEC_SRC_LINEIN: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_LINR; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_MICROPHONE_1A: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1A; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_MICROPHONE_1B: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1B; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_MICROPHONE_2: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_MIC2; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_1: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr63_ad1sel = + AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_2: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr63_ad2sel = + AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_3: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr63_ad3sel = + AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_4: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_5: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr63_ad5sel = + AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_D_MICROPHONE_6: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + + p_ab8500_codec_configuration->cr63_ad6sel = + AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + + break; + + case AB8500_CODEC_SRC_ALL: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionOUT(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration *p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + + switch (g_ab8500_codec_system_context.ab8500_codec_dest) { + case AB8500_CODEC_DEST_HEADSET: + p_ab8500_codec_configuration->cr7_endrvhsl = + AB8500_CODEC_CR7_ENDRVHSL_ENABLED; + p_ab8500_codec_configuration->cr7_endrvhsr = + AB8500_CODEC_CR7_ENDRVHSR_ENABLED; + + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + + p_ab8500_codec_configuration->cr9_endachsl = + AB8500_CODEC_CR9_ENDACHSL_ENABLED; + p_ab8500_codec_configuration->cr9_endachsr = + AB8500_CODEC_CR9_ENDACHSR_ENABLED; + + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_ENABLED; + + p_ab8500_codec_configuration->cr12_encphs = + AB8500_CODEC_CR12_ENCPHS_ENABLED; + + break; + + case AB8500_CODEC_DEST_EARPIECE: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_ENABLED; + + break; + + case AB8500_CODEC_DEST_HANDSFREE: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_ENABLED; + + break; + + case AB8500_CODEC_DEST_VIBRATOR_L: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_ENABLED; + + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + + break; + + case AB8500_CODEC_DEST_VIBRATOR_R: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_ENABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_DISABLED; + + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + + break; + + case AB8500_CODEC_DEST_ALL: + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfl = + AB8500_CODEC_CR10_MUTEHFL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehfr = + AB8500_CODEC_CR10_MUTEHFR_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibl = + AB8500_CODEC_CR10_MUTEVIBL_DISABLED; + p_ab8500_codec_configuration->cr10_mutevibr = + AB8500_CODEC_CR10_MUTEVIBR_DISABLED; + + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + + break; + + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_DestPowerControlUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + + ab8500_codec_error = ab8500_codec_UpdateCR8(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR9(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR10(); + if (ab8500_codec_error != AB8500_CODEC_OK) { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + + ab8500_codec_error = ab8500_codec_UpdateCR15(); + + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} diff --git a/sound/ab8500_codec_v1_0.c b/sound/ab8500_codec_v1_0.c new file mode 100644 index 00000000000..5df1ca3eae4 --- /dev/null +++ b/sound/ab8500_codec_v1_0.c @@ -0,0 +1,6405 @@ +/*****************************************************************************/ + +/** +* © ST-Ericsson, 2009 - All rights reserved +* Reproduction and Communication of this document is strictly prohibited +* unless specifically authorized in writing by ST-Ericsson +* +* \brief This module provides some support routines for the AB8500 CODEC +* \author ST-Ericsson +*/ +/*****************************************************************************/ + +/*---------------------------------------------------------------------------- + * Includes + *---------------------------------------------------------------------------*/ + +#ifdef CONFIG_U8500_AB8500_CUT10 +#include +#include +#else /* */ +#include +#include +#endif /* */ + +/*--------------------------------------------------------------------------* + * debug stuff * + *--------------------------------------------------------------------------*/ +#ifdef __DEBUG +#define MY_DEBUG_LEVEL_VAR_NAME myDebugLevel_AB8500_CODEC +#define MY_DEBUG_ID myDebugID_AB8500_CODEC +PRIVATE t_dbg_level MY_DEBUG_LEVEL_VAR_NAME = DEBUG_LEVEL0; +PRIVATE t_dbg_id MY_DEBUG_ID = AB8500_CODEC_HCL_DBG_ID; + +#endif /* */ + +/*--------------------------------------------------------------------------* + * Global data for interrupt mode management * + *--------------------------------------------------------------------------*/ +PRIVATE t_ab8500_codec_system_context g_ab8500_codec_system_context; + +/*--------------------------------------------------------------------------* + * Default Values * + *--------------------------------------------------------------------------*/ +#define AB8500_CODEC_DEFAULT_SLAVE_ADDRESS_OF_CODEC 0xD +#define AB8500_CODEC_DEFAULT_DIRECTION AB8500_CODEC_DIRECTION_OUT + +#define AB8500_CODEC_DEFAULT_MODE_IN AB8500_CODEC_MODE_VOICE +#define AB8500_CODEC_DEFAULT_MODE_OUT AB8500_CODEC_MODE_VOICE + +#define AB8500_CODEC_DEFAULT_INPUT_SRC AB8500_CODEC_SRC_MICROPHONE_1A +#define AB8500_CODEC_DEFAULT_OUTPUT_DEST AB8500_CODEC_DEST_HEADSET + +#define AB8500_CODEC_DEFAULT_VOLUME_LEFT_IN 75 +#define AB8500_CODEC_DEFAULT_VOLUME_RIGHT_IN 75 +#define AB8500_CODEC_DEFAULT_VOLUME_LEFT_OUT 75 +#define AB8500_CODEC_DEFAULT_VOLUME_RIGHT_OUT 75 + +/*--------------------------------------------------------------------- + * PRIVATE APIs + *--------------------------------------------------------------------*/ +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch1(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch2(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch3(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch4(IN + t_ab8500_codec_slot + ad_slot, + IN + t_ab8500_codec_cr31_to_cr46_ad_data_allocation + value); +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch1(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state); +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch2(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state); +PRIVATE t_ab8500_codec_error ab8500_codec_SetModeAndDirectionUpdateCR(void); +PRIVATE t_ab8500_codec_error ab8500_codec_SetSrcVolumeUpdateCR(void); +PRIVATE t_ab8500_codec_error ab8500_codec_SetDestVolumeUpdateCR(void); +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionIN(void); +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionOUT(void); +PRIVATE t_ab8500_codec_error ab8500_codec_DestPowerControlUpdateCR(void); + +/********************************************************************************************/ +/* Name: ab8500_codec_SingleWrite */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_SingleWrite(t_uint8 + register_offset, + t_uint8 data) +{ + return (t_ab8500_codec_error) (AB8500_CODEC_Write + (register_offset, 0x01, &data)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_SingleRead */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_SingleRead(t_uint8 + register_offset, + t_uint8 data) +{ + t_uint8 dummy_data = 0xAA; + return (t_ab8500_codec_error) (AB8500_CODEC_Read + (register_offset, 0x01, &dummy_data, + &data)); +} + +#endif /* */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR0 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR0(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr0_powerup, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR0_POWERUP ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr0_enaana, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR0_ENAANA ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR0, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR1 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR1(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr1_swreset, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR1_SWRESET ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR1, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR2 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR2(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr2_enad1, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR2_ENAD1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr2_enad2, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR2_ENAD2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr2_enad3, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR2_ENAD3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr2_enad4, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR2_ENAD4 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr2_enad5, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR2_ENAD5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr2_enad6, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR2_ENAD6 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR2, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR3 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR3(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr3_enda1, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR3_ENDA1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr3_enda2, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR3_ENDA2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr3_enda3, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR3_ENDA3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr3_enda4, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR3_ENDA4 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr3_enda5, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR3_ENDA5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr3_enda6, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR3_ENDA6 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR3, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR4 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR4(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr4_lowpowhs, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR4_LOWPOWHS ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr4_lowpowdachs, + AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR4_LOWPOWDACHS ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr4_lowpowear, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR4_LOWPOWEAR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr4_ear_sel_cm, AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR4_EAR_SEL_CM ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr4_hs_hp_en, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR4_HS_HP_EN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR4, value)); +} + +#endif /* */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR5 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR5(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_enmic1, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_ENMIC1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_enmic2, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_ENMIC2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_enlinl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_ENLINL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_enlinr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_ENLINR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_mutmic1, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_MUTMIC1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_mutmic2, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_MUTMIC2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_mutlinl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_MUTELINL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr5_mutlinr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR5_MUTELINR ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR5, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR6 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR6(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr6_endmic1, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR6_ENDMIC1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr6_endmic2, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR6_ENDMIC2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr6_endmic3, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR6_ENDMIC3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr6_endmic4, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR6_ENDMIC4 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr6_endmic5, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR6_ENDMIC5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr6_endmic6, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR6_ENDMIC6 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR6, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR7 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR7(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr7_mic1sel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR7_MIC1SEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr7_linrsel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR7_LINRSEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr7_endrvhsl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR7_ENDRVHSL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr7_endrvhsr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR7_ENDRVHSR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr7_enadcmic, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR7_ENADCMIC ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr7_enadclinl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR7_ENADCLINL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr7_enadclinr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR7_ENADCLINR ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR7, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR8 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR8(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_cp_dis_pldwn, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_CP_DIS_PLDWN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_enear, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_ENEAR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_enhsl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_ENHSL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_enhsr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_ENHSR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_enhfl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_ENHFL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_enhfr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_ENHFR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_envibl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_ENVIBL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr8_envibr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR8_ENVIBR ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR8, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR9 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR9(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr9_endacear, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR9_ENADACEAR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr9_endachsl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR9_ENADACHSL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr9_endachsr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR9_ENADACHSR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr9_endachfl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR9_ENADACHFL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr9_endachfr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR9_ENADACHFR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr9_endacvibl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR9_ENADACVIBL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr9_endacvibr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR9_ENADACVIBR ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR9, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR10 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR10(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr10_muteear, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR10_MUTEEAR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr10_mutehsl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR10_MUTEHSL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr10_mutehsr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR10_MUTEHSR ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR10, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR11 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR11(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr11_earshortpwd, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR11_ENSHORTPWD ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr11_earshortdis, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR11_EARSHORTDIS ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr11_hsshortdis, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR11_HSSHORTDIS ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr11_hspullden, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR11_HSPULLDEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr11_hsoscen, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR11_HSOSCEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr11_hsfaden, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR11_HSFADEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr11_hszcddis, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR11_HSZCDDIS ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR11, value)); +} + +#endif /* */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR12 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR12(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr12_encphs, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR12_ENCPHS ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr12_hsautoen, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR12_HSAUTOEN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR12, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR13 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR13(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr13_envdet_hthresh, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR13_ENVDET_HTHRESH ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr13_envdet_lthresh, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR13_ENVDET_LTHRESH ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR13, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR14 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR14(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr14_smpslven, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR14_SMPSLVEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr14_envdetsmpsen, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR14_ENVDETSMPSEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr14_cplven, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR14_CPLVEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr14_envdetcpen, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR14_ENVDETCPEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr14_envet_time, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR14_ENVDET_TIME ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR14, value)); +} + +#endif /* */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR15 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR15(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmtovibl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMTOVIBL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmtovibr, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMTOVIBR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmlctrl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMLCTRL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmrctrl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMRCTRL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmnlctrl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMNLCTRL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmplctrl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMPLCTRL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmnrctrl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMNRCTRL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr15_pwmprctrl, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR15_PWMPRCTRL ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR15, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR16 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR16(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr16_pwmnlpol, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR16_PWMNLPOL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr16_pwmnldutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, + AB8500_CODEC_CR16_PWMNLDUTYCYCLE ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR16, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR17 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR17(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr17_pwmplpol, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR17_PWMPLPOL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr17_pwmpldutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, + AB8500_CODEC_CR17_PWMLPDUTYCYCLE ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR17, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR18 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR18(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr18_pwmnrpol, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR18_PWMNRPOL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr18_pwmnrdutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, + AB8500_CODEC_CR18_PWMNRDUTYCYCLE ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR18, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR19 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR19(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr19_pwmprpol, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR19_PWMPRPOL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr19_pwmprdutycycle, + AB8500_CODEC_MASK_SEVEN_BITS, + AB8500_CODEC_CR19_PWMRPDUTYCYCLE ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR19, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR20 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR20(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr20_en_se_mic1, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR20_EN_SE_MIC1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr20_low_pow_mic1, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR20_LOW_POW_MIC1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr20_mic1_gain, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR20_MIC1_GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR20, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR21 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR21(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr21_en_se_mic2, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR21_EN_SE_MIC2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr21_low_pow_mic2, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR21_LOW_POW_MIC2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr21_mic2_gain, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR21_MIC2_GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR21, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR22 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR22(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr22_hsl_gain, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR22_HSL_GAIN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr22_hsr_gain, AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR22_HSR_GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR22, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR23 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR23(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr23_linl_gain, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR23_LINL_GAIN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr23_linr_gain, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR23_LINR_GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR23, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR24 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR24(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr24_lintohsl_gain, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR24_LINTOHSL_GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR24, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR25 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR25(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr25_lintohsr_gain, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR25_LINTOHSR_GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR25, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR26 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR26(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad1nh, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD1NH ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad2nh, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD2NH ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad3nh, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD3NH ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad4nh, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD4NH ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad1_voice, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD1_VOICE ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad2_voice, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD2_VOICE ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad3_voice, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD3_VOICE ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr26_ad4_voice, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR26_AD4_VOICE ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR26, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR27 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR27(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr27_en_mastgen, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR27_EN_MASTGEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr27_if1_bitclk_osr, + AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR27_IF1_BITCLK_OSR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr27_enfs_bitclk1, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR27_ENFS_BITCLK1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr27_if0_bitclk_osr, + AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR27_IF0_BITCLK_OSR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr27_enfs_bitclk0, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR27_ENFS_BITCLK0 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR27, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR28 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR28(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr28_fsync0p, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR28_FSYNC0P ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr28_bitclk0p, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR28_BITCLK0P ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr28_if0del, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR28_IF0DEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr28_if0format, AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR28_IF0FORMAT ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr28_if0wl, AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR28_IF0WL ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR28, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR29 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR29(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr29_if0datoif1ad, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR29_IF0DATOIF1AD ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr29_if0cktoif1ck, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR29_IF0CKTOIF1CK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr29_if1master, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR29_IF1MASTER ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr29_if1datoif0ad, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR29_IF1DATOIF0AD ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr29_if1cktoif0ck, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR29_IF1CKTOIF0CK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr29_if0master, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR29_IF0MASTER ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr29_if0bfifoen, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR29_IF0BFIFOEN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR29, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR30 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR30(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr30_fsync1p, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR30_FSYNC1P ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr30_bitclk1p, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR30_BITCLK1P ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr30_if1del, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR30_IF1DEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr30_if1format, AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR30_IF1FORMAT ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr30_if1wl, AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR30_IF1WL ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR30, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR31 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR31(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr31_adotoslot1, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR31_ADOTOSLOT1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr31_adotoslot0, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR31_ADOTOSLOT0 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR31, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR32 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR32(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr32_adotoslot3, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR32_ADOTOSLOT3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr32_adotoslot2, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR32_ADOTOSLOT2 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR32, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR33 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR33(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr33_adotoslot5, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR33_ADOTOSLOT5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr33_adotoslot4, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR33_ADOTOSLOT4 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR33, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR34 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR34(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr34_adotoslot7, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR34_ADOTOSLOT7 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr34_adotoslot6, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR34_ADOTOSLOT6 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR34, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR35 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR35(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr35_adotoslot9, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR35_ADOTOSLOT9 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr35_adotoslot8, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR35_ADOTOSLOT8 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR35, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR36 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR36(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr36_adotoslot11, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR36_ADOTOSLOT11 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr36_adotoslot10, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR36_ADOTOSLOT10 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR36, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR37 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR37(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr37_adotoslot13, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR37_ADOTOSLOT13 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr37_adotoslot12, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR37_ADOTOSLOT12 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR37, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR38 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR38(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr38_adotoslot15, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR38_ADOTOSLOT15 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr38_adotoslot14, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR38_ADOTOSLOT14 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR38, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR39 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR39(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr39_adotoslot17, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR39_ADOTOSLOT17 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr39_adotoslot16, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR39_ADOTOSLOT16 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR39, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR40 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR40(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr40_adotoslot19, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR40_ADOTOSLOT19 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr40_adotoslot18, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR40_ADOTOSLOT18 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR40, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR41 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR41(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr41_adotoslot21, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR41_ADOTOSLOT21 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr41_adotoslot20, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR41_ADOTOSLOT20 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR41, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR42 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR42(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr42_adotoslot23, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR42_ADOTOSLOT23 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr42_adotoslot22, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR42_ADOTOSLOT22 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR42, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR43 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR43(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr43_adotoslot25, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR43_ADOTOSLOT25 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr43_adotoslot24, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR43_ADOTOSLOT24 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR43, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR44 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR44(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr44_adotoslot27, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR44_ADOTOSLOT27 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr44_adotoslot26, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR44_ADOTOSLOT26 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR44, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR45 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR45(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr45_adotoslot29, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR45_ADOTOSLOT29 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr45_adotoslot28, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR45_ADOTOSLOT28 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR45, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR46 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR46(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr46_adotoslot31, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR46_ADOTOSLOT31 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr46_adotoslot30, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR46_ADOTOSLOT30 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR46, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR47 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR47(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl7, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL7 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl6, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL6 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl5, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl4, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL4 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl3, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl2, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl1, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr47_hiz_sl0, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR47_HIZ_SL0 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR47, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR48 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR48(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl15, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL15 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl14, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL14 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl13, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL13 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl12, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL12 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl11, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL11 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl10, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL10 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl9, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL9 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr48_hiz_sl8, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR48_HIZ_SL8 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR48, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR49 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR49(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl23, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL23 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl22, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL22 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl21, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL21 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl20, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL20 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl19, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL19 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl18, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL18 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl17, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL17 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr49_hiz_sl16, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR49_HIZ_SL16 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR49, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR50 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR50(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl31, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL31 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl30, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL30 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl29, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL29 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl28, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL28 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl27, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL27 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl26, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL26 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl25, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL25 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr50_hiz_sl24, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR50_HIZ_SL24 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR50, value)); +} + +#endif /* */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR51 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR51(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr51_da12_voice, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR51_DA12_VOICE ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr51_swapda12_34, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR51_SWAP_DA12_34 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr51_sldai7toslado1, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR51_SLDAI7TOSLADO1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr51_sltoda1, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR51_SLTODA1 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR51, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR52 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR52(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr52_sldai8toslado2, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR52_SLDAI8TOSLADO2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr52_sltoda2, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR52_SLTODA2 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR52, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR53 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR53(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr53_da34_voice, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR53_DA34_VOICE ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr53_sldai7toslado3, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR53_SLDAI7TOSLADO3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr53_sltoda3, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR53_SLTODA3 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR53, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR54 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR54(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr54_sldai8toslado4, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR54_SLDAI8TOSLADO4 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr54_sltoda4, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR54_SLTODA4 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR54, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR55 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR55(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr55_da56_voice, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR55_DA56_VOICE ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr55_sldai7toslado5, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR55_SLDAI7TOSLADO5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr55_sltoda5, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR55_SLTODA5 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR55, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR56 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR56(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr56_sldai8toslado6, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR56_SLDAI8TOSLADO6 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr56_sltoda6, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR56_SLTODA6 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR56, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR57 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR57(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr57_sldai8toslado7, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR57_SLDAI8TOSLADO7 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr57_sltoda7, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR57_SLTODA7 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR57, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR58 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR58(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr58_sldai7toslado8, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR58_SLDAI7TOSLADO8 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr58_sltoda8, AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR58_SLTODA8 ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR58, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR59 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR59(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr59_parlhf, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR59_PARLHF ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr59_parlvib, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR59_PARLVIB ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr59_classdvib1_swapen, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR59_CLASSDVIB1SWAPEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr59_classdvib2_swapen, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR59_CLASSDVIB2SWAPEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr59_classdhfl_swapen, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR59_CLASSDHFLSWAPEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr59_classdhfr_swapen, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR59_CLASSDHFRSWAPEN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR59, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR60 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR60(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr60_classd_firbyp, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR60_CLASSD_FIR_BYP ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr60_classd_highvolen, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR60_CLASSD_HIGHVOL_EN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR60, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR61 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR61(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + + /* 5 bits are Read Only */ + AB8500_CODEC_WRITE_BITS + (value, + (t_uint8) p_ab8500_codec_configuration->cr61_classddith_hpgain, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR61_CLASSD_DITH_HPGAIN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr61_classddith_wgain, + AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR61_CLASSD_DITH_WGAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR61, value)); +} + +#endif /* */ + +/* CR62 is Read Only */ +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR63 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR63(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_datohslen, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_DATOHSLEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_datohsren, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_DATOHSREN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_ad1sel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_AD1SEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_ad2sel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_AD2SEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_ad3sel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_AD3SEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_ad5sel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_AD5SEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_ad6sel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_AD6SEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr63_ancsel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR63_ANCSEL ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR63, value)); +} + +#if 0 +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR64 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR64(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr64_datohfren, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR64_DATOHFREN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr64_datohflen, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR64_DATOHFLEN ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr64_hfrsel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR64_HFRSEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr64_hflsel, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR64_HFLSEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr64_stfir1sel, AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR64_STFIR1SEL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr64_stfir2sel, AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR64_STFIR2SEL ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR64, value)); +} + +#endif /* */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR65 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR65(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr65_fadedis_ad1, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR65_FADEDIS_AD1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr65_ad1gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR65_AD1GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR65, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR66 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR66(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr66_fadedis_ad2, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR66_FADEDIS_AD2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr66_ad2gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR66_AD2GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR66, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR67 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR67(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr67_fadedis_ad3, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR67_FADEDIS_AD3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr67_ad3gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR67_AD3GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR67, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR68 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR68(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr68_fadedis_ad4, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR68_FADEDIS_AD4 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr68_ad4gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR68_AD4GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR68, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR69 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR69(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr69_fadedis_ad5, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR69_FADEDIS_AD5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr69_ad5gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR69_AD5GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR69, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR70 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR70(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr70_fadedis_ad6, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR70_FADEDIS_AD6 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr70_ad6gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR70_AD6GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR70, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR71 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR71(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr71_fadedis_da1, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR71_FADEDIS_DA1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr71_da1gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR71_DA1GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR71, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR72 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR72(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr72_fadedis_da2, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR72_FADEDIS_DA2 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr72_da2gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR72_DA2GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR72, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR73 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR73(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr73_fadedis_da3, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR73_FADEDIS_DA3 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr73_da3gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR73_DA3GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR73, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR74 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR74(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr74_fadedis_da4, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR74_FADEDIS_DA4 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr74_da4gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR74_DA4GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR74, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR75 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR75(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr75_fadedis_da5, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR75_FADEDIS_DA5 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr75_da5gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR75_DA5GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR75, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR76 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR76(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr76_fadedis_da6, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR76_FADEDIS_DA6 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr76_da6gain, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR76_DA6GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR76, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR77 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR77(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr77_fadedis_ad1l, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR77_FADEDIS_AD1L ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr77_ad1lbgain_to_hfl, + AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR77_AD1LBGAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR77, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR78 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR78(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr78_fadedis_ad2l, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR78_FADEDIS_AD2L ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr78_ad2lbgain_to_hfr, + AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR78_AD2LBGAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR78, value)); +} + +#endif /* */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR79 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR79(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr79_hssinc1, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR79_HSSINC1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr79_fadedis_hsl, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR79_FADEDIS_HSL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr79_hsldgain, AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR79_HSLDGAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR79, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR80 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR80(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr80_fade_speed, + AB8500_CODEC_MASK_TWO_BITS, + AB8500_CODEC_CR80_FADE_SPEED ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr80_fadedis_hsr, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR80_FADEDIS_HSR ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr80_hsrdgain, AB8500_CODEC_MASK_FOUR_BITS, + AB8500_CODEC_CR80_HSRDGAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR80, value)); +} + +#if 0 + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR81 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR81(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr81_stfir1gain, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR81_STFIR1GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR81, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR82 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR82(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr82_stfir2gain, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR82_STFIR2GAIN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR82, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR83 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR83(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr83_enanc, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR83_ENANC ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr83_anciirinit, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR83_ANCIIRINIT ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr83_ancfirupdate, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR83_ANCFIRUPDATE ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR83, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR84 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR84(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr84_ancinshift, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR84_ANCINSHIFT ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR84, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR85 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR85(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr85_ancfiroutshift, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR85_ANCFIROUTSHIFT ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR85, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR86 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR86(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr86_ancshiftout, + AB8500_CODEC_MASK_FIVE_BITS, + AB8500_CODEC_CR86_ANCSHIFTOUT ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR86, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR87 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR87(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr87_ancfircoeff_msb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR87_ANCFIRCOEFF_MSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR87, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR88 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR88(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr88_ancfircoeff_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR88_ANCFIRCOEFF_LSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR88, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR89 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR89(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr89_anciircoeff_msb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR89_ANCIIRCOEFF_MSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR89, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR90 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR90(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr90_anciircoeff_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR90_ANCIIRCOEFF_LSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR90, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR91 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR91(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr91_ancwarpdel_msb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR91_ANCWARPDEL_MSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR91, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR92 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR92(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr92_ancwarpdel_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR92_ANCWARPDEL_LSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR92, value)); +} + +/* CR93 is Read Only */ +/* CR94 is Read Only */ +/* CR95 is Read Only */ +/* CR96 is Read Only */ +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR97 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR97(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr97_stfir_set, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR97_STFIR_SET ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr97_stfir_addr, + AB8500_CODEC_MASK_SEVEN_BITS, + AB8500_CODEC_CR97_STFIR_ADDR ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR97, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR98 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR98(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr98_stfir_coeff_msb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR98_STFIR_COEFF_MSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR98, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR99 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR99(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr99_stfir_coeff_lsb, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR99_STFIR_COEFF_LSB ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR99, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR100 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR100(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr100_enstfirs, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR100_ENSTFIRS ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr100_stfirstoif1, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR100_STFIRSTOIF1 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr100_stfir_busy, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR100_STFIR_BUSY ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR100, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR101 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR101(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_hsoffst_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_HSOFFSTMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_fifofull_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_FIFOFULLMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_fifoempty_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_FIFOEMPTYMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_dasat_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_DASATMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_adsat_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_ADSATMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_addsp_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_ADDSPMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_dadsp_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_DADSPMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr101_firsid_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR101_FIRSIDMASK ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR101, value)); +} + +/* CR102 is Read Only */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR103 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR103(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr103_vssready_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR103_VSSREADYMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr103_shorthsl_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR103_SHORTHSLMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr103_shorthsr_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR103_SHORTHSRMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr103_shortear_mask, + AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR103_SHORTEARMASK ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR103, value)); +} + +#endif /* */ + +/* CR104 is Read Only */ + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR105 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR105(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr105_bfifomsk, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR105_BFIFOMASK ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr105_bfifoint, AB8500_CODEC_MASK_SIX_BITS, + AB8500_CODEC_CR105_BFIFOINT ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR105, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR106 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR106(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr106_bfifotx, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR106_BFIFOTX ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR106, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR107 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR107(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr107_bfifoexsl, + AB8500_CODEC_MASK_THREE_BITS, + AB8500_CODEC_CR107_BFIFOEXSL ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr107_prebitclk0, + AB8500_CODEC_MASK_THREE_BITS, + AB8500_CODEC_CR107_PREBITCLK0 ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr107_bfifomast, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR107_BFIFOMAST ); + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr107_bfiforun, AB8500_CODEC_MASK_ONE_BIT, + AB8500_CODEC_CR107_BFIFORUN ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR107, value)); +} + + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR108 */ +/********************************************************************************************/ + PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR108(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr108_bfifoframsw, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR108_BFIFOFRAMESW ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR108, value)); +} + +/********************************************************************************************/ +/* Name: ab8500_codec_UpdateCR109 */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_UpdateCR109(void) +{ + t_uint8 value = 0x00; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + AB8500_CODEC_WRITE_BITS (value, + (t_uint8) p_ab8500_codec_configuration-> + cr109_bfifowakeup, + AB8500_CODEC_MASK_EIGHT_BITS, + AB8500_CODEC_CR109_BFIFOWAKEUP ); + return (ab8500_codec_SingleWrite(AB8500_CODEC_CR109, value)); +} + +/* CR110 is Read Only */ + +/* CR111 is Read Only */ + +/********************************************************************************************/ +/* Name: ab8500_codec_Reset() */ + +/********************************************************************************************/ +PRIVATE t_ab8500_codec_error ab8500_codec_Reset(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + p_ab8500_codec_configuration->cr1_swreset = + AB8500_CODEC_CR1_SWRESET_ENABLED; + ab8500_codec_error = ab8500_codec_UpdateCR1(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirection(IN + t_ab8500_codec_direction + ab8500_codec_direction) + /*only IN or OUT must be passed (not INOUT) */ +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + if (AB8500_CODEC_DIRECTION_IN == ab8500_codec_direction) + { + ab8500_codec_error = ab8500_codec_ProgramDirectionIN(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + if (AB8500_CODEC_DIRECTION_OUT == ab8500_codec_direction) + { + ab8500_codec_error = ab8500_codec_ProgramDirectionOUT(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetDirection(IN + t_ab8500_codec_direction + ab8500_codec_direction) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + switch (ab8500_codec_direction) + { + case AB8500_CODEC_DIRECTION_IN: + ab8500_codec_error = + ab8500_codec_ProgramDirection(AB8500_CODEC_DIRECTION_IN); + break; + case AB8500_CODEC_DIRECTION_OUT: + ab8500_codec_error = + ab8500_codec_ProgramDirection(AB8500_CODEC_DIRECTION_OUT); + break; + case AB8500_CODEC_DIRECTION_INOUT: + ab8500_codec_error = + ab8500_codec_ProgramDirection(AB8500_CODEC_DIRECTION_IN); + if (AB8500_CODEC_OK == ab8500_codec_error) + { + ab8500_codec_error = + ab8500_codec_ProgramDirection + (AB8500_CODEC_DIRECTION_OUT); + } + break; + } + if (ab8500_codec_error != AB8500_CODEC_OK) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR5(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR6(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR7(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR8(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR9(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR10(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR12(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR15(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR63(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_Init */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Initialize the global variables & stores the slave address of codec. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* slave_address_of_ab8500_codec: Audio codec slave address */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* Returns AB8500_CODEC_OK */ +/* COMMENTS: */ +/* 1) Saves the supplied slave_address_of_codec in global variable */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_Init(IN t_uint8 + slave_address_of_ab8500_codec) +{ + DBGENTER1(" (%lx)", slave_address_of_ab8500_codec); + g_ab8500_codec_system_context.slave_address_of_ab8500_codec = + slave_address_of_ab8500_codec; + DBGEXIT(AB8500_CODEC_OK); + return (AB8500_CODEC_OK); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_Reset */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Reset the global variables and clear audiocodec settings to default. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_Reset(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER(); + g_ab8500_codec_system_context.ab8500_codec_direction = + AB8500_CODEC_DEFAULT_DIRECTION; + g_ab8500_codec_system_context.ab8500_codec_mode_in = + AB8500_CODEC_DEFAULT_MODE_IN; + g_ab8500_codec_system_context.ab8500_codec_mode_out = + AB8500_CODEC_DEFAULT_MODE_OUT; + g_ab8500_codec_system_context.ab8500_codec_src = + AB8500_CODEC_DEFAULT_INPUT_SRC; + g_ab8500_codec_system_context.ab8500_codec_dest = + AB8500_CODEC_DEFAULT_OUTPUT_DEST; + g_ab8500_codec_system_context.in_left_volume = + AB8500_CODEC_DEFAULT_VOLUME_LEFT_IN; + g_ab8500_codec_system_context.in_right_volume = + AB8500_CODEC_DEFAULT_VOLUME_RIGHT_IN; + g_ab8500_codec_system_context.out_left_volume = + AB8500_CODEC_DEFAULT_VOLUME_LEFT_OUT; + g_ab8500_codec_system_context.out_right_volume = + AB8500_CODEC_DEFAULT_VOLUME_RIGHT_OUT; + ab8500_codec_error = ab8500_codec_Reset(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetModeAndDirection */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Configures the whole audio codec to work in audio mode */ +/* (using I2S protocol). */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* direction: select the direction (IN, OUT or INOUT) */ +/* in_mode: codec mode for recording. If direction is OUT only, */ +/* this parameter is ignored. */ +/* out_mode: codec mode for playing. If direction is IN only, */ +/* this parameter is ignored. */ +/* p_tdm_config: TDM configuration required to be configured by user */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: The API may not allow setting */ +/* 2 different modes, in which case it should return this value. */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetModeAndDirection + (IN t_ab8500_codec_direction ab8500_codec_direction, + IN t_ab8500_codec_mode ab8500_codec_mode_in, + IN t_ab8500_codec_mode ab8500_codec_mode_out, + IN t_ab8500_codec_tdm_config const *const p_tdm_config ) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + DBGENTER3(" (%lx %lx %lx)", ab8500_codec_direction, + ab8500_codec_mode_in, ab8500_codec_mode_out); + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) + { + if (AB8500_CODEC_DIRECTION_OUT == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == + ab8500_codec_direction ) + { + p_ab8500_codec_configuration->cr3_enda1 = + AB8500_CODEC_CR3_ENDA1_ENABLED; + p_ab8500_codec_configuration->cr3_enda2 = + AB8500_CODEC_CR3_ENDA2_ENABLED; + p_ab8500_codec_configuration->cr3_enda3 = + AB8500_CODEC_CR3_ENDA3_ENABLED; + p_ab8500_codec_configuration->cr3_enda4 = + AB8500_CODEC_CR3_ENDA4_ENABLED; + p_ab8500_codec_configuration->cr3_enda5 = + AB8500_CODEC_CR3_ENDA5_ENABLED; + p_ab8500_codec_configuration->cr3_enda6 = + AB8500_CODEC_CR3_ENDA6_ENABLED; + p_ab8500_codec_configuration->cr27_if1_bitclk_osr = + p_tdm_config->cr27_if1_bitclk_osr; + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_out) + { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } + + else + { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_TDM; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } + } + if (AB8500_CODEC_DIRECTION_IN == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == + ab8500_codec_direction ) + { + p_ab8500_codec_configuration->cr2_enad1 = + AB8500_CODEC_CR2_ENAD1_ENABLED; + p_ab8500_codec_configuration->cr2_enad2 = + AB8500_CODEC_CR2_ENAD2_ENABLED; + p_ab8500_codec_configuration->cr2_enad3 = + AB8500_CODEC_CR2_ENAD3_ENABLED; + p_ab8500_codec_configuration->cr2_enad4 = + AB8500_CODEC_CR2_ENAD4_ENABLED; + p_ab8500_codec_configuration->cr2_enad5 = + AB8500_CODEC_CR2_ENAD5_ENABLED; + p_ab8500_codec_configuration->cr2_enad6 = + AB8500_CODEC_CR2_ENAD6_ENABLED; + p_ab8500_codec_configuration->cr27_if1_bitclk_osr = + p_tdm_config->cr27_if1_bitclk_osr; + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_in) + { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } + + else + { + p_ab8500_codec_configuration->cr30_fsync1p = + AB8500_CODEC_CR30_FSYNC1P_RISING_EDGE; + p_ab8500_codec_configuration->cr30_bitclk1p = + AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE; + p_ab8500_codec_configuration->cr30_if1del = + AB8500_CODEC_CR30_IF1DEL_NOT_DELAYED; + p_ab8500_codec_configuration->cr30_if1format = + AB8500_CODEC_CR30_IF1FORMAT_TDM; + p_ab8500_codec_configuration->cr30_if1wl = + p_tdm_config->cr30_if1wl; + } + } + } + + else + { + if (AB8500_CODEC_DIRECTION_OUT == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == + ab8500_codec_direction ) + { + p_ab8500_codec_configuration->cr3_enda1 = + AB8500_CODEC_CR3_ENDA1_ENABLED; + p_ab8500_codec_configuration->cr3_enda2 = + AB8500_CODEC_CR3_ENDA2_ENABLED; + p_ab8500_codec_configuration->cr3_enda3 = + AB8500_CODEC_CR3_ENDA3_ENABLED; + p_ab8500_codec_configuration->cr3_enda4 = + AB8500_CODEC_CR3_ENDA4_ENABLED; + p_ab8500_codec_configuration->cr3_enda5 = + AB8500_CODEC_CR3_ENDA5_ENABLED; + p_ab8500_codec_configuration->cr3_enda6 = + AB8500_CODEC_CR3_ENDA6_ENABLED; + p_ab8500_codec_configuration->cr27_if0_bitclk_osr = + p_tdm_config->cr27_if0_bitclk_osr; + p_ab8500_codec_configuration->cr63_datohslen = + AB8500_CODEC_CR63_DATOHSLEN_ENABLED; + p_ab8500_codec_configuration->cr63_datohsren = + AB8500_CODEC_CR63_DATOHSREN_ENABLED; + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_out) + { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } + + else + { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_TDM; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } + } + if (AB8500_CODEC_DIRECTION_IN == ab8500_codec_direction + || AB8500_CODEC_DIRECTION_INOUT == + ab8500_codec_direction ) + { + p_ab8500_codec_configuration->cr2_enad1 = + AB8500_CODEC_CR2_ENAD1_ENABLED; + p_ab8500_codec_configuration->cr2_enad2 = + AB8500_CODEC_CR2_ENAD2_ENABLED; + p_ab8500_codec_configuration->cr2_enad3 = + AB8500_CODEC_CR2_ENAD3_ENABLED; + p_ab8500_codec_configuration->cr2_enad4 = + AB8500_CODEC_CR2_ENAD4_ENABLED; + p_ab8500_codec_configuration->cr2_enad5 = + AB8500_CODEC_CR2_ENAD5_ENABLED; + p_ab8500_codec_configuration->cr2_enad6 = + AB8500_CODEC_CR2_ENAD6_ENABLED; + p_ab8500_codec_configuration->cr26_ad1_voice = + AB8500_CODEC_CR26_AD1_VOICE_LOWLATENCYFILTER; + p_ab8500_codec_configuration->cr26_ad2_voice = + AB8500_CODEC_CR26_AD2_VOICE_LOWLATENCYFILTER; + p_ab8500_codec_configuration->cr26_ad3_voice = + AB8500_CODEC_CR26_AD3_VOICE_LOWLATENCYFILTER; + p_ab8500_codec_configuration->cr26_ad4_voice = + AB8500_CODEC_CR26_AD4_VOICE_LOWLATENCYFILTER; + p_ab8500_codec_configuration->cr27_if0_bitclk_osr = + p_tdm_config->cr27_if0_bitclk_osr; + if (AB8500_CODEC_MODE_HIFI == ab8500_codec_mode_in) + { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } + + else + { + p_ab8500_codec_configuration->cr28_fsync0p = + AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE; + p_ab8500_codec_configuration->cr28_bitclk0p = p_tdm_config->cr28_bitclk0p; /*AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; */ + p_ab8500_codec_configuration->cr28_if0del = p_tdm_config->cr28_if0del; /*AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED; */ + p_ab8500_codec_configuration->cr28_if0format = + AB8500_CODEC_CR28_IF0FORMAT_TDM; + p_ab8500_codec_configuration->cr28_if0wl = + p_tdm_config->cr28_if0wl; + } + } + } + ab8500_codec_error = ab8500_codec_SetModeAndDirectionUpdateCR(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + g_ab8500_codec_system_context.ab8500_codec_direction = + ab8500_codec_direction; + g_ab8500_codec_system_context.ab8500_codec_mode_in = + ab8500_codec_mode_in; + g_ab8500_codec_system_context.ab8500_codec_mode_out = + ab8500_codec_mode_out; + ab8500_codec_error = + ab8500_codec_SetDirection(ab8500_codec_direction); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetSrcVolume */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Sets the record volumes. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* t_ab8500_codec_src: select source device for recording. */ +/* in_left_volume: record volume for left channel. */ +/* in_right_volume: record volume for right channel. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetSrcVolume + (IN t_ab8500_codec_src src_device, IN t_uint8 in_left_volume, + IN t_uint8 in_right_volume ) { + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + DBGENTER3(" (%lx %lx %lx)", src_device, in_left_volume, + in_right_volume); + if (in_left_volume > AB8500_CODEC_MAX_VOLUME) + { + in_left_volume = AB8500_CODEC_MAX_VOLUME; + } + if (in_right_volume > AB8500_CODEC_MAX_VOLUME) + { + in_right_volume = AB8500_CODEC_MAX_VOLUME; + } + g_ab8500_codec_system_context.in_left_volume = in_left_volume; + g_ab8500_codec_system_context.in_right_volume = in_right_volume; + p_ab8500_codec_configuration->cr65_ad1gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr66_ad2gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr67_ad3gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr68_ad4gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr69_ad5gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr70_ad6gain = + AB8500_CODEC_AD_D_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_AD_D_VOLUME_MAX - + AB8500_CODEC_AD_D_VOLUME_MIN)) / 100; + + /* Set mininimum volume if volume is zero */ + switch (src_device) + { + case AB8500_CODEC_SRC_LINEIN: + p_ab8500_codec_configuration->cr23_linl_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr23_linr_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_right_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + break; + case AB8500_CODEC_SRC_MICROPHONE_1A: + case AB8500_CODEC_SRC_MICROPHONE_1B: + p_ab8500_codec_configuration->cr20_mic1_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + break; + case AB8500_CODEC_SRC_MICROPHONE_2: + p_ab8500_codec_configuration->cr21_mic2_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_1: + break; + case AB8500_CODEC_SRC_D_MICROPHONE_2: + break; + case AB8500_CODEC_SRC_D_MICROPHONE_3: + break; + case AB8500_CODEC_SRC_D_MICROPHONE_4: + break; + case AB8500_CODEC_SRC_D_MICROPHONE_5: + break; + case AB8500_CODEC_SRC_D_MICROPHONE_6: + break; + case AB8500_CODEC_SRC_ALL: + p_ab8500_codec_configuration->cr23_linl_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr23_linr_gain = + AB8500_CODEC_LINEIN_VOLUME_MIN + + (in_right_volume * + (AB8500_CODEC_LINEIN_VOLUME_MAX - + AB8500_CODEC_LINEIN_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr20_mic1_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr21_mic2_gain = + AB8500_CODEC_MIC_VOLUME_MIN + + (in_left_volume * + (AB8500_CODEC_MIC_VOLUME_MAX - + AB8500_CODEC_MIC_VOLUME_MIN)) / 100; + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_SetSrcVolumeUpdateCR(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetDestVolume */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Sets the play volumes. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* out_left_volume: play volume for left channel. */ +/* out_right_volume: play volume for right channel. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetDestVolume + (IN t_ab8500_codec_dest dest_device, IN t_uint8 out_left_volume, + IN t_uint8 out_right_volume ) { + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + DBGENTER3(" (%lx %lx %lx)", dest_device, out_left_volume, + out_right_volume); + if (out_left_volume > AB8500_CODEC_MAX_VOLUME) + { + out_left_volume = AB8500_CODEC_MAX_VOLUME; + } + if (out_right_volume > AB8500_CODEC_MAX_VOLUME) + { + out_right_volume = AB8500_CODEC_MAX_VOLUME; + } + g_ab8500_codec_system_context.out_left_volume = out_left_volume; + g_ab8500_codec_system_context.out_right_volume = out_right_volume; + p_ab8500_codec_configuration->cr71_da1gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr72_da2gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr73_da3gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr74_da4gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr75_da5gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr76_da6gain = + AB8500_CODEC_DA_D_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_DA_D_VOLUME_MAX - + AB8500_CODEC_DA_D_VOLUME_MIN)) / 100; + + /* Set mininimum volume if volume is zero */ + switch (dest_device) + { + case AB8500_CODEC_DEST_HEADSET: + p_ab8500_codec_configuration->cr22_hsl_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr22_hsr_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr79_hsldgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + p_ab8500_codec_configuration->cr80_hsrdgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + break; + case AB8500_CODEC_DEST_EARPIECE: + p_ab8500_codec_configuration->cr79_hsldgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + break; + case AB8500_CODEC_DEST_HANDSFREE: + break; + case AB8500_CODEC_DEST_VIBRATOR_L: + p_ab8500_codec_configuration->cr16_pwmnldutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN; + p_ab8500_codec_configuration->cr17_pwmpldutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_VIBRATOR_VOLUME_MAX - + AB8500_CODEC_VIBRATOR_VOLUME_MIN)) / 100; + break; + case AB8500_CODEC_DEST_VIBRATOR_R: + p_ab8500_codec_configuration->cr18_pwmnrdutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN; + p_ab8500_codec_configuration->cr19_pwmprdutycycle = + AB8500_CODEC_VIBRATOR_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_VIBRATOR_VOLUME_MAX - + AB8500_CODEC_VIBRATOR_VOLUME_MIN)) / 100; + break; + case AB8500_CODEC_DEST_ALL: + p_ab8500_codec_configuration->cr22_hsl_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr22_hsr_gain = + AB8500_CODEC_HEADSET_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_HEADSET_VOLUME_MAX - + AB8500_CODEC_HEADSET_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr79_hsldgain = + AB8500_CODEC_HEADSET_D_VOLUME_0DB; + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_SetDestVolumeUpdateCR(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetMasterMode */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Set the Audio Codec in Master mode. */ +/* */ +/* ARGUMENTS */ +/* IN: t_codec_master_mode: Enable/disable master mode */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: Call this API after calling AB8500_CODEC_SetModeAndDirection() API*/ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetMasterMode(IN + t_ab8500_codec_master_mode + mode) +{ + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) + { + p_ab8500_codec_configuration->cr27_en_mastgen = + AB8500_CODEC_CR27_EN_MASTGEN_ENABLED; + p_ab8500_codec_configuration->cr27_enfs_bitclk1 = + AB8500_CODEC_CR27_ENFS_BITCLK1_ENABLED; + if (AB8500_CODEC_MASTER_MODE_ENABLE == mode) + { + p_ab8500_codec_configuration->cr29_if1master = + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_OUTPUT; + } + + else + { + p_ab8500_codec_configuration->cr29_if1master = + AB8500_CODEC_CR29_IF1MASTER_FS1CK1_INPUT; + } + } + + else + { + p_ab8500_codec_configuration->cr27_en_mastgen = + AB8500_CODEC_CR27_EN_MASTGEN_ENABLED; + p_ab8500_codec_configuration->cr27_enfs_bitclk0 = + AB8500_CODEC_CR27_ENFS_BITCLK0_ENABLED; + if (AB8500_CODEC_MASTER_MODE_ENABLE == mode) + { + p_ab8500_codec_configuration->cr29_if0master = + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_OUTPUT; + } + + else + { + p_ab8500_codec_configuration->cr29_if0master = + AB8500_CODEC_CR29_IF0MASTER_FS0CK0_INPUT; + } + } + ab8500_codec_error = ab8500_codec_UpdateCR27(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR29(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SelectInput */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Select input source for recording. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* input_src: select input source for recording when several sources */ +/* are supported in codec. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If input_src provided is invalid */ +/* by the codec hardware in use. */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SelectInput(IN t_ab8500_codec_src + ab8500_codec_src) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER1(" (%lx)", ab8500_codec_src); + g_ab8500_codec_system_context.ab8500_codec_src = ab8500_codec_src; + ab8500_codec_error = + ab8500_codec_SetDirection(AB8500_CODEC_DIRECTION_IN); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SelectOutput */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Select output desination for playing. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* output_dest: select output destination for playing when several are */ +/* supported by codec hardware. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If output_src provided is invalid */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SelectOutput(IN t_ab8500_codec_dest + ab8500_codec_dest) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + g_ab8500_codec_system_context.ab8500_codec_dest = ab8500_codec_dest; + DBGENTER1(" (%lx)", ab8500_codec_dest); + ab8500_codec_error = + ab8500_codec_SetDirection(AB8500_CODEC_DIRECTION_OUT); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_PowerDown */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Shuts the audio codec down completely. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* OUT: */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_PowerDown(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + g_ab8500_codec_system_context.ab8500_codec_configuration.cr0_powerup = + AB8500_CODEC_CR0_POWERUP_OFF; + ab8500_codec_error = ab8500_codec_UpdateCR0(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_PowerUp */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Switch on the audio codec. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_PowerUp(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER(); + g_ab8500_codec_system_context.ab8500_codec_configuration.cr0_powerup = + AB8500_CODEC_CR0_POWERUP_ON; + g_ab8500_codec_system_context.ab8500_codec_configuration.cr0_enaana = + AB8500_CODEC_CR0_ENAANA_ON; + ab8500_codec_error = ab8500_codec_UpdateCR0(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SelectInterface */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Select the Audio Interface 0 or 1. */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_audio_interface: The selected interface */ +/* */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_OK: Always. */ +/* REMARK: Call this API before using a function of the low level drivers */ +/* to select the interface that you want to configure */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SelectInterface(IN + t_ab8500_codec_audio_interface + audio_interface) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + g_ab8500_codec_system_context.audio_interface = audio_interface; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_GetInterface */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Get the Audio Interface 0 or 1. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: p_audio_interface: Store the selected interface */ +/* RETURN: */ +/* AB8500_CODEC_OK: Always */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_GetInterface(OUT + t_ab8500_codec_audio_interface + * p_audio_interface) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + *p_audio_interface = g_ab8500_codec_system_context.audio_interface; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetAnalogLoopback */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Sets Line-In to HeadSet loopback with the required gain. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* out_left_volume: play volume for left channel. */ +/* out_right_volume: play volume for right channel. */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetAnalogLoopback(IN t_uint8 + out_left_volume, + IN t_uint8 + out_right_volume) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER2(" (%lx %lx)", out_left_volume, out_right_volume); + if (out_left_volume > AB8500_CODEC_MAX_VOLUME) + { + out_left_volume = AB8500_CODEC_MAX_VOLUME; + } + if (out_right_volume > AB8500_CODEC_MAX_VOLUME) + { + out_right_volume = AB8500_CODEC_MAX_VOLUME; + } + g_ab8500_codec_system_context.out_left_volume = out_left_volume; + g_ab8500_codec_system_context.out_right_volume = out_right_volume; + p_ab8500_codec_configuration->cr24_lintohsl_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN + + (out_left_volume * + (AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX - + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN)) / 100; + p_ab8500_codec_configuration->cr25_lintohsr_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN + + (out_right_volume * + (AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX - + AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN)) / 100; + ab8500_codec_error = ab8500_codec_UpdateCR24(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR25(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_RemoveAnalogLoopback */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Remove Line-In to HeadSet loopback. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_RemoveAnalogLoopback(void) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER0(); + p_ab8500_codec_configuration->cr24_lintohsl_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN; + p_ab8500_codec_configuration->cr25_lintohsr_gain = + AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN; + ab8500_codec_error = ab8500_codec_UpdateCR24(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR25(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_EnableBypassMode */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enables IF0 to IF1 path or vice versa */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_EnableBypassMode(void) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER0(); + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) + { + p_ab8500_codec_configuration->cr29_if1datoif0ad = + AB8500_CODEC_CR29_IF1DATOIF0AD_SENT; + p_ab8500_codec_configuration->cr29_if1cktoif0ck = + AB8500_CODEC_CR29_IF1CKTOIF0CK_SENT; + } + + else + { + p_ab8500_codec_configuration->cr29_if0datoif1ad = + AB8500_CODEC_CR29_IF0DATOIF1AD_SENT; + p_ab8500_codec_configuration->cr29_if0cktoif1ck = + AB8500_CODEC_CR29_IF0CKTOIF1CK_SENT; + } + ab8500_codec_error = ab8500_codec_UpdateCR29(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DisableBypassMode */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Disables IF0 to IF1 path or vice versa */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DisableBypassMode(void) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER0(); + if (AB8500_CODEC_AUDIO_INTERFACE_1 == + g_ab8500_codec_system_context.audio_interface) + { + p_ab8500_codec_configuration->cr29_if1datoif0ad = + AB8500_CODEC_CR29_IF1DATOIF0AD_NOTSENT; + p_ab8500_codec_configuration->cr29_if1cktoif0ck = + AB8500_CODEC_CR29_IF1CKTOIF0CK_NOTSENT; + } + + else + { + p_ab8500_codec_configuration->cr29_if0datoif1ad = + AB8500_CODEC_CR29_IF0DATOIF1AD_NOTSENT; + p_ab8500_codec_configuration->cr29_if0cktoif1ck = + AB8500_CODEC_CR29_IF0CKTOIF1CK_NOTSENT; + } + ab8500_codec_error = ab8500_codec_UpdateCR29(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SrcPowerControl */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enables/Disables & UnMute/Mute the desired source */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* t_ab8500_codec_src: select source device for enabling/disabling. */ +/* t_ab8500_codec_src_state: Enable/Disable */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_SrcPowerControl(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state) +{ + t_ab8500_codec_error ab8500_codec_error; + DBGENTER2(" (%lx %lx)", src_device, state); + if (src_device <= AB8500_CODEC_SRC_D_MICROPHONE_2) + { + ab8500_codec_error = + ab8500_codec_SrcPowerControlSwitch1(src_device, state); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else if (src_device <= AB8500_CODEC_SRC_ALL) + { + ab8500_codec_error = + ab8500_codec_SrcPowerControlSwitch2(src_device, state); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else + { + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR5(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR6(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR7(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR63(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DestPowerControl */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enables/Disables & UnMute/Mute the desired destination */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* t_ab8500_codec_dest: select destination device for enabling/disabling. */ +/* t_ab8500_codec_dest_state: Enable/Disable */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_TRANSACTION_FAILED: If transaction fails. */ +/* AB8500_CODEC_OK: if successful. */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DestPowerControl(IN + t_ab8500_codec_dest + dest_device, + t_ab8500_codec_dest_state + state) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context.ab8500_codec_configuration; + DBGENTER2(" (%lx %lx)", dest_device, state); + switch (dest_device) + { + case AB8500_CODEC_DEST_HEADSET: + if (AB8500_CODEC_DEST_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + p_ab8500_codec_configuration->cr9_endachsl = + AB8500_CODEC_CR9_ENDACHSL_ENABLED; + p_ab8500_codec_configuration->cr9_endachsr = + AB8500_CODEC_CR9_ENDACHSR_ENABLED; + } + + else + { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr9_endachsl = + AB8500_CODEC_CR9_ENDACHSL_DISABLED; + p_ab8500_codec_configuration->cr9_endachsr = + AB8500_CODEC_CR9_ENDACHSR_DISABLED; + } + break; + case AB8500_CODEC_DEST_EARPIECE: + if (AB8500_CODEC_DEST_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + } + + else + { + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_DISABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + } + break; + case AB8500_CODEC_DEST_HANDSFREE: + if (AB8500_CODEC_DEST_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + } + + else + { + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_DISABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_DISABLED; + } + break; + case AB8500_CODEC_DEST_VIBRATOR_L: + if (AB8500_CODEC_DEST_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + } + + else + { + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_DISABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL; + } + break; + case AB8500_CODEC_DEST_VIBRATOR_R: + if (AB8500_CODEC_DEST_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + } + + else + { + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_DISABLED; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL; + } + break; + case AB8500_CODEC_DEST_ALL: + if (AB8500_CODEC_DEST_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + } + + else + { + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_DISABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_DISABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL; + } + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_DestPowerControlUpdateCR(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_GetVersion */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* This routine populates the pVersion structure with */ +/* the current version of HCL. */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* p_version: this parameter is used to return current HCL version. */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_ERROR: if p_version is NULL. */ +/* AB8500_CODEC_OK: if successful */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_GetVersion(OUT t_version * p_version) +{ + DBGENTER1(" (%lx)", p_version); + if (p_version != NULL) + { + p_version->minor = AB8500_CODEC_HCL_MINOR_ID; + p_version->major = AB8500_CODEC_HCL_MAJOR_ID; + p_version->version = AB8500_CODEC_HCL_VERSION_ID; + DBGEXIT0(AB8500_CODEC_OK); + return (AB8500_CODEC_OK); + } + + else + { + DBGEXIT0(AB8500_CODEC_INVALID_PARAMETER); + return (AB8500_CODEC_INVALID_PARAMETER); + } +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_SetDbgLevel */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Set the debug level used by the debug module (mask-like value). */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* debug_level: debug level to be set */ +/* OUT: */ +/* None */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_OK: always */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +/* +PUBLIC t_ab8500_codec_error AB8500_CODEC_SetDbgLevel(IN t_dbg_level dbg_level) +{ + DBGENTER1(" (%d)", dbg_level); + dbg_level = dbg_level; +#ifdef __DEBUG + MY_DEBUG_LEVEL_VAR_NAME = dbg_level; +#endif + DBGEXIT(AB8500_CODEC_OK); + return(AB8500_CODEC_OK); +} + */ + +/****************************************************************************/ +/* NAME: AB8500_CODEC_GetDbgLevel */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Set the debug level used by the debug module (mask-like value). */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* p_dbg_level: this parameter is used to return debug level. */ +/* */ +/* RETURN: */ +/* AB8500_CODEC_ERROR: if p_version is NULL. */ +/* AB8500_CODEC_OK: if successful */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Re-Entrant */ +/* REENTRANCY ISSUES: No Issues */ + +/****************************************************************************/ +/* +PUBLIC t_ab8500_codec_error AB8500_CODEC_GetDbgLevel(OUT t_dbg_level *p_dbg_level) +{ + if (NULL == p_dbg_level) + { + DBGEXIT(AB8500_CODEC_INVALID_PARAMETER); + return(AB8500_CODEC_INVALID_PARAMETER); + } + +#ifdef __DEBUG + * p_dbg_level = MY_DEBUG_LEVEL_VAR_NAME; +#endif + DBGEXIT(AB8500_CODEC_OK); + return(AB8500_CODEC_OK); +} +*/ +/****************************************************************************/ +/* NAME: AB8500_CODEC_ADSlotAllocation */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* AD Data Allocation in slots. */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_slot: The slot to be allocated. */ +/* IN: t_ab8500_codec_cr31_to_cr46_ad_data_allocation: The value */ +/* to be allocated. */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If invalid slot number */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_ADSlotAllocation + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value ) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER2(" (%lx %lx)", ad_slot, value); + if (ad_slot <= AB8500_CODEC_SLOT7) + { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch1(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else if (ad_slot <= AB8500_CODEC_SLOT15) + { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch2(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else if (ad_slot <= AB8500_CODEC_SLOT23) + { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch3(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else if (ad_slot <= AB8500_CODEC_SLOT31) + { + ab8500_codec_error = + ab8500_codec_ADSlotAllocationSwitch4(ad_slot, value); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else + { + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DASlotAllocation */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Allocate the Audio Interface slot for DA paths. */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_da_channel_number: Channel number 1/2/3/4/5/6 */ +/* IN: t_ab8500_codec_cr51_to_cr56_sltoda: Slot number */ +/* */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If invalid channel number */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DASlotAllocation + (IN t_ab8500_codec_da_channel_number channel_number, + IN t_ab8500_codec_cr51_to_cr58_sltoda slot ) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + t_ab8500_codec_cr0_powerup ab8500_codec_cr0_powerup; + DBGENTER2(" (%lx %lx)", channel_number, slot); + p_ab8500_codec_configuration->cr51_da12_voice = + AB8500_CODEC_CR51_DA12_VOICE_LOWLATENCYFILTER; + switch (channel_number) + { + case AB8500_CODEC_DA_CHANNEL_NUMBER_1: + p_ab8500_codec_configuration->cr51_sltoda1 = slot; + break; + case AB8500_CODEC_DA_CHANNEL_NUMBER_2: + p_ab8500_codec_configuration->cr52_sltoda2 = slot; + break; + case AB8500_CODEC_DA_CHANNEL_NUMBER_3: + p_ab8500_codec_configuration->cr53_sltoda3 = slot; + break; + case AB8500_CODEC_DA_CHANNEL_NUMBER_4: + p_ab8500_codec_configuration->cr54_sltoda4 = slot; + break; + case AB8500_CODEC_DA_CHANNEL_NUMBER_5: + p_ab8500_codec_configuration->cr55_sltoda5 = slot; + break; + case AB8500_CODEC_DA_CHANNEL_NUMBER_6: + p_ab8500_codec_configuration->cr56_sltoda6 = slot; + break; + case AB8500_CODEC_DA_CHANNEL_NUMBER_7: + p_ab8500_codec_configuration->cr57_sltoda7 = slot; + break; + case AB8500_CODEC_DA_CHANNEL_NUMBER_8: + p_ab8500_codec_configuration->cr58_sltoda8 = slot; + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_cr0_powerup = p_ab8500_codec_configuration->cr0_powerup; + p_ab8500_codec_configuration->cr0_powerup = + AB8500_CODEC_CR0_POWERUP_OFF; + ab8500_codec_error = ab8500_codec_UpdateCR0(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR51(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR52(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR53(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR54(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR55(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR56(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR57(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR58(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + p_ab8500_codec_configuration->cr0_powerup = ab8500_codec_cr0_powerup; + ab8500_codec_error = ab8500_codec_UpdateCR0(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_ConfigureBurstFifo */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Configuration for Burst FIFO control */ +/* */ +/* ARGUMENTS */ +/* IN: t_ab8500_codec_burst_fifo_config: structure for configuration of */ +/* burst FIFO */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_INVALID_PARAMETER: If invalid parameter */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: If interface 1 selected */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +t_ab8500_codec_error AB8500_CODEC_ConfigureBurstFifo(IN + t_ab8500_codec_burst_fifo_config + const *const + p_burst_fifo_config) +{ + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER1(" (%lx)", p_burst_fifo_config); + if (AB8500_CODEC_AUDIO_INTERFACE_0 == + g_ab8500_codec_system_context.audio_interface) + { + if (AB8500_CODEC_CR27_EN_MASTGEN_ENABLED == + p_ab8500_codec_configuration->cr27_en_mastgen) + { + p_ab8500_codec_configuration->cr105_bfifomsk = + p_burst_fifo_config->cr105_bfifomsk; + p_ab8500_codec_configuration->cr105_bfifoint = + p_burst_fifo_config->cr105_bfifoint; + p_ab8500_codec_configuration->cr106_bfifotx = + p_burst_fifo_config->cr106_bfifotx; + p_ab8500_codec_configuration->cr107_bfifoexsl = + p_burst_fifo_config->cr107_bfifoexsl; + p_ab8500_codec_configuration->cr107_bfifomast = + p_burst_fifo_config->cr107_bfifomast; + p_ab8500_codec_configuration->cr107_bfiforun = + p_burst_fifo_config->cr107_bfiforun; + p_ab8500_codec_configuration->cr108_bfifoframsw = + p_burst_fifo_config->cr108_bfifoframsw; + p_ab8500_codec_configuration->cr109_bfifowakeup = + p_burst_fifo_config->cr109_bfifowakeup; + ab8500_codec_error = ab8500_codec_UpdateCR105(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR106(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR107(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR108(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR109(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else + { + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else + { + ab8500_codec_error = AB8500_CODEC_UNSUPPORTED_FEATURE; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_EnableBurstFifo */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Enable the Burst FIFO for Interface 0 */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: If Interface 1 is selected */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_EnableBurstFifo(void) +{ + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + if (AB8500_CODEC_AUDIO_INTERFACE_0 == + g_ab8500_codec_system_context.audio_interface) + { + p_ab8500_codec_configuration->cr29_if0bfifoen = + AB8500_CODEC_CR29_IF0BFIFOEN_BURST_MODE; + ab8500_codec_error = ab8500_codec_UpdateCR29(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else + { + ab8500_codec_error = AB8500_CODEC_UNSUPPORTED_FEATURE; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +/****************************************************************************/ +/* NAME: AB8500_CODEC_DisableBurstFifo */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: */ +/* Disable the Burst FIFO for Interface 0 */ +/* */ +/* ARGUMENTS */ +/* IN: */ +/* None */ +/* OUT: */ +/* None */ +/* RETURN: */ +/* AB8500_CODEC_UNSUPPORTED_FEATURE: If Interface 1 is selected */ +/* AB8500_CODEC_OK: if successful. */ +/* REMARK: */ +/*--------------------------------------------------------------------------*/ +/* REENTRANCY: Non Re-Entrant */ + +/****************************************************************************/ +PUBLIC t_ab8500_codec_error AB8500_CODEC_DisableBurstFifo(void) +{ + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + DBGENTER0(); + if (AB8500_CODEC_AUDIO_INTERFACE_0 == + g_ab8500_codec_system_context.audio_interface) + { + p_ab8500_codec_configuration->cr29_if0bfifoen = + AB8500_CODEC_CR29_IF0BFIFOEN_NORMAL_MODE; + ab8500_codec_error = ab8500_codec_UpdateCR29(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + } + + else + { + ab8500_codec_error = AB8500_CODEC_UNSUPPORTED_FEATURE; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch1 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value ) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (ad_slot) + { + case AB8500_CODEC_SLOT0: + p_ab8500_codec_configuration->cr31_adotoslot0 = value; + ab8500_codec_error = ab8500_codec_UpdateCR31(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT1: + p_ab8500_codec_configuration->cr31_adotoslot1 = value; + ab8500_codec_error = ab8500_codec_UpdateCR31(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT2: + p_ab8500_codec_configuration->cr32_adotoslot2 = value; + ab8500_codec_error = ab8500_codec_UpdateCR32(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT3: + p_ab8500_codec_configuration->cr32_adotoslot3 = value; + ab8500_codec_error = ab8500_codec_UpdateCR32(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT4: + p_ab8500_codec_configuration->cr33_adotoslot4 = value; + ab8500_codec_error = ab8500_codec_UpdateCR33(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT5: + p_ab8500_codec_configuration->cr33_adotoslot5 = value; + ab8500_codec_error = ab8500_codec_UpdateCR33(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT6: + p_ab8500_codec_configuration->cr34_adotoslot6 = value; + ab8500_codec_error = ab8500_codec_UpdateCR34(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT7: + p_ab8500_codec_configuration->cr34_adotoslot7 = value; + ab8500_codec_error = ab8500_codec_UpdateCR34(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch2 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value ) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (ad_slot) + { + case AB8500_CODEC_SLOT8: + p_ab8500_codec_configuration->cr35_adotoslot8 = value; + ab8500_codec_error = ab8500_codec_UpdateCR35(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT9: + p_ab8500_codec_configuration->cr35_adotoslot9 = value; + ab8500_codec_error = ab8500_codec_UpdateCR35(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT10: + p_ab8500_codec_configuration->cr36_adotoslot10 = value; + ab8500_codec_error = ab8500_codec_UpdateCR36(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT11: + p_ab8500_codec_configuration->cr36_adotoslot11 = value; + ab8500_codec_error = ab8500_codec_UpdateCR36(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT12: + p_ab8500_codec_configuration->cr37_adotoslot12 = value; + ab8500_codec_error = ab8500_codec_UpdateCR37(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT13: + p_ab8500_codec_configuration->cr37_adotoslot13 = value; + ab8500_codec_error = ab8500_codec_UpdateCR37(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT14: + p_ab8500_codec_configuration->cr38_adotoslot14 = value; + ab8500_codec_error = ab8500_codec_UpdateCR38(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT15: + p_ab8500_codec_configuration->cr38_adotoslot15 = value; + ab8500_codec_error = ab8500_codec_UpdateCR38(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch3 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value ) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (ad_slot) + { + case AB8500_CODEC_SLOT16: + p_ab8500_codec_configuration->cr39_adotoslot16 = value; + ab8500_codec_error = ab8500_codec_UpdateCR39(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT17: + p_ab8500_codec_configuration->cr39_adotoslot17 = value; + ab8500_codec_error = ab8500_codec_UpdateCR39(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT18: + p_ab8500_codec_configuration->cr40_adotoslot18 = value; + ab8500_codec_error = ab8500_codec_UpdateCR40(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT19: + p_ab8500_codec_configuration->cr40_adotoslot19 = value; + ab8500_codec_error = ab8500_codec_UpdateCR40(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT20: + p_ab8500_codec_configuration->cr41_adotoslot20 = value; + ab8500_codec_error = ab8500_codec_UpdateCR41(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT21: + p_ab8500_codec_configuration->cr41_adotoslot21 = value; + ab8500_codec_error = ab8500_codec_UpdateCR41(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT22: + p_ab8500_codec_configuration->cr42_adotoslot22 = value; + ab8500_codec_error = ab8500_codec_UpdateCR42(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT23: + p_ab8500_codec_configuration->cr42_adotoslot23 = value; + ab8500_codec_error = ab8500_codec_UpdateCR42(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ADSlotAllocationSwitch4 + (IN t_ab8500_codec_slot ad_slot, + IN t_ab8500_codec_cr31_to_cr46_ad_data_allocation value ) { + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (ad_slot) + { + case AB8500_CODEC_SLOT24: + p_ab8500_codec_configuration->cr43_adotoslot24 = value; + ab8500_codec_error = ab8500_codec_UpdateCR43(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT25: + p_ab8500_codec_configuration->cr43_adotoslot25 = value; + ab8500_codec_error = ab8500_codec_UpdateCR43(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT26: + p_ab8500_codec_configuration->cr44_adotoslot26 = value; + ab8500_codec_error = ab8500_codec_UpdateCR44(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT27: + p_ab8500_codec_configuration->cr44_adotoslot27 = value; + ab8500_codec_error = ab8500_codec_UpdateCR44(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT28: + p_ab8500_codec_configuration->cr45_adotoslot28 = value; + ab8500_codec_error = ab8500_codec_UpdateCR45(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT29: + p_ab8500_codec_configuration->cr45_adotoslot29 = value; + ab8500_codec_error = ab8500_codec_UpdateCR45(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT30: + p_ab8500_codec_configuration->cr46_adotoslot30 = value; + ab8500_codec_error = ab8500_codec_UpdateCR46(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + case AB8500_CODEC_SLOT31: + p_ab8500_codec_configuration->cr46_adotoslot31 = value; + ab8500_codec_error = ab8500_codec_UpdateCR46(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch1(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (src_device) + { + case AB8500_CODEC_SRC_LINEIN: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_LINR; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + } + + else + { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_MIC2; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + } + break; + case AB8500_CODEC_SRC_MICROPHONE_1A: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1A; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + } + + else + { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_DISABLED; + } + break; + case AB8500_CODEC_SRC_MICROPHONE_1B: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1B; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + } + + else + { + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_DISABLED; + } + break; + case AB8500_CODEC_SRC_MICROPHONE_2: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_MIC2; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + } + + else + { + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_LINR; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_1: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + p_ab8500_codec_configuration->cr63_ad1sel = + AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED; + } + + else + { + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr63_ad1sel = + AB8500_CODEC_CR63_AD1SEL_LINLADL_SELECTED; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_2: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + p_ab8500_codec_configuration->cr63_ad2sel = + AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED; + } + + else + { + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr63_ad2sel = + AB8500_CODEC_CR63_AD2SEL_LINRADR_SELECTED; + } + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SrcPowerControlSwitch2(IN + t_ab8500_codec_src + src_device, + t_ab8500_codec_src_state + state) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (src_device) + { + case AB8500_CODEC_SRC_D_MICROPHONE_3: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + p_ab8500_codec_configuration->cr63_ad3sel = + AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED; + } + + else + { + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr63_ad3sel = + AB8500_CODEC_CR63_AD3SEL_ADMO_SELECTED; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_4: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + } + + else + { + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_5: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + p_ab8500_codec_configuration->cr63_ad5sel = + AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED; + } + + else + { + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr63_ad5sel = + AB8500_CODEC_CR63_AD5SEL_AMADR_SELECTED; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_6: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + p_ab8500_codec_configuration->cr63_ad6sel = + AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED; + } + + else + { + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr63_ad6sel = + AB8500_CODEC_CR63_AD6SEL_ADMO_SELECTED; + } + break; + case AB8500_CODEC_SRC_ALL: + if (AB8500_CODEC_SRC_STATE_ENABLE == state) + { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + } + + else + { + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + } + break; + case AB8500_CODEC_SRC_FM_RX: + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetModeAndDirectionUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + t_ab8500_codec_cr0_powerup ab8500_codec_cr0_powerup; + ab8500_codec_cr0_powerup = p_ab8500_codec_configuration->cr0_powerup; + p_ab8500_codec_configuration->cr0_powerup = + AB8500_CODEC_CR0_POWERUP_OFF; + ab8500_codec_error = ab8500_codec_UpdateCR0(); + if (AB8500_CODEC_OK != ab8500_codec_error) + { + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR2(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR3(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR26(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR27(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR28(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR30(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR63(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + p_ab8500_codec_configuration->cr0_powerup = ab8500_codec_cr0_powerup; + ab8500_codec_error = ab8500_codec_UpdateCR0(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetSrcVolumeUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + ab8500_codec_error = ab8500_codec_UpdateCR20(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR21(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR23(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR65(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR66(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR67(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR68(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR69(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR70(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_SetDestVolumeUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + ab8500_codec_error = ab8500_codec_UpdateCR16(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR17(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR18(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR19(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR22(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR71(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR72(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR73(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR74(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR75(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR76(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR79(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR80(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionIN(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (g_ab8500_codec_system_context.ab8500_codec_src) + { + case AB8500_CODEC_SRC_LINEIN: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_LINR; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_MICROPHONE_1A: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1A; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_MICROPHONE_1B: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_mic1sel = + AB8500_CODEC_CR7_MIC1SEL_MIC1B; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_MICROPHONE_2: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_linrsel = + AB8500_CODEC_CR7_LINRSEL_MIC2; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_1: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr63_ad1sel = + AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_2: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr63_ad2sel = + AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_3: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr63_ad3sel = + AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_4: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_5: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_DISABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr63_ad5sel = + AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_6: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_DISABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_DISABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_DISABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_DISABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_DISABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_DISABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_DISABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_DISABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_DISABLED; + p_ab8500_codec_configuration->cr63_ad6sel = + AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_ENABLED; + break; + case AB8500_CODEC_SRC_ALL: + p_ab8500_codec_configuration->cr5_enlinl = + AB8500_CODEC_CR5_ENLINL_ENABLED; + p_ab8500_codec_configuration->cr5_enlinr = + AB8500_CODEC_CR5_ENLINR_ENABLED; + p_ab8500_codec_configuration->cr5_enmic1 = + AB8500_CODEC_CR5_ENMIC1_ENABLED; + p_ab8500_codec_configuration->cr5_enmic2 = + AB8500_CODEC_CR5_ENMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic1 = + AB8500_CODEC_CR6_ENDMIC1_ENABLED; + p_ab8500_codec_configuration->cr6_endmic2 = + AB8500_CODEC_CR6_ENDMIC2_ENABLED; + p_ab8500_codec_configuration->cr6_endmic3 = + AB8500_CODEC_CR6_ENDMIC3_ENABLED; + p_ab8500_codec_configuration->cr6_endmic4 = + AB8500_CODEC_CR6_ENDMIC4_ENABLED; + p_ab8500_codec_configuration->cr6_endmic5 = + AB8500_CODEC_CR6_ENDMIC5_ENABLED; + p_ab8500_codec_configuration->cr6_endmic6 = + AB8500_CODEC_CR6_ENDMIC6_ENABLED; + p_ab8500_codec_configuration->cr7_enadcmic = + AB8500_CODEC_CR7_ENADCMIC_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinl = + AB8500_CODEC_CR7_ENADCLINL_ENABLED; + p_ab8500_codec_configuration->cr7_enadclinr = + AB8500_CODEC_CR7_ENADCLINR_ENABLED; + p_ab8500_codec_configuration->cr5_mutlinl = + AB8500_CODEC_CR5_MUTLINL_DISABLED; + p_ab8500_codec_configuration->cr5_mutlinr = + AB8500_CODEC_CR5_MUTLINR_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic1 = + AB8500_CODEC_CR5_MUTMIC1_DISABLED; + p_ab8500_codec_configuration->cr5_mutmic2 = + AB8500_CODEC_CR5_MUTMIC2_DISABLED; + break; + case AB8500_CODEC_SRC_D_MICROPHONE_12: + case AB8500_CODEC_SRC_D_MICROPHONE_34: + case AB8500_CODEC_SRC_D_MICROPHONE_56: + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_ProgramDirectionOUT(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + t_ab8500_codec_configuration * p_ab8500_codec_configuration = + &g_ab8500_codec_system_context. ab8500_codec_configuration; + switch (g_ab8500_codec_system_context.ab8500_codec_dest) + { + case AB8500_CODEC_DEST_HEADSET: + p_ab8500_codec_configuration->cr7_endrvhsl = + AB8500_CODEC_CR7_ENDRVHSL_ENABLED; + p_ab8500_codec_configuration->cr7_endrvhsr = + AB8500_CODEC_CR7_ENDRVHSR_ENABLED; + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + p_ab8500_codec_configuration->cr9_endachsl = + AB8500_CODEC_CR9_ENDACHSL_ENABLED; + p_ab8500_codec_configuration->cr9_endachsr = + AB8500_CODEC_CR9_ENDACHSR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + p_ab8500_codec_configuration->cr12_encphs = + AB8500_CODEC_CR12_ENCPHS_ENABLED; + break; + case AB8500_CODEC_DEST_EARPIECE: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + break; + case AB8500_CODEC_DEST_HANDSFREE: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + break; + case AB8500_CODEC_DEST_VIBRATOR_L: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_DISABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + break; + case AB8500_CODEC_DEST_VIBRATOR_R: + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_DISABLED; + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_DISABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_DISABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_DISABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_DISABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_DISABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_ENABLED; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + break; + case AB8500_CODEC_DEST_ALL: + p_ab8500_codec_configuration->cr8_enhsl = + AB8500_CODEC_CR8_ENHSL_ENABLED; + p_ab8500_codec_configuration->cr8_enhsr = + AB8500_CODEC_CR8_ENHSR_ENABLED; + p_ab8500_codec_configuration->cr8_enear = + AB8500_CODEC_CR8_ENEAR_ENABLED; + p_ab8500_codec_configuration->cr8_enhfl = + AB8500_CODEC_CR8_ENHFL_ENABLED; + p_ab8500_codec_configuration->cr8_enhfr = + AB8500_CODEC_CR8_ENHFR_ENABLED; + p_ab8500_codec_configuration->cr8_envibl = + AB8500_CODEC_CR8_ENVIBL_ENABLED; + p_ab8500_codec_configuration->cr8_envibr = + AB8500_CODEC_CR8_ENVIBR_ENABLED; + p_ab8500_codec_configuration->cr9_endacear = + AB8500_CODEC_CR9_ENDACEAR_ENABLED; + p_ab8500_codec_configuration->cr9_endachfl = + AB8500_CODEC_CR9_ENDACHFL_ENABLED; + p_ab8500_codec_configuration->cr9_endachfr = + AB8500_CODEC_CR9_ENDACHFR_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibl = + AB8500_CODEC_CR9_ENDACVIBL_ENABLED; + p_ab8500_codec_configuration->cr9_endacvibr = + AB8500_CODEC_CR9_ENDACVIBR_ENABLED; + p_ab8500_codec_configuration->cr10_mutehsl = + AB8500_CODEC_CR10_MUTEHSL_DISABLED; + p_ab8500_codec_configuration->cr10_mutehsr = + AB8500_CODEC_CR10_MUTEHSR_DISABLED; + p_ab8500_codec_configuration->cr10_muteear = + AB8500_CODEC_CR10_MUTEEAR_DISABLED; + p_ab8500_codec_configuration->cr15_pwmtovibl = + AB8500_CODEC_CR15_PWMTOVIBL_PWM; + p_ab8500_codec_configuration->cr15_pwmlctrl = + AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnlctrl = + AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmplctrl = + AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmtovibr = + AB8500_CODEC_CR15_PWMTOVIBR_PWM; + p_ab8500_codec_configuration->cr15_pwmrctrl = + AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmnrctrl = + AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE; + p_ab8500_codec_configuration->cr15_pwmprctrl = + AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE; + break; + default: + ab8500_codec_error = AB8500_CODEC_INVALID_PARAMETER; + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} + +PRIVATE t_ab8500_codec_error ab8500_codec_DestPowerControlUpdateCR(void) +{ + t_ab8500_codec_error ab8500_codec_error = AB8500_CODEC_OK; + ab8500_codec_error = ab8500_codec_UpdateCR8(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR9(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR10(); + if (ab8500_codec_error != AB8500_CODEC_OK) + { + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); + } + ab8500_codec_error = ab8500_codec_UpdateCR15(); + DBGEXIT(ab8500_codec_error); + return (ab8500_codec_error); +} diff --git a/sound/u8500_acodec_ab8500.c b/sound/u8500_acodec_ab8500.c new file mode 100644 index 00000000000..2c1ae702b79 --- /dev/null +++ b/sound/u8500_acodec_ab8500.c @@ -0,0 +1,2522 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Deepak Karda + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +/*----------------------------------------------------------------------------- +* Common Includes +*---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include +#include +#include + +#ifdef CONFIG_U8500_AB8500_CUT10 +#include +#endif +#ifdef CONFIG_U8500_AB8500_ED +#include +#endif + +#define ELEMENT_SIZE 0 +#define FRAME_SIZE -1 +#define MSP_NUM 0 + +/* Debugging stuff */ + +#define ACODEC_NAME "DRIVER ACODEC" +#define DRIVER_DEBUG CONFIG_STM_ACODEC_DEBUG /* enables/disables debug msgs */ +#define DRIVER_DEBUG_PFX ACODEC_NAME /* msg header represents this module */ +#define DRIVER_DBG KERN_ERR /* message level */ +#define NMDK_DEBUG CONFIG_STM_ACODEC_DEBUG +extern struct driver_debug_st DBG_ST; + +#if NMDK_DEBUG > 0 +t_ab8500_codec_error dump_acodec_registers(void); +t_ab8500_codec_error dump_msp_registers(void); +#endif + +#ifdef CONFIG_U8500_ACODEC_DMA +static void u8500_digital_lpbk_tx_dma_start(void); +static void u8500_digital_lpbk_rx_dma_start(void); +#endif + +int second_config; +/*---------------------------------------------------------------------------- +* global declarations +*---------------------------------------------------------------------------*/ +t_u8500_codec_system_context g_codec_system_context; + +int u8500_acodec_rates[MAX_NO_OF_RATES] = { 48000 }; + +char *codec_dest_texts[NUMBER_OUTPUT_DEVICE] = { + "CODEC_DEST_HEADSET", "CODEC_DEST_EARPIECE", "CODEC_DEST_HANDSFREE", + "CODEC_DEST_VIBRATOR1", "CODEC_DEST_VIBRATOR2" +}; + +char *codec_in_texts[NUMBER_INPUT_DEVICE] = { + "CODEC_SRC_LINEIN", "CODEC_SRC_MICROPHONE_1A", + "CODEC_SRC_MICROPHONE_1B", + "CODEC_SRC_MICROPHONE_2", "CODEC_SRC_D_MICROPHONE_1", + "CODEC_SRC_D_MICROPHONE_2", + "CODEC_SRC_D_MICROPHONE_3", "CODEC_SRC_D_MICROPHONE_4", + "CODEC_SRC_D_MICROPHONE_5", + "CODEC_SRC_D_MICROPHONE_6", "CODEC_SRC_D_MICROPHONE_12", + "CODEC_SRC_D_MICROPHONE_34", + "CODEC_SRC_D_MICROPHONE_56" +}; + +char *lpbk_state_in_texts[NUMBER_LOOPBACK_STATE] = { "DISABLE", "ENABLE" }; +char *switch_state_in_texts[NUMBER_SWITCH_STATE] = { "DISABLE", "ENABLE" }; +char *power_state_in_texts[NUMBER_POWER_STATE] = { "DISABLE", "ENABLE" }; +char *tdm_mode_state_in_texts[NUMBER_POWER_STATE] = { "DISABLE", "ENABLE" }; +char *direct_rendering_state_in_texts[NUMBER_DIRECT_RENDERING_STATE] = + { "DISABLE", "ENABLE" }; +char *pcm_rendering_state_in_texts[NUMBER_PCM_RENDERING_STATE] = + { "DISABLE", "ENABLE", "PENDING" }; + +EXPORT_SYMBOL(codec_dest_texts); +EXPORT_SYMBOL(codec_in_texts); + +static void ab8500_codec_power_init(void); +static int check_device_id(); +t_ab8500_codec_error perform_src_routing(t_ab8500_codec_src input_device); +t_ab8500_codec_error + u8500_acodec_allocate_all_mono_slots + (t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line1); +t_ab8500_codec_error + u8500_acodec_allocate_all_stereo_slots + (t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line1, + t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line2); + +#if 0 //from Arnaud +/* For Codec in Master mode for recording*/ +struct msp_protocol_desc protocol_desc_tdm_mode = { + MSP_DATA_TRANSFER_WIDTH_HALFWORD, /*rx_data_transfer_width */ + MSP_DATA_TRANSFER_WIDTH_HALFWORD, /*tx_data_transfer_width */ + MSP_SINGLE_PHASE, /*rx_phase_mode */ + MSP_SINGLE_PHASE, /*tx_phase_mode */ + MSP_PHASE2_START_MODE_IMEDIATE, /*rx_phase2_start_mode */ + MSP_PHASE2_START_MODE_IMEDIATE, /*tx_phase2_start_mode */ + MSP_BTF_MS_BIT_FIRST, /*rx_endianess */ + MSP_BTF_MS_BIT_FIRST, /*tx_endianess */ + MSP_FRAME_LENGTH_2, /*rx_frame_length_1 */ + MSP_FRAME_LENGTH_2, /*rx_frame_length_2 */ + MSP_FRAME_LENGTH_2, /*tx_frame_length_1 */ + MSP_FRAME_LENGTH_2, /*tx_frame_length_2 */ + MSP_ELEM_LENGTH_16, /*rx_element_length_1 */ + MSP_ELEM_LENGTH_16, /*rx_element_length_2 */ + MSP_ELEM_LENGTH_16, /*tx_element_length_1 */ + MSP_ELEM_LENGTH_16, /*tx_element_length_2 */ + MSP_DELAY_0, /*rx_data_delay */ + MSP_DELAY_0, /*tx_data_delay */ + MSP_FALLING_EDGE, /*rx_clock_pol */ + MSP_RISING_EDGE, /*tx_clock_pol */ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, /*rx_msp_frame_pol */ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, /*tx_msp_frame_pol */ + MSP_HWS_NO_SWAP, /*rx_half_word_swap */ + MSP_HWS_NO_SWAP, /*tx_half_word_swap */ + MSP_COMPRESS_MODE_LINEAR, /*compression_mode */ + MSP_EXPAND_MODE_LINEAR, /*expansion_mode */ + MSP_SPI_CLOCK_MODE_NON_SPI, /*spi_clk_mode */ + MSP_SPI_BURST_MODE_DISABLE, /*spi_burst_mode */ + 63, /*frame_period */ + 31, /*frame_width */ + 64, /*total_clocks_for_one_frame */ +}; +#endif + +#if 0 //from HCL +/* For Codec in Master mode for recording*/ +struct msp_protocol_desc protocol_desc_tdm_mode = { + MSP_DATA_TRANSFER_WIDTH_WORD, /*rx_data_transfer_width */ + MSP_DATA_TRANSFER_WIDTH_WORD, /*tx_data_transfer_width */ + MSP_DUAL_PHASE, /*rx_phase_mode */ + MSP_DUAL_PHASE, /*tx_phase_mode */ + MSP_PHASE2_START_MODE_FRAME_SYNC, /*rx_phase2_start_mode */ + MSP_PHASE2_START_MODE_FRAME_SYNC, /*tx_phase2_start_mode */ + MSP_BTF_MS_BIT_FIRST, /*rx_endianess */ + MSP_BTF_MS_BIT_FIRST, /*tx_endianess */ + MSP_FRAME_LENGTH_1, /*rx_frame_length_1 */ + MSP_FRAME_LENGTH_1, /*rx_frame_length_2 */ + MSP_FRAME_LENGTH_1, /*tx_frame_length_1 */ + MSP_FRAME_LENGTH_1, /*tx_frame_length_2 */ + MSP_ELEM_LENGTH_16, /*rx_element_length_1 */ + MSP_ELEM_LENGTH_16, /*rx_element_length_2 */ + MSP_ELEM_LENGTH_16, /*tx_element_length_1 */ + MSP_ELEM_LENGTH_16, /*tx_element_length_2 */ + MSP_DELAY_0, /*rx_data_delay */ + MSP_DELAY_0, /*tx_data_delay */ + MSP_RISING_EDGE, /*rx_clock_pol */ + MSP_RISING_EDGE, /*tx_clock_pol */ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, /*rx_msp_frame_pol */ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, /*tx_msp_frame_pol */ + MSP_HWS_NO_SWAP, /*rx_half_word_swap */ + MSP_HWS_NO_SWAP, /*tx_half_word_swap */ + MSP_COMPRESS_MODE_LINEAR, /*compression_mode */ + MSP_EXPAND_MODE_LINEAR, /*expansion_mode */ + MSP_SPI_CLOCK_MODE_NON_SPI, /*spi_clk_mode */ + MSP_SPI_BURST_MODE_DISABLE, /*spi_burst_mode */ + 255, /*frame_period */ + 0, /*frame_width */ + 256, /*total_clocks_for_one_frame */ +}; + +#endif + +#if 0 //from STS +struct msp_protocol_desc protocol_desc_tdm_mode = { + MSP_DATA_TRANSFER_WIDTH_HALFWORD, /*rx_data_transfer_width */ + MSP_DATA_TRANSFER_WIDTH_HALFWORD, /*tx_data_transfer_width */ + MSP_SINGLE_PHASE, /*rx_phase_mode */ + MSP_SINGLE_PHASE, /*tx_phase_mode */ + MSP_PHASE2_START_MODE_IMEDIATE, /*rx_phase2_start_mode */ + MSP_PHASE2_START_MODE_IMEDIATE, /*tx_phase2_start_mode */ + MSP_BTF_MS_BIT_FIRST, /*rx_endianess */ + MSP_BTF_MS_BIT_FIRST, /*tx_endianess */ + MSP_FRAME_LENGTH_2, /*rx_frame_length_1 */ + MSP_FRAME_LENGTH_1, /*rx_frame_length_2 */ + MSP_FRAME_LENGTH_2, /*tx_frame_length_1 */ + MSP_FRAME_LENGTH_1, /*tx_frame_length_2 */ + MSP_ELEM_LENGTH_16, /*rx_element_length_1 */ + MSP_ELEM_LENGTH_16, /*rx_element_length_2 */ + MSP_ELEM_LENGTH_16, /*tx_element_length_1 */ + MSP_ELEM_LENGTH_16, /*tx_element_length_2 */ + MSP_DELAY_0, /*rx_data_delay */ + MSP_DELAY_0, /*tx_data_delay */ + MSP_FALLING_EDGE, /*rx_clock_pol */ + MSP_RISING_EDGE, /*tx_clock_pol */ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, /*rx_msp_frame_pol */ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, /*tx_msp_frame_pol */ + MSP_HWS_NO_SWAP, /*rx_half_word_swap */ + MSP_HWS_NO_SWAP, /*tx_half_word_swap */ + MSP_COMPRESS_MODE_LINEAR, /*compression_mode */ + MSP_EXPAND_MODE_LINEAR, /*expansion_mode */ + MSP_SPI_CLOCK_MODE_NON_SPI, /*spi_clk_mode */ + MSP_SPI_BURST_MODE_DISABLE, /*spi_burst_mode */ + 25, /*frame_period */ + 32, /*frame_width */ + 32, /*total_clocks_for_one_frame */ +}; +#endif + +#define DIGITAL_LPBK_MAX_BIFFERS 3 + +#ifdef CONFIG_U8500_AB8500_CUT10 +#define NB_OF_CHANNEL_USED 8 +#else +#define NB_OF_CHANNEL_USED 6 +#endif + +#define MONO_SRC 1 +#define STEREO_SRC 2 + +typedef struct { + unsigned char *area; /* virtual pointer */ + dma_addr_t addr; /* physical address */ +} t_dma_buffer; + +typedef struct { + struct completion tx_dma_com; + struct completion rx_dma_com; + volatile int rx_active; + volatile int tx_active; + t_dma_buffer buffer; + int data_size; + int rx_index; + int tx_index; +} t_digital_lpbk_cnxt; + +const int play_flag = 1; +const int capture_flag = 2; + +t_digital_lpbk_cnxt digital_lpbk_cnxt; + +void u8500_set_defaults() +{ + int i; + + for (i = 0; i < NUMBER_INPUT_DEVICE; i++) { + g_codec_system_context.input_config[i].left_volume = 0; + g_codec_system_context.input_config[i].right_volume = 0; + g_codec_system_context.input_config[i].mute_state = DISABLE; + g_codec_system_context.input_config[i].power_state = DISABLE; + } + + for (i = 0; i < NUMBER_OUTPUT_DEVICE; i++) { + g_codec_system_context.output_config[i].left_volume = 0; + g_codec_system_context.output_config[i].right_volume = 0; + g_codec_system_context.output_config[i].mute_state = DISABLE; + g_codec_system_context.output_config[i].power_state = DISABLE; + } + +} //END OF FUNCTION + +struct i2sdrv_data *i2sdrv[MAX_I2S_CLIENTS]; + +t_ab8500_codec_error u8500_acodec_open(int client_id, int stream_id) +{ + struct i2sdrv_data *p_i2sdrv_data = NULL; + struct i2s_device *i2s; + + p_i2sdrv_data = i2sdrv[client_id]; + + if (!p_i2sdrv_data) + return (-1); + + i2s = p_i2sdrv_data->i2s; + + if (stream_id == 0) //PLAYBACK + { + if (p_i2sdrv_data->tx_status) + return -1; + else { + p_i2sdrv_data->tx_status = 1; + } + } else if (stream_id == 1) //CAPTURE + { + if (p_i2sdrv_data->rx_status) + return -1; + else { + p_i2sdrv_data->rx_status = 1; + } + } + + p_i2sdrv_data->flag = 0; + + return 0; +} + +t_ab8500_codec_error u8500_acodec_send_data(int client_id, void *data, + size_t bytes, int dma_flag) +{ + struct i2sdrv_data *p_i2sdrv_data = NULL; + struct i2s_device *i2s_dev = NULL; + int bytes_transmit; + struct i2s_message message; + + p_i2sdrv_data = i2sdrv[client_id]; + + if (!p_i2sdrv_data) + return (-1); + + i2s_dev = p_i2sdrv_data->i2s; + + if (p_i2sdrv_data->flag) { + stm_dbg(DBG_ST.acodec, " I2S controller not available\n"); + return -1; + } + message.txbytes = bytes; + message.txdata = data; + message.rxbytes = 0; + message.rxdata = NULL; + message.dma_flag = dma_flag; + + bytes_transmit = i2s_transfer(i2s_dev->controller, &message); + + if (bytes_transmit < 0) { + printk("error in transfer\n"); + return -1; + } + return bytes_transmit; + +} + +t_ab8500_codec_error u8500_acodec_loopback_configure(int client_id, void *data, + size_t bytes, int dma_flag) +{ + struct i2sdrv_data *p_i2sdrv_data = NULL; + struct i2s_device *i2s_dev = NULL; + int bytes_receive; + struct i2s_message message; + + p_i2sdrv_data = i2sdrv[client_id]; + + if (!p_i2sdrv_data) + return (-1); + + i2s_dev = p_i2sdrv_data->i2s; + + if (p_i2sdrv_data->flag) { + stm_dbg(DBG_ST.acodec, " I2S controller not available\n"); + return -1; + } + + message.rxbytes = bytes; + message.rxdata = data; + message.txbytes = bytes; + message.txdata = data; + message.dma_flag = dma_flag; + message.inf_loopback_xfer = true; + + bytes_receive = i2s_transfer(i2s_dev->controller, &message); + + if (bytes_receive < 0) { + printk(" not get\n"); + return -1; + } + return bytes_receive; + +} + +t_ab8500_codec_error u8500_acodec_receive_data(int client_id, void *data, + size_t bytes, int dma_flag) +{ + struct i2sdrv_data *p_i2sdrv_data = NULL; + struct i2s_device *i2s_dev = NULL; + int bytes_receive; + struct i2s_message message; + + p_i2sdrv_data = i2sdrv[client_id]; + + if (!p_i2sdrv_data) + return (-1); + + i2s_dev = p_i2sdrv_data->i2s; + + if (p_i2sdrv_data->flag) { + stm_dbg(DBG_ST.acodec, " I2S controller not available\n"); + return -1; + } + + message.rxbytes = bytes; + message.rxdata = data; + message.txbytes = 0; + message.txdata = NULL; + message.dma_flag = dma_flag; + + bytes_receive = i2s_transfer(i2s_dev->controller, &message); + + if (bytes_receive < 0) { + printk(" not get\n"); + return -1; + } + return bytes_receive; + +} + +t_ab8500_codec_error u8500_acodec_close(int client_id, t_acodec_disable flag) +{ + struct i2sdrv_data *p_i2sdrv_data = NULL; + struct i2s_device *i2s_dev = NULL; + int status = 0; + + p_i2sdrv_data = i2sdrv[client_id]; + + if (!p_i2sdrv_data) + return (-1); + + i2s_dev = p_i2sdrv_data->i2s; + + if (p_i2sdrv_data->flag) { + stm_dbg(DBG_ST.acodec, " I2S controller not available\n"); + return -1; + } + + if (flag == DISABLE_ALL) { + p_i2sdrv_data->flag = -1; + p_i2sdrv_data->tx_status = 0; + p_i2sdrv_data->rx_status = 0; + } else if (flag == DISABLE_TRANSMIT) { + p_i2sdrv_data->tx_status = 0; + } else if (flag == DISABLE_RECEIVE) { + p_i2sdrv_data->rx_status = 0; + } + status = i2s_cleanup(i2s_dev->controller, flag); + if (status) { + return -1; + } + + return 0; +} + +/** +* u8500_acodec_enable_audio_mode +* +* @direction - direction of data flow (from/to) audiocode +* @mspClockSel - clock for MSP +* @mspInClockFreq - input clock for MSP +* @channels - number of channel, 1 for mono and 2 for stereo +* +* It configures the audiocodec in audio mode. In this case,the I2S +* protocol is used for data exchanges. +*/ + +t_ab8500_codec_error u8500_acodec_enable_audio_mode(struct acodec_configuration + * acodec_config) +{ + struct i2s_device *i2s_dev = NULL; + t_ab8500_codec_error error_status = AB8500_CODEC_OK; + struct msp_config msp_config; + t_ab8500_codec_error codec_error; + t_ab8500_codec_mode codec_in_mode = AB8500_CODEC_MODE_MANUAL_SETTING; + t_ab8500_codec_mode codec_out_mode = AB8500_CODEC_MODE_MANUAL_SETTING; + t_ab8500_codec_direction codec_direction; +/*#ifdef CONFIG_U8500_AB8500_CUT10*/ +#if 1 + t_ab8500_codec_tdm_config tdm_config; +#endif + + memset(&msp_config, 0, sizeof(msp_config)); + + FUNC_ENTER(); + stm_dbg(DBG_ST.acodec, + " Entering in u8500_acodec_enable_audio_mode()\n"); + + if (i2sdrv[I2S_CLIENT_MSP1]->flag) { + stm_dbg(DBG_ST.acodec, " I2S controller not available\n"); + return -1; + } + + i2s_dev = i2sdrv[I2S_CLIENT_MSP1]->i2s; + + if (g_codec_system_context.cur_user == NO_USER) { + stm_error("Audiocodec not yet configured by any user\n"); + return (AB8500_CODEC_ERROR); + } else if (g_codec_system_context.cur_user != acodec_config->user) { + stm_error + (" Trying to acces audiocodec already in use by user %d\n", + g_codec_system_context.cur_user); + return (AB8500_CODEC_ERROR); + } + + switch (acodec_config->direction) { + case AB8500_CODEC_DIRECTION_INOUT: + codec_direction = AB8500_CODEC_DIRECTION_INOUT; + codec_in_mode = AB8500_CODEC_MODE_VOICE; //HIFI + codec_out_mode = AB8500_CODEC_MODE_VOICE; //VOICE + break; + case AB8500_CODEC_DIRECTION_IN: + codec_direction = AB8500_CODEC_DIRECTION_IN; + codec_in_mode = AB8500_CODEC_MODE_VOICE; //HIFI + break; + case AB8500_CODEC_DIRECTION_OUT: + codec_direction = AB8500_CODEC_DIRECTION_OUT; + codec_out_mode = AB8500_CODEC_MODE_VOICE; //HIFI + break; + default: + stm_error("Invalid direction\n"); + return AB8500_CODEC_ERROR; + } + + /* MSP configuration */ + + msp_config.tx_clock_sel = 0; //TX_CLK_SEL_SRG; + msp_config.rx_clock_sel = 0; //RX_CLK_SEL_SRG; + + msp_config.tx_frame_sync_sel = 0; //0x00000400; Frame synchronization signal is provided by an external source. MSPTFS is an input pin + msp_config.rx_frame_sync_sel = 0; //0: Rx Frame synchronization signal is provided by an external source. MSPRFS is an input pin + + msp_config.input_clock_freq = MSP_INPUT_FREQ_48MHZ; + + msp_config.srg_clock_sel = 0; //0x000C0000 + + //msp_config.rx_endianess = MSP_BIG_ENDIAN; + //msp_config.tx_endianess = MSP_BIG_ENDIAN; + + msp_config.rx_frame_sync_pol = RX_FIFO_SYNC_HI; + msp_config.tx_frame_sync_pol = TX_FIFO_SYNC_HI; + + //msp_config.rx_unexpect_frame_sync = MSP_UNEXPECTED_FS_IGNORE; + //msp_config.tx_unexpect_frame_sync = MSP_UNEXPECTED_FS_IGNORE; + + msp_config.rx_fifo_config = RX_FIFO_ENABLE; + msp_config.tx_fifo_config = TX_FIFO_ENABLE; + + msp_config.spi_clk_mode = SPI_CLK_MODE_NORMAL; + msp_config.spi_burst_mode = 0; + + msp_config.handler = acodec_config->handler; + msp_config.tx_callback_data = acodec_config->tx_callback_data; + msp_config.tx_data_enable = 0; + msp_config.rx_callback_data = acodec_config->rx_callback_data; + + msp_config.loopback_enable = 0; + msp_config.multichannel_configured = 0; + + msp_config.def_elem_len = 0; + //msp_config.loopback_enable = g_codec_system_context.msp_loopback; + + stm_dbg(DBG_ST.acodec, " msp_config.loopback_enable = 0x%x \n", + msp_config.loopback_enable); + +#if 0 + msp_config.default_protocol_desc = 1; +#else + msp_config.default_protocol_desc = 0; + msp_config.protocol_desc.rx_phase_mode = MSP_SINGLE_PHASE; + msp_config.protocol_desc.tx_phase_mode = MSP_SINGLE_PHASE; + msp_config.protocol_desc.rx_phase2_start_mode = + MSP_PHASE2_START_MODE_IMEDIATE; + msp_config.protocol_desc.tx_phase2_start_mode = + MSP_PHASE2_START_MODE_IMEDIATE; + msp_config.protocol_desc.rx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + msp_config.protocol_desc.tx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + msp_config.protocol_desc.rx_frame_length_1 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.rx_frame_length_2 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.tx_frame_length_1 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.tx_frame_length_2 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.rx_element_length_1 = MSP_ELEM_LENGTH_32; + msp_config.protocol_desc.rx_element_length_2 = MSP_ELEM_LENGTH_32; + msp_config.protocol_desc.tx_element_length_1 = MSP_ELEM_LENGTH_32; + msp_config.protocol_desc.tx_element_length_2 = MSP_ELEM_LENGTH_32; + msp_config.protocol_desc.rx_data_delay = MSP_DELAY_0; + msp_config.protocol_desc.tx_data_delay = MSP_DELAY_0; + msp_config.protocol_desc.rx_clock_pol = MSP_RISING_EDGE; + msp_config.protocol_desc.tx_clock_pol = MSP_FALLING_EDGE; + msp_config.protocol_desc.rx_frame_sync_pol = + MSP_FRAME_SYNC_POL_ACTIVE_HIGH; + msp_config.protocol_desc.tx_frame_sync_pol = + MSP_FRAME_SYNC_POL_ACTIVE_HIGH; + msp_config.protocol_desc.rx_half_word_swap = MSP_HWS_NO_SWAP; + msp_config.protocol_desc.tx_half_word_swap = MSP_HWS_NO_SWAP; + msp_config.protocol_desc.compression_mode = MSP_COMPRESS_MODE_LINEAR; + msp_config.protocol_desc.expansion_mode = MSP_EXPAND_MODE_LINEAR; + msp_config.protocol_desc.spi_clk_mode = MSP_SPI_CLOCK_MODE_NON_SPI; + msp_config.protocol_desc.spi_burst_mode = MSP_SPI_BURST_MODE_DISABLE; + msp_config.protocol_desc.frame_sync_ignore = MSP_FRAME_SYNC_IGNORE; + msp_config.protocol_desc.frame_period = 63; + msp_config.protocol_desc.frame_width = 31; + msp_config.protocol_desc.total_clocks_for_one_frame = 64; + +#endif + + msp_config.direction = MSP_BOTH_T_R_MODE; + msp_config.protocol = MSP_PCM_PROTOCOL; //MSP_I2S_PROTOCOL + msp_config.frame_size = ELEMENT_SIZE; + // msp_config.frame_freq = freq; $kardad$ + msp_config.frame_freq = CODEC_SAMPLING_FREQ_48KHZ; + + /* enable msp for both tr and rx mode with dma data transfer. THIS IS NOW DONE SEPARATELY from SAA. */ + + if (acodec_config->channels == 1) + msp_config.data_size = MSP_DATA_SIZE_16BIT; + else + msp_config.data_size = MSP_DATA_SIZE_32BIT; + +#ifdef CONFIG_U8500_ACODEC_DMA + msp_config.work_mode = MSP_DMA_MODE; +#elif defined(CONFIG_U8500_ACODEC_POLL) + msp_config.work_mode = MSP_POLLING_MODE; +#else + msp_config.work_mode = MSP_INTERRUPT_MODE; +#endif + + if (DISABLE == acodec_config->direct_rendering_mode) { + msp_config.multichannel_configured = 1; + msp_config.multichannel_config.tx_multichannel_enable = 1; + if (acodec_config->channels == 1) { + msp_config.multichannel_config.tx_channel_0_enable = + 0x0000001; + } else { + msp_config.multichannel_config.tx_channel_0_enable = + 0x0000003; + } + msp_config.multichannel_config.tx_channel_1_enable = 0x0000000; + msp_config.multichannel_config.tx_channel_2_enable = 0x0000000; + msp_config.multichannel_config.tx_channel_3_enable = 0x0000000; + + msp_config.multichannel_config.rx_multichannel_enable = 1; + + if (acodec_config->channels == 1) { + msp_config.multichannel_config.rx_channel_0_enable = + 0x0000001; + } else { + msp_config.multichannel_config.rx_channel_0_enable = + 0x0000003; + } + msp_config.multichannel_config.rx_channel_1_enable = 0x0000000; + msp_config.multichannel_config.rx_channel_2_enable = 0x0000000; + msp_config.multichannel_config.rx_channel_3_enable = 0x0000000; + + if (acodec_config->tdm8_ch_mode == ENABLE) { + msp_config.def_elem_len = 1; + + msp_config.protocol_desc.tx_element_length_1 = + MSP_ELEM_LENGTH_20; + msp_config.protocol_desc.tx_frame_length_1 = + MSP_FRAME_LENGTH_8; + msp_config.protocol_desc.tx_data_delay = MSP_DELAY_1; + + msp_config.protocol_desc.tx_element_length_2 = + MSP_ELEM_LENGTH_8; + msp_config.protocol_desc.tx_frame_length_2 = + MSP_FRAME_LENGTH_1; + + msp_config.protocol_desc.rx_element_length_1 = + MSP_ELEM_LENGTH_20; + msp_config.protocol_desc.rx_frame_length_1 = + MSP_FRAME_LENGTH_8; + msp_config.protocol_desc.rx_data_delay = MSP_DELAY_1; + + msp_config.protocol_desc.rx_element_length_2 = + MSP_ELEM_LENGTH_8; + msp_config.protocol_desc.rx_frame_length_2 = + MSP_FRAME_LENGTH_1; + + msp_config.protocol_desc.frame_sync_ignore = + MSP_FRAME_SYNC_UNIGNORE; + msp_config.protocol_desc.rx_clock_pol = MSP_RISING_EDGE; + + //if(acodec_config->digital_loopback == ENABLE) { + if (1) { + msp_config.multichannel_config. + tx_channel_0_enable = + (1 << NB_OF_CHANNEL_USED) - 1; + msp_config.multichannel_config. + rx_channel_0_enable = + (1 << NB_OF_CHANNEL_USED) - 1; + } else { + msp_config.multichannel_config. + tx_channel_0_enable = 0x3; + msp_config.multichannel_config. + rx_channel_0_enable = 0x3; + } + } + + if (acodec_config->tdm8_ch_mode == ENABLE) { + /* TFSDLY = 2 delay units */ + msp_config.iodelay = 0x20; + } + + error_status = i2s_setup(i2s_dev->controller, &msp_config); + if (error_status < 0) { + stm_error("error in msp enable, error_status is %d\n", + error_status); + return error_status; + } + } else if (ENABLE == acodec_config->direct_rendering_mode) { + writel(0x00, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x04))); //MSP_GCR + } + + if (ACODEC_CONFIG_REQUIRED == acodec_config->acodec_config_need) { + AB8500_CODEC_SelectInterface(AB8500_CODEC_AUDIO_INTERFACE_0); + + codec_error = AB8500_CODEC_PowerUp(); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_PowerUp failed\n"); + return AB8500_CODEC_ERROR; + } + +/*#ifdef CONFIG_U8500_AB8500_CUT10*/ +#if 1 + tdm_config.cr27_if1_bitclk_osr = + AB8500_CODEC_CR27_IF1_BITCLK_OSR_32; + tdm_config.cr27_if0_bitclk_osr = + AB8500_CODEC_CR27_IF0_BITCLK_OSR_32; + tdm_config.cr28_if0wl = AB8500_CODEC_CR28_IF0WL_16BITS; + tdm_config.cr30_if1wl = AB8500_CODEC_CR30_IF1WL_16BITS; + + switch (acodec_config->direction) { + case AB8500_CODEC_DIRECTION_INOUT: + tdm_config.cr28_bitclk0p = + AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; + tdm_config.cr28_if0del = + AB8500_CODEC_CR28_IF0DEL_DELAYED; + break; + case AB8500_CODEC_DIRECTION_IN: + tdm_config.cr28_bitclk0p = + AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE; + tdm_config.cr28_if0del = + AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED; + break; + case AB8500_CODEC_DIRECTION_OUT: + tdm_config.cr28_bitclk0p = + AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE; + tdm_config.cr28_if0del = + AB8500_CODEC_CR28_IF0DEL_DELAYED; + break; + default: + stm_error("Invalid direction\n"); + return AB8500_CODEC_ERROR; + } + + if (acodec_config->tdm8_ch_mode == ENABLE) { + tdm_config.cr27_if0_bitclk_osr = + AB8500_CODEC_CR27_IF0_BITCLK_OSR_256; + tdm_config.cr28_if0wl = AB8500_CODEC_CR28_IF0WL_20BITS; + tdm_config.cr28_bitclk0p = + AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE; + tdm_config.cr28_if0del = + AB8500_CODEC_CR28_IF0DEL_DELAYED; + codec_in_mode = AB8500_CODEC_MODE_VOICE; + codec_out_mode = AB8500_CODEC_MODE_VOICE; + acodec_config->direction = AB8500_CODEC_DIRECTION_INOUT; + } + + codec_error = + AB8500_CODEC_SetModeAndDirection(acodec_config->direction, + codec_in_mode, + codec_out_mode, + &tdm_config); +#else + codec_error = + AB8500_CODEC_SetModeAndDirection(acodec_config->direction, + codec_in_mode, + codec_out_mode); +#endif + if (AB8500_CODEC_OK != codec_error) { + stm_error("set mode and direction failed\n"); + return AB8500_CODEC_ERROR; + } + + codec_error = + AB8500_CODEC_SetMasterMode(AB8500_CODEC_MASTER_MODE_ENABLE); + + if (AB8500_CODEC_OK != codec_error) { + stm_error("set mode and direction failed\n"); + return AB8500_CODEC_ERROR; + } + + /*codec_error = trg_codec_set_sample_frequency(0); */ + + /*u8500_acodec_set_volume(g_codec_system_context.in_left_volume, + g_codec_system_context.in_right_volume, + g_codec_system_context.out_left_volume, + g_codec_system_context.out_right_volume, + user); */ +#if 0 + if (AB8500_CODEC_DIRECTION_IN == acodec_config->direction + || AB8500_CODEC_DIRECTION_INOUT == + acodec_config->direction) { + + u8500_acodec_allocate_ad_slot + (AB8500_CODEC_SRC_D_MICROPHONE_1, TDM_8_CH_MODE); + u8500_acodec_allocate_ad_slot + (AB8500_CODEC_SRC_D_MICROPHONE_2, TDM_8_CH_MODE); + + /*codec_error = AB8500_CODEC_ADSlotAllocation (AB8500_CODEC_SLOT0, + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + codec_error = AB8500_CODEC_ADSlotAllocation (AB8500_CODEC_SLOT1, + AB8500_CODEC_CR31_TO_CR46_SLOT_IS_TRISTATE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } */ + + } + + if (AB8500_CODEC_DIRECTION_OUT == acodec_config->direction + || AB8500_CODEC_DIRECTION_INOUT == + acodec_config->direction) { + u8500_acodec_allocate_da_slot(AB8500_CODEC_DEST_HEADSET, + TDM_8_CH_MODE); + /*codec_error = AB8500_CODEC_DASlotAllocation (AB8500_CODEC_DA_CHANNEL_NUMBER_1, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT08); + if (AB8500_CODEC_OK != codec_error) { + stm_error + ("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + codec_error = AB8500_CODEC_DASlotAllocation (AB8500_CODEC_DA_CHANNEL_NUMBER_2, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT09); + if (AB8500_CODEC_OK != codec_error) { + stm_error + ("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } */ + + } +#endif + + } //END of if acodec_config_need + +/*#if DRIVER_DEBUG > 0 + { + dump_msp_registers(); + dump_acodec_registers(); + } +#endif*/ + + stm_dbg(DBG_ST.acodec, + "leaving in u8500_acodec_enable_audio_mode() \n"); + + FUNC_EXIT(); + return AB8500_CODEC_OK; +} + +/** +* u8500_acodec_set_output_volume - configures the volume level for both speakers +* @in_left_volume - volume for left channel of mic +* @in_right_volume - volume for right channel of mic +* @out_left_volume - volume for left speaker +* @out_right_volume - volume for right speaker +*/ +t_ab8500_codec_error u8500_acodec_set_output_volume(t_ab8500_codec_dest + dest_device, + int left_volume, + int right_volume, + t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, + " Entering in u8500_acodec_set_output_volume()\n"); + + FUNC_ENTER(); + + user = user; //keep compiler happy + + g_codec_system_context.output_config[dest_device].left_volume = + left_volume; + g_codec_system_context.output_config[dest_device].right_volume = + right_volume; + + AB8500_CODEC_SetDestVolume(dest_device, left_volume, right_volume); + + FUNC_EXIT(); + return codec_error; +} + +/*u8500_acodec_get_output_volume*/ + +t_ab8500_codec_error u8500_acodec_get_output_volume(t_ab8500_codec_dest + dest_device, + int *p_left_volume, + int *p_right_volume, + t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, + " Entering in u8500_acodec_set_output_volume()\n"); + + user = user; //keep compiler happy + + *p_left_volume = + g_codec_system_context.output_config[dest_device].left_volume; + *p_right_volume = + g_codec_system_context.output_config[dest_device].right_volume; + + return codec_error; +} + +/** +* u8500_acodec_set_input_volume - configures the volume level for both speakers +* @in_left_volume - volume for left channel of mic +* @in_right_volume - volume for right channel of mic +* @out_left_volume - volume for left speaker +* @out_right_volume - volume for right speaker +*/ +t_ab8500_codec_error u8500_acodec_set_input_volume(t_ab8500_codec_src + src_device, int left_volume, + int right_volume, + t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, + " Entering in u8500_acodec_set_input_volume()\n"); + + user = user; //keep compiler happy + + g_codec_system_context.input_config[src_device].left_volume = + left_volume; + g_codec_system_context.input_config[src_device].right_volume = + right_volume; + + AB8500_CODEC_SetSrcVolume(src_device, left_volume, right_volume); + + return codec_error; +} + +/** +* u8500_acodec_get_input_volume - configures the volume level for both speakers +* @in_left_volume - volume for left channel of mic +* @in_right_volume - volume for right channel of mic +* @out_left_volume - volume for left speaker +* @out_right_volume - volume for right speaker +*/ +t_ab8500_codec_error u8500_acodec_get_input_volume(t_ab8500_codec_src + src_device, + int *p_left_volume, + int *p_right_volume, + t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, + " Entering in u8500_acodec_get_input_volume()\n"); + + user = user; //keep compiler happy + + *p_left_volume = + g_codec_system_context.input_config[src_device].left_volume; + *p_right_volume = + g_codec_system_context.input_config[src_device].right_volume; + + return codec_error; +} + +/** +* u8500_acodec_toggle_playback_mute_control - configures the mute for both speakers +* @in_left_volume - volume for left channel of mic +* @in_right_volume - volume for right channel of mic +* @out_left_volume - volume for left speaker +* @out_right_volume - volume for right speaker +*/ +t_ab8500_codec_error +u8500_acodec_toggle_playback_mute_control(t_ab8500_codec_dest dest_device, + t_u8500_bool_state mute_state, + t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, + " Entering in u8500_acodec_toggle_playback_mute_control \n"); + + user = user; //keep compiler happy + + g_codec_system_context.output_config[dest_device].mute_state = + mute_state; + + if (ENABLE == mute_state) { + AB8500_CODEC_DestPowerControl(dest_device, + AB8500_CODEC_SRC_STATE_ENABLE); + } else { + AB8500_CODEC_DestPowerControl(dest_device, + AB8500_CODEC_SRC_STATE_DISABLE); + } + + return codec_error; +} + +/** +* u8500_acodec_toggle_capture_mute_control - configures the mute for both speakers +* @in_left_volume - volume for left channel of mic +* @in_right_volume - volume for right channel of mic +* @out_left_volume - volume for left speaker +* @out_right_volume - volume for right speaker +*/ +t_ab8500_codec_error u8500_acodec_toggle_capture_mute_control(t_ab8500_codec_src + src_device, + t_u8500_bool_state + mute_state, + t_acodec_user + user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, + " Entering in u8500_acodec_toggle_capture_mute_control \n"); + + user = user; //keep compiler happy + + g_codec_system_context.input_config[src_device].mute_state = mute_state; + + if (ENABLE == mute_state) { + AB8500_CODEC_SrcPowerControl(src_device, + AB8500_CODEC_SRC_STATE_ENABLE); + } else { + AB8500_CODEC_SrcPowerControl(src_device, + AB8500_CODEC_SRC_STATE_DISABLE); + } + + return codec_error; +} + +/** +* u8500_acodec_select_input +* @input_device: MIC or linein. +* +* This routine selects the input device mic or linein. +*/ + +t_ab8500_codec_error u8500_acodec_select_input(t_ab8500_codec_src + input_device, + t_acodec_user user, + t_u8500_mode mode) +{ + + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, " Entering u8500_acodec_select_input\n"); + + if (TDM_8_CH_MODE == mode) + u8500_acodec_allocate_ad_slot(input_device, TDM_8_CH_MODE); + else + u8500_acodec_allocate_ad_slot(input_device, CLASSICAL_MODE); + + codec_error = AB8500_CODEC_SelectInput(input_device); + + stm_dbg(DBG_ST.acodec, " leaving u8500_acodec_select_input\n"); + return codec_error; +} + +/** +* u8500_acodec_select_output +* @output_device: output device HP/LSP +* +* This routine selects the output device Headphone or loud speaker +*/ + +t_ab8500_codec_error u8500_acodec_select_output(t_ab8500_codec_dest + output_device, + t_acodec_user user, + t_u8500_mode mode) +{ + + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + FUNC_ENTER(); + stm_dbg(DBG_ST.acodec, " Entering u8500_acodec_select_output()\n"); + + if (TDM_8_CH_MODE == mode) + u8500_acodec_allocate_da_slot(output_device, TDM_8_CH_MODE); + else + u8500_acodec_allocate_da_slot(output_device, CLASSICAL_MODE); + + codec_error = AB8500_CODEC_SelectOutput(output_device); + + stm_dbg(DBG_ST.acodec, " leaving u8500_acodec_select_output()\n"); + FUNC_EXIT(); + return codec_error; +} + +t_ab8500_codec_error u8500_acodec_allocate_ad_slot(t_ab8500_codec_src + input_device, + t_u8500_mode mode) +{ + t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line1, + ad_data_line2; + t_ab8500_codec_slot slot1, slot2; + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + slot1 = AB8500_CODEC_SLOT_UNDEFINED; + slot2 = AB8500_CODEC_SLOT_UNDEFINED; + + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED; + ad_data_line2 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED; + + switch (input_device) { + case AB8500_CODEC_SRC_D_MICROPHONE_1: + { + slot1 = AB8500_CODEC_SLOT0; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1; + } + break; + case AB8500_CODEC_SRC_MICROPHONE_2: + case AB8500_CODEC_SRC_D_MICROPHONE_2: + { + slot1 = AB8500_CODEC_SLOT1; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_3: + case AB8500_CODEC_SRC_MICROPHONE_1A: + case AB8500_CODEC_SRC_MICROPHONE_1B: + { + slot1 = AB8500_CODEC_SLOT2; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_4: + { + slot1 = AB8500_CODEC_SLOT3; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT4; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_5: + { + slot1 = AB8500_CODEC_SLOT4; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT5; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_6: + { + slot1 = AB8500_CODEC_SLOT5; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT6; + } + break; + case AB8500_CODEC_SRC_LINEIN: + { + slot1 = AB8500_CODEC_SLOT0; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1; + + slot2 = AB8500_CODEC_SLOT1; + ad_data_line2 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2; + } + case AB8500_CODEC_SRC_FM_RX: + { + slot1 = AB8500_CODEC_SLOT6; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT7; + + slot2 = AB8500_CODEC_SLOT7; + ad_data_line2 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT8; + } + break; + case AB8500_CODEC_SRC_ALL: + break; + } + + if ((AB8500_CODEC_SLOT_UNDEFINED != slot1) + && (AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED != + ad_data_line1)) { + if (CLASSICAL_MODE == mode) { + slot1 = AB8500_CODEC_SLOT0; + } + codec_error = + AB8500_CODEC_ADSlotAllocation(slot1, ad_data_line1); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + if ((AB8500_CODEC_SLOT_UNDEFINED != slot2) + && (AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED != + ad_data_line2)) { + if (CLASSICAL_MODE == mode) { + slot2 = AB8500_CODEC_SLOT1; + } + codec_error = + AB8500_CODEC_ADSlotAllocation(slot2, ad_data_line2); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + return AB8500_CODEC_OK; +} + +t_ab8500_codec_error u8500_acodec_unallocate_ad_slot(t_ab8500_codec_src + input_device, + t_u8500_mode mode) +{ + t_ab8500_codec_slot slot1, slot2; + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + slot1 = AB8500_CODEC_SLOT_UNDEFINED; + slot2 = AB8500_CODEC_SLOT_UNDEFINED; + + switch (input_device) { + case AB8500_CODEC_SRC_D_MICROPHONE_1: + { + slot1 = AB8500_CODEC_SLOT0; + } + break; + case AB8500_CODEC_SRC_MICROPHONE_2: + case AB8500_CODEC_SRC_D_MICROPHONE_2: + { + slot1 = AB8500_CODEC_SLOT1; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_3: + case AB8500_CODEC_SRC_MICROPHONE_1A: + case AB8500_CODEC_SRC_MICROPHONE_1B: + { + slot1 = AB8500_CODEC_SLOT2; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_4: + { + slot1 = AB8500_CODEC_SLOT3; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_5: + { + slot1 = AB8500_CODEC_SLOT4; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_6: + { + slot1 = AB8500_CODEC_SLOT5; + } + break; + case AB8500_CODEC_SRC_LINEIN: + { + slot1 = AB8500_CODEC_SLOT0; + slot2 = AB8500_CODEC_SLOT1; + } + break; + case AB8500_CODEC_SRC_ALL: + break; + } + + if (AB8500_CODEC_SLOT_UNDEFINED != slot1) { + if (CLASSICAL_MODE == mode) { + slot1 = AB8500_CODEC_SLOT0; + } + codec_error = + AB8500_CODEC_ADSlotAllocation(slot1, + AB8500_CODEC_CR31_TO_CR46_SLOT_IS_TRISTATE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + if (AB8500_CODEC_SLOT_UNDEFINED != slot2) { + if (CLASSICAL_MODE == mode) { + slot2 = AB8500_CODEC_SLOT1; + } + codec_error = + AB8500_CODEC_ADSlotAllocation(slot2, + AB8500_CODEC_CR31_TO_CR46_SLOT_IS_TRISTATE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + return AB8500_CODEC_OK; +} + +#ifdef CONFIG_U8500_AB8500_CUT10 +t_ab8500_codec_error u8500_acodec_allocate_da_slot(t_ab8500_codec_dest + output_device, + t_u8500_mode mode) +{ + t_ab8500_codec_da_channel_number da_ch_no1, da_ch_no2; + t_ab8500_codec_cr51_to_cr58_sltoda da_slot1, da_slot2; + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED; + da_ch_no2 = AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED; + + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT_UNDEFINED; + da_slot2 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT_UNDEFINED; + + switch (output_device) { + case AB8500_CODEC_DEST_HEADSET: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_1; + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT08; + + da_ch_no2 = AB8500_CODEC_DA_CHANNEL_NUMBER_2; + da_slot2 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT09; + } + break; + case AB8500_CODEC_DEST_EARPIECE: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_1; + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT08; + } + break; + case AB8500_CODEC_DEST_HANDSFREE: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_3; + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT10; + + da_ch_no2 = AB8500_CODEC_DA_CHANNEL_NUMBER_4; + da_slot2 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT11; + } + break; + case AB8500_CODEC_DEST_VIBRATOR_L: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_5; + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT12; + } + break; + case AB8500_CODEC_DEST_VIBRATOR_R: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_6; + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT13; + } + break; + + case AB8500_CODEC_DEST_FM_TX: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_7; + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT14; + + da_ch_no2 = AB8500_CODEC_DA_CHANNEL_NUMBER_8; + da_slot2 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT15; + } + + case AB8500_CODEC_DEST_ALL: + break; + } + + if ((AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED != da_ch_no1) + && (AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT_UNDEFINED != da_slot1)) { + if (CLASSICAL_MODE == mode) { + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT08; + } + codec_error = + AB8500_CODEC_DASlotAllocation(da_ch_no1, da_slot1); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + if ((AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED != da_ch_no2) + && (AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT_UNDEFINED != da_slot2)) { + if (CLASSICAL_MODE == mode) { + da_slot1 = AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT09; + } + codec_error = + AB8500_CODEC_DASlotAllocation(da_ch_no2, da_slot2); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + return AB8500_CODEC_OK; +} + +#else +t_ab8500_codec_error u8500_acodec_allocate_da_slot(t_ab8500_codec_dest + output_device, + t_u8500_mode mode) +{ + t_ab8500_codec_da_channel_number da_ch_no1, da_ch_no2; + t_ab8500_codec_cr51_to_cr56_sltoda da_slot1, da_slot2; + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED; + da_ch_no2 = AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED; + + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT_UNDEFINED; + da_slot2 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT_UNDEFINED; + + switch (output_device) { + case AB8500_CODEC_DEST_HEADSET: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_1; + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT08; + + da_ch_no2 = AB8500_CODEC_DA_CHANNEL_NUMBER_2; + da_slot2 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT09; + } + break; + case AB8500_CODEC_DEST_EARPIECE: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_1; + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT08; + } + break; + case AB8500_CODEC_DEST_HANDSFREE: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_3; + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT10; + + da_ch_no2 = AB8500_CODEC_DA_CHANNEL_NUMBER_4; + da_slot2 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT11; + } + break; + case AB8500_CODEC_DEST_VIBRATOR_L: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_5; + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT12; + } + break; + case AB8500_CODEC_DEST_VIBRATOR_R: + { + da_ch_no1 = AB8500_CODEC_DA_CHANNEL_NUMBER_6; + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT13; + } + break; + + case AB8500_CODEC_DEST_ALL: + break; + } + + if ((AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED != da_ch_no1) + && (AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT_UNDEFINED != da_slot1)) { + if (CLASSICAL_MODE == mode) { + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT08; + } + codec_error = + AB8500_CODEC_DASlotAllocation(da_ch_no1, da_slot1); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + if ((AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED != da_ch_no2) + && (AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT_UNDEFINED != da_slot2)) { + if (CLASSICAL_MODE == mode) { + da_slot1 = AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT09; + } + codec_error = + AB8500_CODEC_DASlotAllocation(da_ch_no2, da_slot2); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + + return AB8500_CODEC_OK; +} +#endif + +t_ab8500_codec_error u8500_acodec_unallocate_da_slot(t_ab8500_codec_dest + output_device, + t_u8500_mode mode) +{ + return AB8500_CODEC_OK; +} + +t_ab8500_codec_error u8500_acodec_set_src_power_cntrl(t_ab8500_codec_src + input_device, + t_u8500_bool_state + pwr_state) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + if (ENABLE == pwr_state) { + u8500_acodec_allocate_ad_slot(input_device, TDM_8_CH_MODE); + codec_error = + AB8500_CODEC_SrcPowerControl(input_device, + AB8500_CODEC_SRC_STATE_ENABLE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_SrcPowerControl failed\n"); + return AB8500_CODEC_ERROR; + } + g_codec_system_context.input_config[input_device].power_state = + ENABLE; + } else { + u8500_acodec_unallocate_ad_slot(input_device, TDM_8_CH_MODE); + codec_error = + AB8500_CODEC_SrcPowerControl(input_device, + AB8500_CODEC_SRC_STATE_DISABLE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_SrcPowerControl failed\n"); + return AB8500_CODEC_ERROR; + } + g_codec_system_context.input_config[input_device].power_state = + DISABLE; + } + + return AB8500_CODEC_OK; +} + +t_u8500_bool_state u8500_acodec_get_src_power_state(t_ab8500_codec_src + input_device) +{ + return (g_codec_system_context.input_config[input_device].power_state); +} + +t_ab8500_codec_error u8500_acodec_set_dest_power_cntrl(t_ab8500_codec_dest + output_device, + t_u8500_bool_state + pwr_state) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + if (ENABLE == pwr_state) { + AB8500_CODEC_SelectInterface(AB8500_CODEC_AUDIO_INTERFACE_0); + + codec_error = AB8500_CODEC_PowerUp(); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_PowerUp failed\n"); + return AB8500_CODEC_ERROR; + } + + u8500_acodec_allocate_da_slot(output_device, TDM_8_CH_MODE); + + codec_error = + AB8500_CODEC_DestPowerControl(output_device, + AB8500_CODEC_DEST_STATE_ENABLE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_DestPowerControl failed\n"); + return AB8500_CODEC_ERROR; + } + g_codec_system_context.output_config[output_device]. + power_state = ENABLE; + } else { + u8500_acodec_unallocate_da_slot(output_device, TDM_8_CH_MODE); + codec_error = + AB8500_CODEC_DestPowerControl(output_device, + AB8500_CODEC_DEST_STATE_DISABLE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_DestPowerControl failed\n"); + return AB8500_CODEC_ERROR; + } + g_codec_system_context.output_config[output_device]. + power_state = DISABLE; + } + + return AB8500_CODEC_OK; +} + +t_u8500_bool_state u8500_acodec_get_dest_power_state(t_ab8500_codec_dest + output_device) +{ + return (g_codec_system_context.output_config[output_device]. + power_state); +} + +/** +* u8500_acodec_toggle_analog_lpbk +* @output_device: output device HP/LSP +* +* This routine selects the output device Headphone or loud speaker +*/ +t_ab8500_codec_error u8500_acodec_toggle_analog_lpbk(t_u8500_bool_state + lpbk_state, + t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + stm_dbg(DBG_ST.acodec, + " Entering inu8500_acodec_toggle_analog_lpbk() \n"); + + user = user; //keep compiler happy + + if (ENABLE == lpbk_state) { + /* Reset CODEC */ + codec_error = AB8500_CODEC_Reset(); + + AB8500_CODEC_SelectInterface(AB8500_CODEC_AUDIO_INTERFACE_0); + + codec_error = AB8500_CODEC_PowerUp(); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_PowerUp failed\n"); + return AB8500_CODEC_ERROR; + } + + codec_error = AB8500_CODEC_SelectInput(AB8500_CODEC_SRC_LINEIN); + + codec_error = + AB8500_CODEC_SrcPowerControl(AB8500_CODEC_SRC_LINEIN, + AB8500_CODEC_SRC_STATE_ENABLE); + + //codec_error = AB8500_CODEC_SetSrcVolume(AB8500_CODEC_SRC_LINEIN,VOL_MAX,VOL_MAX); + + codec_error = + AB8500_CODEC_SelectOutput(AB8500_CODEC_DEST_HEADSET); + + codec_error = + AB8500_CODEC_DestPowerControl(AB8500_CODEC_DEST_HEADSET, + AB8500_CODEC_DEST_STATE_ENABLE); + + //codec_error = AB8500_CODEC_SetDestVolume(AB8500_CODEC_DEST_HEADSET,0,0); + + codec_error = AB8500_CODEC_SetAnalogLoopback(VOL_MAX, VOL_MAX); + + ab8500_write(AB8500_AUDIO, 0xd05, 0x30); + ab8500_write(AB8500_AUDIO, 0xd07, 0xf3); + ab8500_write(AB8500_AUDIO, 0xd16, 0xdd); + ab8500_write(AB8500_AUDIO, 0xd17, 0x55); + ab8500_write(AB8500_AUDIO, 0xd3f, 0xc0); + + } else { + codec_error = AB8500_CODEC_RemoveAnalogLoopback(); + } + +#if DRIVER_DEBUG > 0 + { + dump_acodec_registers(); + } +#endif + + return codec_error; +} + +#ifdef CONFIG_U8500_ACODEC_POLL + +static int digital_lpbk_msp_rx_tx_thread(void *data) +{ + t_digital_lpbk_cnxt *p_cnxt = (t_digital_lpbk_cnxt *) data; + unsigned int sample[8], count = 32; + + daemonize("digital_lpbk_msp_rx_tx_thread"); + allow_signal(SIGKILL); + + printk("\n Rx-Tx : digital_lpbk_msp_rx_tx_thread started \n"); + + while ((!signal_pending(current)) && (p_cnxt->rx_active)) { + +// ret_val = u8500_msp_receive_data(alsa_msp_adev,p_cnxt->buffer[p_cnxt->rx_index],p_cnxt->data_size); + + //u8500_msp_transceive_data(alsa_msp_adev,p_cnxt->buffer[0], p_cnxt->data_size,p_cnxt->buffer[1], p_cnxt->data_size); + + //u8500_msp_transceive_data(alsa_msp_adev,p_cnxt->buffer[1], p_cnxt->data_size,p_cnxt->buffer[0], p_cnxt->data_size); + +#if DRIVER_DEBUG > 1 + stm_dbg(DBG_ST.alsa, " Receiving \n"); +#endif + u8500_acodec_receive_data(I2S_CLIENT_MSP1, (void *)sample, + count, 0); + +#if DRIVER_DEBUG > 1 + stm_dbg(DBG_ST.alsa, " Transmitting \n"); +#endif + u8500_acodec_send_data(I2S_CLIENT_MSP1, (void *)sample, count, + 0); + + } + printk("\n Rx-Tx : digital_lpbk_msp_rx_tx_thread ended \n"); + return 0; +} + +#endif + +#ifdef CONFIG_U8500_ACODEC_DMA + +static void u8500_digital_lpbk_dma_start() +{ + u8500_acodec_loopback_configure(I2S_CLIENT_MSP1, + (void *)digital_lpbk_cnxt.buffer.addr, + digital_lpbk_cnxt.data_size, 1); + + stm_dbg(DBG_ST.alsa, " Rx DMA Transfer started\n"); + stm_dbg(DBG_ST.alsa, " Rx : add = %x size=%d\n", + (int)(digital_lpbk_cnxt.buffer.addr), + digital_lpbk_cnxt.data_size); + +} +#endif + +/** +* u8500_acodec_toggle_digital_lpbk +* @output_device: output device HP/LSP +* +* This routine selects the output device Headphone or loud speaker +*/ + +t_ab8500_codec_error u8500_acodec_toggle_digital_lpbk(t_u8500_bool_state + lpbk_state, + t_ab8500_codec_dest + dest_device, + t_ab8500_codec_src + src_device, + t_acodec_user user, + t_u8500_bool_state + tdm8_ch_mode) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + struct acodec_configuration acodec_config; + int status = 0; + + stm_dbg(DBG_ST.acodec, + " Entering u8500_acodec_toggle_digital_lpbk() \n"); + + user = user; //keep compiler happy + + if (ENABLE == lpbk_state) { + //data_size = 1024*100; + + //data[0] = (unsigned char *)kmalloc(data_size, GFP_KERNEL); + + codec_error = AB8500_CODEC_Reset(); + + //AB8500_CODEC_SelectInterface(AB8500_CODEC_AUDIO_INTERFACE_0); + + //codec_error = AB8500_CODEC_PowerUp(); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_PowerUp failed\n"); + return AB8500_CODEC_ERROR; + } + + status = u8500_acodec_open(I2S_CLIENT_MSP1, 0); + if (status) { + printk("failed in getting acodec playback open\n"); + return -1; + } + status = u8500_acodec_open(I2S_CLIENT_MSP1, 1); + if (status) { + printk("failed in getting acdoec capture open\n"); + return -1; + } + + u8500_acodec_setuser(USER_ALSA); + + if (ENABLE == tdm8_ch_mode) { + printk("\n 20 bit 8 ch Digital Loopback"); + printk("\n DMIC1 -> HS-L"); + printk("\n DMIC2 -> HS-R"); + printk("\n DMIC3 -> IHF-L"); + printk("\n DMIC5 -> Vibra-L\n"); + printk("\n DMIC6 -> Vibra-R\n"); + printk("\n FM -> FM Tx\n"); + } else { + printk("\n 16 bit 2 ch Digital Loopback"); + printk("\n DMIC1 -> HS-L"); + printk("\n DMIC2 -> HS-R"); + } + + stm_dbg(DBG_ST.alsa, "enabling audiocodec audio mode\n"); + acodec_config.direction = AB8500_CODEC_DIRECTION_INOUT; + acodec_config.input_frequency = T_CODEC_SAMPLING_FREQ_48KHZ; + acodec_config.output_frequency = T_CODEC_SAMPLING_FREQ_48KHZ; + acodec_config.mspClockSel = CODEC_MSP_APB_CLOCK; + acodec_config.mspInClockFreq = CODEC_MSP_INPUT_FREQ_48MHZ; + acodec_config.channels = 2; + acodec_config.user = 2; + acodec_config.acodec_config_need = ACODEC_CONFIG_REQUIRED; + acodec_config.direct_rendering_mode = DISABLE; + acodec_config.tdm8_ch_mode = tdm8_ch_mode; + acodec_config.digital_loopback = ENABLE; +#ifdef CONFIG_U8500_ACODEC_POLL + acodec_config.handler = NULL; + acodec_config.tx_callback_data = NULL; + acodec_config.rx_callback_data = NULL; +#endif + u8500_acodec_enable_audio_mode(&acodec_config); + + /*turn on src devices */ + + perform_src_routing(src_device); + +/* u8500_acodec_set_src_power_cntrl(src_device,ENABLE); + u8500_acodec_set_input_volume(src_device,50,50,USER_ALSA); + + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_2,ENABLE); + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_2,50,50,USER_ALSA); + + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_3,ENABLE); + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_3,50,50,USER_ALSA); + + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_4,ENABLE); + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_4,50,50,USER_ALSA); + + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_5,ENABLE); + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_5,50,50,USER_ALSA); + + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_6,ENABLE); + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_6,50,50,USER_ALSA); + + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_6,ENABLE); + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_6,50,50,USER_ALSA); + + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_FM_RX,ENABLE); */ + + /*turn on dest devices */ + + //u8500_acodec_set_dest_power_cntrl(dest_device,ENABLE); + u8500_acodec_allocate_da_slot(dest_device, TDM_8_CH_MODE); + codec_error = AB8500_CODEC_SelectOutput(dest_device); + u8500_acodec_set_output_volume(dest_device, 100, 100, + USER_ALSA); + + /*u8500_acodec_set_dest_power_cntrl(AB8500_CODEC_DEST_HEADSET,ENABLE); + u8500_acodec_set_output_volume(AB8500_CODEC_DEST_HEADSET,100,100,USER_ALSA); */ + + /*u8500_acodec_set_dest_power_cntrl(AB8500_CODEC_DEST_HANDSFREE,ENABLE); + u8500_acodec_set_output_volume(AB8500_CODEC_DEST_HANDSFREE,100,100,USER_ALSA); */ + +#ifdef CONFIG_U8500_AB8500_CUT10 + codec_error = + AB8500_CODEC_DASlotAllocation + (AB8500_CODEC_DA_CHANNEL_NUMBER_5, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT12); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + + codec_error = + AB8500_CODEC_DASlotAllocation + (AB8500_CODEC_DA_CHANNEL_NUMBER_6, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT13); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + + codec_error = + AB8500_CODEC_DASlotAllocation + (AB8500_CODEC_DA_CHANNEL_NUMBER_7, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT14); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + + codec_error = + AB8500_CODEC_DASlotAllocation + (AB8500_CODEC_DA_CHANNEL_NUMBER_8, + AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT15); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } +#else + codec_error = + AB8500_CODEC_DASlotAllocation + (AB8500_CODEC_DA_CHANNEL_NUMBER_5, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT12); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + + codec_error = + AB8500_CODEC_DASlotAllocation + (AB8500_CODEC_DA_CHANNEL_NUMBER_6, + AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT13); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_daslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } +#endif + + digital_lpbk_cnxt.data_size = 2048; + + digital_lpbk_cnxt.rx_active = 1; + digital_lpbk_cnxt.tx_active = 1; + + digital_lpbk_cnxt.rx_index = 0; + digital_lpbk_cnxt.tx_index = 2; + + digital_lpbk_cnxt.buffer.area = + dma_alloc_coherent(NULL, digital_lpbk_cnxt.data_size, + &digital_lpbk_cnxt.buffer.addr, + GFP_KERNEL); + if (NULL == digital_lpbk_cnxt.buffer.area) { + printk("\n dma_alloc_coherent failed \n"); + } +#if DRIVER_DEBUG > 0 + { + dump_msp_registers(); + dump_acodec_registers(); + } +#endif + +#ifdef CONFIG_U8500_ACODEC_POLL + { + pid_t pid_rx_tx; + pid_rx_tx = + kernel_thread(digital_lpbk_msp_rx_tx_thread, + &digital_lpbk_cnxt, + CLONE_FS | CLONE_SIGHAND); + } +#elif defined(CONFIG_U8500_ACODEC_DMA) + { + u8500_digital_lpbk_dma_start(); + } +#endif + } else //lpbk is disable + { + + digital_lpbk_cnxt.rx_active = 0; + digital_lpbk_cnxt.tx_active = 0; + + dma_free_coherent(NULL, digital_lpbk_cnxt.data_size, + digital_lpbk_cnxt.buffer.area, + digital_lpbk_cnxt.buffer.addr); + + u8500_acodec_set_src_power_cntrl + (AB8500_CODEC_SRC_D_MICROPHONE_1, DISABLE); + u8500_acodec_set_src_power_cntrl + (AB8500_CODEC_SRC_D_MICROPHONE_2, DISABLE); + u8500_acodec_set_src_power_cntrl + (AB8500_CODEC_SRC_D_MICROPHONE_3, DISABLE); + u8500_acodec_set_src_power_cntrl + (AB8500_CODEC_SRC_D_MICROPHONE_4, DISABLE); + + u8500_acodec_set_dest_power_cntrl(AB8500_CODEC_DEST_HEADSET, + DISABLE); + u8500_acodec_set_dest_power_cntrl(AB8500_CODEC_DEST_HANDSFREE, + DISABLE); + + u8500_acodec_unsetuser(USER_ALSA); + u8500_acodec_close(I2S_CLIENT_MSP1, ACODEC_DISABLE_ALL); + } + return codec_error; +} + +t_ab8500_codec_error perform_src_routing(t_ab8500_codec_src input_device) +{ + int src_type = 0; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line1; + t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line2; + t_ab8500_codec_src input_device1; + t_ab8500_codec_src input_device2; + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + switch (input_device) { + case AB8500_CODEC_SRC_D_MICROPHONE_1: + { + src_type = MONO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1; + } + break; + case AB8500_CODEC_SRC_MICROPHONE_2: + case AB8500_CODEC_SRC_D_MICROPHONE_2: + { + src_type = MONO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_3: + case AB8500_CODEC_SRC_MICROPHONE_1A: + case AB8500_CODEC_SRC_MICROPHONE_1B: + { + src_type = MONO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_4: + { + src_type = MONO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT4; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_5: + { + src_type = MONO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT5; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_6: + { + src_type = MONO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT6; + } + break; + case AB8500_CODEC_SRC_LINEIN: + { + src_type = STEREO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1; + ad_data_line2 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2; + input_device1 = AB8500_CODEC_SRC_LINEIN; + input_device2 = AB8500_CODEC_SRC_LINEIN; + } + break; +#ifdef CONFIG_U8500_AB8500_CUT10 + case AB8500_CODEC_SRC_D_MICROPHONE_12: + { + src_type = STEREO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1; + ad_data_line2 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2; + input_device1 = AB8500_CODEC_SRC_D_MICROPHONE_1; + input_device2 = AB8500_CODEC_SRC_D_MICROPHONE_2; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_34: + { + src_type = STEREO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3; + ad_data_line2 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT4; + input_device1 = AB8500_CODEC_SRC_D_MICROPHONE_3; + input_device2 = AB8500_CODEC_SRC_D_MICROPHONE_4; + } + break; + case AB8500_CODEC_SRC_D_MICROPHONE_56: + { + src_type = STEREO_SRC; + ad_data_line1 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT5; + ad_data_line2 = + AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT6; + input_device1 = AB8500_CODEC_SRC_D_MICROPHONE_5; + input_device2 = AB8500_CODEC_SRC_D_MICROPHONE_6; + } + break; +#endif /* #ifdef CONFIG_U8500_AB8500_CUT10 */ + } + if (STEREO_SRC == src_type) { + u8500_acodec_allocate_all_stereo_slots(ad_data_line1, + ad_data_line2); + codec_error = + AB8500_CODEC_SrcPowerControl(input_device1, + AB8500_CODEC_SRC_STATE_ENABLE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_SrcPowerControl failed\n"); + return AB8500_CODEC_ERROR; + } + g_codec_system_context.input_config[input_device1].power_state = + ENABLE; + + u8500_acodec_set_input_volume(input_device1, 50, 50, USER_ALSA); + + codec_error = + AB8500_CODEC_SrcPowerControl(input_device2, + AB8500_CODEC_SRC_STATE_ENABLE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_SrcPowerControl failed\n"); + return AB8500_CODEC_ERROR; + } + g_codec_system_context.input_config[input_device2].power_state = + ENABLE; + + u8500_acodec_set_input_volume(input_device2, 50, 50, USER_ALSA); + } else { + u8500_acodec_allocate_all_mono_slots(ad_data_line1); + codec_error = + AB8500_CODEC_SrcPowerControl(input_device, + AB8500_CODEC_SRC_STATE_ENABLE); + if (AB8500_CODEC_OK != codec_error) { + stm_error("AB8500_CODEC_SrcPowerControl failed\n"); + return AB8500_CODEC_ERROR; + } + g_codec_system_context.input_config[input_device].power_state = + ENABLE; + + u8500_acodec_set_input_volume(input_device, 50, 50, USER_ALSA); + } + return AB8500_CODEC_OK; +} + +t_ab8500_codec_error + u8500_acodec_allocate_all_mono_slots + (t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line1) { + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + int i; + + for (i = AB8500_CODEC_SLOT0; i <= AB8500_CODEC_SLOT7; i++) { + codec_error = AB8500_CODEC_ADSlotAllocation(i, ad_data_line1); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + return AB8500_CODEC_OK; +} + +t_ab8500_codec_error + u8500_acodec_allocate_all_stereo_slots + (t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line1, + t_ab8500_codec_cr31_to_cr46_ad_data_allocation ad_data_line2) { + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + int i; + + for (i = AB8500_CODEC_SLOT0; i <= AB8500_CODEC_SLOT7; i += 2) { + codec_error = AB8500_CODEC_ADSlotAllocation(i, ad_data_line1); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + codec_error = + AB8500_CODEC_ADSlotAllocation(i + 1, ad_data_line2); + if (AB8500_CODEC_OK != codec_error) { + stm_error("ab8500_codec_adslot_allocation failed\n"); + return AB8500_CODEC_ERROR; + } + } + return AB8500_CODEC_OK; +} + +#ifdef CONFIG_U8500_AB8500_CUT10 +t_ab8500_codec_error +u8500_acodec_set_burst_mode_fifo(t_u8500_pmc_rendering_state fifo_state) +{ + +} +#else +t_ab8500_codec_error +u8500_acodec_set_burst_mode_fifo(t_u8500_pmc_rendering_state fifo_state) +{ + t_ab8500_codec_error ab8500_codec_error; + t_ab8500_codec_burst_fifo_config burst_fifo_config; + + if (RENDERING_ENABLE == fifo_state) { + burst_fifo_config.cr104_bfifoint = 0x1; + burst_fifo_config.cr105_bfifotx = 0xC0; + burst_fifo_config.cr106_bfifofsext = + AB8500_CODEC_CR106_BFIFOFSEXT_6SLOT_EXTRA_CLK; + burst_fifo_config.cr106_bfifomsk = + AB8500_CODEC_CR106_BFIFOMSK_AD_DATA0_UNMASKED; + burst_fifo_config.cr106_bfifomstr = + AB8500_CODEC_CR106_BFIFOMSTR_MASTER_MODE; + burst_fifo_config.cr106_bfifostrt = + AB8500_CODEC_CR106_BFIFOSTRT_RUNNING; + burst_fifo_config.cr107_bfifosampnr = 0x100; + burst_fifo_config.cr108_bfifowakeup = 0x1; + + ab8500_codec_error = + AB8500_CODEC_ConfigureBurstFifo(&burst_fifo_config); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return ab8500_codec_error; + } + + ab8500_codec_error = AB8500_CODEC_EnableBurstFifo(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return ab8500_codec_error; + } + + printk("\n Burst mode activated\n"); + } else if (RENDERING_DISABLE == fifo_state) { + ab8500_codec_error = AB8500_CODEC_DisableBurstFifo(); + if (AB8500_CODEC_OK != ab8500_codec_error) { + return ab8500_codec_error; + } + printk("\n Burst mode deactivated\n"); + } + return AB8500_CODEC_OK; +} +#endif +/** +* u8500_acodec_set_user +* +* Set the current user for acodec. +*/ + +t_ab8500_codec_error u8500_acodec_setuser(t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + FUNC_ENTER(); + + if ((g_codec_system_context.cur_user == NO_USER) + || (g_codec_system_context.cur_user == user)) + g_codec_system_context.cur_user = user; + else { + stm_error + (" Trying to acces audiocodec already in use by user %d\n", + g_codec_system_context.cur_user); + return AB8500_CODEC_ERROR; + } + FUNC_EXIT(); + return (codec_error); +} + +/** +* u8500_acodec_unset_user +* +* Unset the current user for acodec. +*/ + +t_ab8500_codec_error u8500_acodec_unsetuser(t_acodec_user user) +{ + t_ab8500_codec_error codec_error = AB8500_CODEC_OK; + + if (g_codec_system_context.cur_user != user) { + stm_error + (" Trying to free audiocodec already in use by other user %d\n", + g_codec_system_context.cur_user); + return AB8500_CODEC_ERROR; + } else + g_codec_system_context.cur_user = NO_USER; + + return (codec_error); +} + +#if DRIVER_DEBUG > 0 +t_ab8500_codec_error dump_acodec_registers() +{ + u8 i; + + for (i = 0; i <= 0x6D; i++) + stm_dbg(DBG_ST.acodec, "block=0x0D, adr=%x = %x\n", i, + ab8500_read(AB8500_AUDIO, i)); + + /*for (i = 0; i < 0x5e; i++) + stm_dbg(DBG_ST.acodec,"\n block 1,reg =%d val %x", i, ab8500_read(AB8500_AUDIO, i)); + */ + return 0; +} + +t_ab8500_codec_error dump_msp_registers() +{ + int i; + + stm_dbg(DBG_ST.acodec, "\nMSP_1 base add = 0x%x\n", + (unsigned int)U8500_MSP1_BASE); + + for (i = 0; i < 0x40; i += 4) + stm_dbg(DBG_ST.acodec, "msp[0x%x]=0x%x\n", i, + readl((char *)(IO_ADDRESS(U8500_MSP1_BASE) + i))); + + return 0; +} + +EXPORT_SYMBOL(dump_msp_registers); +EXPORT_SYMBOL(dump_acodec_registers); +#endif + +/** +* u8500_acodec_powerdown +* +* This function power off the audio codec. +*/ +void u8500_acodec_powerdown() +{ + AB8500_CODEC_PowerDown(); +} + +/** +* u8500_acodec_init +* +* This is the init function for STW5098 audiocodec driver. +*/ + +static int i2sdrv_probe(struct i2s_device *i2s) +{ + + /* Allocate driver data */ + try_module_get(i2s->controller->dev.parent->driver->owner); + + /* Allocate memory to i2sdrv structure */ + i2sdrv[i2s->chip_select] = + kzalloc(sizeof(*i2sdrv[i2s->chip_select]), GFP_KERNEL); + if (!i2sdrv[i2s->chip_select]) + return -ENOMEM; + + /* Initialize the driver data */ + i2sdrv[i2s->chip_select]->i2s = i2s; + i2sdrv[i2s->chip_select]->flag = -1; + i2sdrv[i2s->chip_select]->tx_status = 0; + i2sdrv[i2s->chip_select]->rx_status = 0; + spin_lock_init(&i2sdrv[i2s->chip_select]->i2s_lock); + + i2s_set_drvdata(i2s, (void *)i2sdrv[i2s->chip_select]); + return 0; +} + +static int i2sdrv_remove(struct i2s_device *i2s) +{ + struct i2sdrv_data *i2sdrv = i2s_get_drvdata(i2s); + + spin_lock_irq(&i2sdrv->i2s_lock); + i2sdrv->i2s = NULL; + i2s_set_drvdata(i2s, NULL); + spin_unlock_irq(&i2sdrv->i2s_lock); + + stm_dbg(DBG_ST.acodec, "Entering AUDIOTRG_CODEC_DeIni\n"); + stm_dbg(DBG_ST.acodec, "leaving AUDIOTRG_CODEC_DeIni\n"); + module_put(i2s->controller->dev.parent->driver->owner); + printk("Remove of I2S gets called\n"); + return 0; +} +static const struct i2s_device_id acodec_id_table[] = { + {"i2s_device.2", 0, 0}, + {"i2s_device.1", 0, 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2s, acodec_id_table); + +static struct i2s_driver i2sdrv_i2s = { + .driver = { + .name = "u8500_acodec", + .owner = THIS_MODULE, + }, + .probe = i2sdrv_probe, + .remove = __devexit_p(i2sdrv_remove), + .id_table = acodec_id_table, + +}; + +static void ab8500_codec_power_init(void) +{ + __u8 data, old_data; + + old_data = + ab8500_read(AB8500_SYS_CTRL2_BLOCK, (AB8500_CTRL3_REG & 0xFF)); + + data = 0xFE & old_data; + ab8500_write(AB8500_SYS_CTRL2_BLOCK, (AB8500_CTRL3_REG & 0xFF), data); //0x0200 + + data = 0x02 | old_data; + ab8500_write(AB8500_SYS_CTRL2_BLOCK, (AB8500_CTRL3_REG & 0xFF), data); //0x0200 + + old_data = + ab8500_read(AB8500_SYS_CTRL2_BLOCK, + (AB8500_SYSULPCLK_CTRL1_REG & 0xFF)); +#ifdef CONFIG_U8500_AB8500_CUT10 + data = 0x18 | old_data; +#else + data = 0x10 | old_data; +#endif + ab8500_write(AB8500_SYS_CTRL2_BLOCK, (AB8500_SYSULPCLK_CTRL1_REG & 0xFF), data); //0x020B + + old_data = + ab8500_read(AB8500_REGU_CTRL1, (AB8500_REGU_MISC1_REG & 0xFF)); + data = 0x04 | old_data; + ab8500_write(AB8500_REGU_CTRL1, (AB8500_REGU_MISC1_REG & 0xFF), data); //0x380 + + old_data = + ab8500_read(AB8500_REGU_CTRL1, + (AB8500_REGU_VAUDIO_SUPPLY_REG & 0xFF)); + data = 0x5E | old_data; + ab8500_write(AB8500_REGU_CTRL1, (AB8500_REGU_VAUDIO_SUPPLY_REG & 0xFF), data); //0x0383 + +#ifdef CONFIG_U8500_AB8500_CUT10 + old_data = ab8500_read(AB8500_MISC, (AB8500_GPIO_DIR4_REG & 0xFF)); + data = 0x54 | old_data; + ab8500_write(AB8500_MISC, (AB8500_GPIO_DIR4_REG & 0xFF), data); //0x1013 +#endif +} + +/** +* u8500_acodec_deinit +* +* exit function for STW5098 audiocodec driver. +*/ +static int check_device_id() +{ + __u8 data; + + data = ab8500_read(AB8500_MISC, (0x80 & 0xFF)); + if (((data & 0xF0) == 0x10) || ((data & 0xF0) == 0x11)) { + /* V1 version */ +#ifndef CONFIG_U8500_AB8500_CUT10 + printk("ERROR: AB8500 hardware detected is CUT1x\n"); + return -ENODEV; +#endif + } else { +#ifndef CONFIG_U8500_AB8500_ED + /* ED version */ + printk("ERROR: AB8500 hardware detected is EarlyDrop\n"); + return -ENODEV; +#endif + } + return 0; +} + +static int __init u8500_acodec_init(void) +{ + int status, ret_val; + t_ab8500_codec_error error; + + ret_val = check_device_id(); + if (0 != ret_val) + return ret_val; + + status = i2s_register_driver(&i2sdrv_i2s); + if (status < 0) { + printk("Unable to register i2s driver\n"); + return status; + } + + /*Initialize Audiocodec */ + + ab8500_codec_power_init(); + + AB8500_CODEC_Init(TRG_CODEC_ADDRESS_ON_SPI_BUS); + + /* Reset CODEC */ + error = AB8500_CODEC_Reset(); + if (AB8500_CODEC_OK != error) { + stm_error("Error in AB8500_CODEC_Reset\n"); + return -1; + } + + stm_dbg(DBG_ST.acodec, " leaving u8500_acodec_init() \n"); + return 0; +} + +static void __exit u8500_acodec_deinit(void) +{ + stm_dbg(DBG_ST.acodec, "Entering AUDIOTRG_CODEC_DeIni\n"); + stm_dbg(DBG_ST.acodec, "leaving AUDIOTRG_CODEC_DeIni\n"); + i2s_unregister_driver(&i2sdrv_i2s); +} + +module_init(u8500_acodec_init); +module_exit(u8500_acodec_deinit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AB8500 stw5098 audiocodec driver"); + +/* exported function by audiocodec to be used by SAA driver and ALSA driver */ + +EXPORT_SYMBOL(u8500_acodec_open); +EXPORT_SYMBOL(u8500_acodec_close); +EXPORT_SYMBOL(u8500_acodec_send_data); +EXPORT_SYMBOL(u8500_acodec_receive_data); +EXPORT_SYMBOL(u8500_acodec_rates); +EXPORT_SYMBOL(u8500_acodec_powerdown); +EXPORT_SYMBOL(u8500_acodec_setuser); +EXPORT_SYMBOL(u8500_acodec_unsetuser); +EXPORT_SYMBOL(u8500_acodec_enable_audio_mode); +//EXPORT_SYMBOL(u8500_acodec_enable_voice_mode); +EXPORT_SYMBOL(u8500_acodec_get_output_volume); +EXPORT_SYMBOL(u8500_acodec_get_input_volume); +EXPORT_SYMBOL(u8500_acodec_set_output_volume); +EXPORT_SYMBOL(u8500_acodec_set_input_volume); +EXPORT_SYMBOL(u8500_acodec_select_input); +EXPORT_SYMBOL(u8500_acodec_select_output); + +t_ab8500_codec_error AB8500_CODEC_Write(IN t_uint8 register_offset, + IN t_uint8 count, IN t_uint8 * ptr_data) +{ + int i; + u32 address; + + for (i = 0; i < count; i++) { + address = (AB8500_AUDIO << 8) | (register_offset + i); + ab8500_write(AB8500_AUDIO, address, ptr_data[i]); + } + return AB8500_CODEC_OK; +} + +t_ab8500_codec_error AB8500_CODEC_Read(IN t_uint8 register_offset, + IN t_uint8 count, + IN t_uint8 * dummy_data, + IN t_uint8 * ptr_data) +{ + int i; + u32 address; + + dummy_data = dummy_data; /*keep compiler happy */ + + for (i = 0; i < count; i++) { + address = (AB8500_AUDIO << 8) | (register_offset + i); + ptr_data[i] = ab8500_read(AB8500_AUDIO, address); + } + + return AB8500_CODEC_OK; +} + +EXPORT_SYMBOL(u8500_acodec_set_src_power_cntrl); +EXPORT_SYMBOL(u8500_acodec_set_burst_mode_fifo); +EXPORT_SYMBOL(u8500_acodec_get_dest_power_state); +EXPORT_SYMBOL(lpbk_state_in_texts); +EXPORT_SYMBOL(u8500_acodec_toggle_playback_mute_control); +EXPORT_SYMBOL(u8500_acodec_set_dest_power_cntrl); +EXPORT_SYMBOL(power_state_in_texts); +EXPORT_SYMBOL(u8500_acodec_toggle_capture_mute_control); +EXPORT_SYMBOL(u8500_acodec_toggle_analog_lpbk); +EXPORT_SYMBOL(u8500_acodec_toggle_digital_lpbk); +EXPORT_SYMBOL(tdm_mode_state_in_texts); +EXPORT_SYMBOL(switch_state_in_texts); +EXPORT_SYMBOL(pcm_rendering_state_in_texts); +EXPORT_SYMBOL(direct_rendering_state_in_texts); +EXPORT_SYMBOL(u8500_acodec_get_src_power_state); +EXPORT_SYMBOL(i2sdrv); +EXPORT_SYMBOL(second_config); -- cgit v1.2.3 From b89deddb8cc442d089236f4c012a29daaec75922 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 11 Oct 2011 09:28:24 +0200 Subject: mach-ux500: add msp board file Signed-off-by: Philippe Langlais --- arch/arm/mach-ux500/board-mop500-msp.c | 225 +++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 arch/arm/mach-ux500/board-mop500-msp.c diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c new file mode 100644 index 00000000000..8867dded7aa --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "board-mop500.h" +#include "devices-db8500.h" +#include "pins-db8500.h" + +/* MSP1/3 Tx/Rx usage protection */ +static DEFINE_SPINLOCK(msp_rxtx_lock); + +/* Reference Count */ +static int msp_rxtx_ref; + +static pin_cfg_t mop500_msp1_pins[] = { + GPIO33_MSP1_TXD | PIN_OUTPUT_LOW, + GPIO34_MSP1_TFS | PIN_INPUT_NOPULL, + GPIO35_MSP1_TCK | PIN_INPUT_NOPULL, + GPIO36_MSP1_RXD | PIN_INPUT_NOPULL, +}; + +int msp13_i2s_init(void) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&msp_rxtx_lock, flags); + if (msp_rxtx_ref == 0) + retval = nmk_config_pins( + ARRAY_AND_SIZE(mop500_msp1_pins)); + if (!retval) + msp_rxtx_ref++; + spin_unlock_irqrestore(&msp_rxtx_lock, flags); + + return retval; +} + +int msp13_i2s_exit(void) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&msp_rxtx_lock, flags); + WARN_ON(!msp_rxtx_ref); + msp_rxtx_ref--; + if (msp_rxtx_ref == 0) + retval = nmk_config_pins_sleep( + ARRAY_AND_SIZE(mop500_msp1_pins)); + spin_unlock_irqrestore(&msp_rxtx_lock, flags); + + return retval; +} + +static struct stedma40_chan_cfg msp0_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp0_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp0_platform_data = { + .id = MSP_0_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp0_dma_rx, + .msp_i2s_dma_tx = &msp0_dma_tx, +}; + +static struct stedma40_chan_cfg msp1_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV30_MSP1_RX, /* v2: MSP3 RX */ + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp1_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp1_platform_data = { + .id = MSP_1_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp1_dma_rx, + .msp_i2s_dma_tx = &msp1_dma_tx, + .msp_i2s_init = msp13_i2s_init, + .msp_i2s_exit = msp13_i2s_exit, +}; + +static struct stedma40_chan_cfg msp2_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV14_MSP2_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp2_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp2_platform_data = { + .id = MSP_2_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp2_dma_rx, + .msp_i2s_dma_tx = &msp2_dma_tx, +}; + +static struct msp_i2s_platform_data msp3_platform_data = { + .id = MSP_3_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp1_dma_rx, + .msp_i2s_dma_tx = NULL, + .msp_i2s_init = msp13_i2s_init, + .msp_i2s_exit = msp13_i2s_exit, +}; + +static struct i2s_board_info stm_i2s_board_info[] __initdata = { + { + .modalias = "i2s_device.0", + .id = 0, + .chip_select = 0, + }, + { + .modalias = "i2s_device.1", + .id = 1, + .chip_select = 1, + }, + { + .modalias = "i2s_device.2", + .id = 2, + .chip_select = 2, + }, + { + .modalias = "i2s_device.3", + .id = 3, + .chip_select = 3, + }, +}; + +static void __init mop500_msp_fixup(void) +{ + if (cpu_is_u8500ed() || cpu_is_u8500v1()) + return; + + /* DMA Rx is moved to MSP3 on DB8500v2 */ + msp1_platform_data.msp_i2s_dma_rx = NULL; + + /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */ + msp2_dma_rx.src_info.psize = STEDMA40_PSIZE_LOG_1; + msp2_dma_rx.dst_info.psize = STEDMA40_PSIZE_LOG_1; +} + +void __init mop500_msp_init(void) +{ + mop500_msp_fixup(); + + db8500_add_msp0_i2s(&msp0_platform_data); + db8500_add_msp1_i2s(&msp1_platform_data); + db8500_add_msp2_i2s(&msp2_platform_data); + + if (cpu_is_u8500v2()) + db8500_add_msp3_i2s(&msp3_platform_data); + + i2s_register_board_info(stm_i2s_board_info, + ARRAY_SIZE(stm_i2s_board_info)); +} -- cgit v1.2.3 From 533a9b55e5250c63fb6e1263b8c9f2f947e599e3 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Tue, 19 Oct 2010 20:22:31 +0200 Subject: sound: add alsa support for ab8500 This patch is based on the following work: Add a power management scheme for AB3550 and fix bugs that hinder simultaneous playback/capture. ST-Ericsson ID: WP 259100 Author: Xie Xiaolei msp: add configuration param for MSP_IODLY ST-Ericsson ID: CR261462 Author: Rabin Vincent ux500: switch to DMAENGINE-based DMA driver ST-Ericsson ID: AP259210 Author: Rabin Vincent ab8500-acodec: remove unused dma variables ST-Ericsson ID: AP259210 Author: Rabin Vincent updates for u8500 sound drivers for v2.6.33 Author: Mian Yousaf Kaukab Signed-off-by: Mian Yousaf Kaukab --- sound/arm/Kconfig | 12 + sound/arm/Makefile | 4 + sound/arm/u8500_alsa_ab8500.c | 2710 +++++++++++++++++++++++++++++++++++++++++ sound/arm/u8500_alsa_ab8500.h | 165 +++ sound/arm/u8500_alsa_hdmi.c | 936 ++++++++++++++ 5 files changed, 3827 insertions(+) create mode 100644 sound/arm/u8500_alsa_ab8500.c create mode 100644 sound/arm/u8500_alsa_ab8500.h create mode 100644 sound/arm/u8500_alsa_hdmi.c diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index 885683a3b0b..86cd48bfd8d 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig @@ -39,5 +39,17 @@ config SND_PXA2XX_AC97 Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. +config SND_U8500_ALSA_AB8500 + tristate "U8500 alsa support for AB8500" + depends on SND && STE_DMA40 && U8500_ACODEC && (U8500_AB8500_ED || U8500_AB8500_CUT10) + default y + select SND_PCM + help + Say Y here if you have a u8500 based device + and want to use alsa for pcm playback and capture. + + To compile this driver as a module, choose M here: the module + will be called u8500mod_alsa. + endif # SND_ARM diff --git a/sound/arm/Makefile b/sound/arm/Makefile index 8c0c851d464..e41f1f4db14 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -14,3 +14,7 @@ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o snd-pxa2xx-ac97-objs := pxa2xx-ac97.o +obj-$(CONFIG_SND_U8500_ALSA_AB8500) += u8500mod_alsa.o +ifneq ($(CONFIG_SND_U8500_ALSA_AB8500),n) +u8500mod_alsa-objs := u8500_alsa_ab8500.o u8500_alsa_hdmi.o +endif diff --git a/sound/arm/u8500_alsa_ab8500.c b/sound/arm/u8500_alsa_ab8500.c new file mode 100644 index 00000000000..c14eed19196 --- /dev/null +++ b/sound/arm/u8500_alsa_ab8500.c @@ -0,0 +1,2710 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Deepak Karda + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.1 as published + * by the Free Software Foundation. + */ + +/* This include must be defined at this point */ +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* alsa system */ +#include +#include +#include +#include +#include +#include "u8500_alsa_ab8500.h" +#include +#include + +#define ALSA_NAME "DRIVER ALSA" + +#define DRIVER_DEBUG CONFIG_STM_ALSA_DEBUG /* enables/disables debug msgs */ +#define DRIVER_DEBUG_PFX ALSA_NAME /* msg header represents this module */ +#define DRIVER_DBG KERN_ERR /* message level */ + +static struct platform_device *device; +static int active_user = 0; + +/* +** Externel references +*/ +#if DRIVER_DEBUG > 0 +t_ab8500_codec_error dump_acodec_registers(void); +t_ab8500_codec_error dump_msp_registers(void); +#endif + +extern int u8500_acodec_rates[MAX_NO_OF_RATES]; +extern char *lpbk_state_in_texts[NUMBER_LOOPBACK_STATE]; +extern char *switch_state_in_texts[NUMBER_SWITCH_STATE]; +extern char *power_state_in_texts[NUMBER_POWER_STATE]; +extern char *tdm_mode_state_in_texts[NUMBER_TDM_MODE_STATE]; +extern char *direct_rendering_state_in_texts[NUMBER_DIRECT_RENDERING_STATE]; +extern char *pcm_rendering_state_in_texts[NUMBER_PCM_RENDERING_STATE]; +extern char *codec_dest_texts[NUMBER_OUTPUT_DEVICE]; +extern char *codec_in_texts[NUMBER_INPUT_DEVICE]; +extern struct driver_debug_st DBG_ST; +extern int second_config; +extern int u8500_register_alsa_hdmi_controls(struct snd_card *card, + u8500_acodec_chip_t * u8500_chip); +extern int snd_card_u8500_alsa_hdmi_new(u8500_acodec_chip_t * chip, int device); +/* +** Declaration for local functions +*/ +static int u8500_analog_lpbk_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_analog_lpbk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_analog_lpbk_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_digital_lpbk_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_digital_lpbk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_digital_lpbk_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_playback_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_playback_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_playback_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_capture_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_capture_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_capture_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_playback_sink_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_playback_sink_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_playback_sink_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_capture_src_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_capture_src_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_capture_src_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_playback_switch_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_playback_switch_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_playback_switch_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_capture_switch_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_capture_switch_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_capture_switch_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_playback_power_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_playback_power_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_playback_power_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_capture_power_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_capture_power_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_capture_power_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_tdm_mode_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_tdm_mode_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_tdm_mode_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +static int u8500_direct_rendering_mode_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info + *uinfo); +static int u8500_direct_rendering_mode_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value + *uinfo); +static int u8500_direct_rendering_mode_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value + *uinfo); +static int u8500_register_alsa_controls(struct snd_card *card, + u8500_acodec_chip_t * u8500_chip); + +static int u8500_pcm_rendering_mode_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_pcm_rendering_mode_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_pcm_rendering_mode_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +#if 0 /* DUMP REGISTER CONTROL */ +static int u8500_dump_register_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_dump_register_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_dump_register_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +#endif /* DUMP REGISTER CONTROL */ + +static int configure_rate(struct snd_pcm_substream *, + t_u8500_acodec_config_need acodec_config_need); +static void dma_eot_handler(void *data); +/** +* configure_rate +* @substream - pointer to the playback/capture substream structure +* +* This functions configures audio codec in to stream frequency frequency +*/ + +static int configure_rate(struct snd_pcm_substream *substream, + t_u8500_acodec_config_need acodec_config_need) +{ + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + t_codec_sample_frequency sampling_frequency = 0; + t_ab8500_codec_direction direction = 0; + struct acodec_configuration acodec_config; + int stream_id = substream->pstr->stream; + + FUNC_ENTER(); + switch (chip->freq) { + case 48000: + sampling_frequency = CODEC_SAMPLING_FREQ_48KHZ; + break; + default: + printk("not supported frequnecy \n"); + stm_error("not supported frequnecy \n"); + return -EINVAL; + } + + switch (stream_id) { + case SNDRV_PCM_STREAM_PLAYBACK: + direction = AB8500_CODEC_DIRECTION_OUT; + break; + case SNDRV_PCM_STREAM_CAPTURE: + direction = AB8500_CODEC_DIRECTION_IN; + break; + default: + stm_error(": wrong pcm stream\n"); + return -EINVAL; + } + + stm_dbg(DBG_ST.alsa, "enabling audiocodec audio mode\n"); + acodec_config.direction = direction; + acodec_config.input_frequency = T_CODEC_SAMPLING_FREQ_48KHZ; + acodec_config.output_frequency = T_CODEC_SAMPLING_FREQ_48KHZ; + acodec_config.mspClockSel = CODEC_MSP_APB_CLOCK; + acodec_config.mspInClockFreq = CODEC_MSP_INPUT_FREQ_48MHZ; + acodec_config.channels = chip->channels; + acodec_config.user = 2; + acodec_config.acodec_config_need = acodec_config_need; + acodec_config.handler = dma_eot_handler; + acodec_config.tx_callback_data = + &chip->stream[ALSA_PCM_DEV][SNDRV_PCM_STREAM_PLAYBACK]; + acodec_config.rx_callback_data = + &chip->stream[ALSA_PCM_DEV][SNDRV_PCM_STREAM_CAPTURE]; + acodec_config.direct_rendering_mode = chip->direct_rendering_mode; + acodec_config.tdm8_ch_mode = chip->tdm8_ch_mode; + acodec_config.digital_loopback = DISABLE; + u8500_acodec_enable_audio_mode(&acodec_config); + FUNC_EXIT(); + + return 0; +} + +/* +**************************************************************************************** +* playback vol control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_playback_vol_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 0, + .name = "PCM Playback Volume", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_playback_vol_info, + .get = u8500_playback_vol_get, + .put = u8500_playback_vol_put +}; + +/** +* u8500_playback_vol_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback volume info into user structure. +*/ + +static int u8500_playback_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 100; + uinfo->value.integer.step = 10; + return 0; +} + +/** +* u8500_playback_vol_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills the current volume setting to user structure. +*/ + +static int u8500_playback_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + + int *p_left_volume = NULL; + int *p_right_volume = NULL; + + p_left_volume = (int *)&uinfo->value.integer.value[0]; + p_right_volume = (int *)&uinfo->value.integer.value[1]; + + u8500_acodec_get_output_volume(chip->output_device, p_left_volume, + p_right_volume, USER_ALSA); + return 0; +} + +/** +* u8500_playback_vol_put +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure. +* +* This functions sets the playback audio codec volume . +*/ + +static int u8500_playback_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0, error = 0; + + if (chip->output_lvolume != uinfo->value.integer.value[0] + || chip->output_rvolume != uinfo->value.integer.value[1]) { + chip->output_lvolume = uinfo->value.integer.value[0]; + chip->output_rvolume = uinfo->value.integer.value[1]; + + if (chip->output_lvolume > 100) + chip->output_lvolume = 100; + else if (chip->output_lvolume < 0) + chip->output_lvolume = 0; + + if (chip->output_rvolume > 100) + chip->output_rvolume = 100; + else if (chip->output_rvolume < 0) + chip->output_rvolume = 0; + + error = + u8500_acodec_set_output_volume(chip->output_device, + chip->output_lvolume, + chip->output_rvolume, + USER_ALSA); + + if (error) { + stm_error + (" : set volume for speaker/headphone failed\n"); + return changed; + } + changed = 1; + } + + return changed; +} + +/* +**************************************************************************************** +* capture vol control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_capture_vol_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 1, + .name = "PCM Capture Volume", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_capture_vol_info, + .get = u8500_capture_vol_get, + .put = u8500_capture_vol_put +}; + +/** +* u8500_capture_vol_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills capture volume info into user structure. +*/ +static int u8500_capture_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 100; + uinfo->value.integer.step = 10; + return 0; +} + +/** +* u8500_capture_vol_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current capture volume setting to user structure. +*/ + +static int u8500_capture_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + + int *p_left_volume = NULL; + int *p_right_volume = NULL; + + p_left_volume = (int *)&uinfo->value.integer.value[0]; + p_right_volume = (int *)&uinfo->value.integer.value[1]; + + u8500_acodec_get_input_volume(chip->input_device, p_left_volume, + p_right_volume, USER_ALSA); + return 0; +} + +/** +* u8500_capture_vol_put +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure. +* +* This functions sets the capture audio codec volume with values provided. +*/ + +static int u8500_capture_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0, error = 0; + + if (chip->input_lvolume != uinfo->value.integer.value[0] + || chip->input_rvolume != uinfo->value.integer.value[1]) { + chip->input_lvolume = uinfo->value.integer.value[0]; + chip->input_rvolume = uinfo->value.integer.value[1]; + + if (chip->input_lvolume > 100) + chip->input_lvolume = 100; + else if (chip->input_lvolume < 0) + chip->input_lvolume = 0; + + if (chip->input_rvolume > 100) + chip->input_rvolume = 100; + else if (chip->input_rvolume < 0) + chip->input_rvolume = 0; + + error = u8500_acodec_set_input_volume(chip->input_device, + chip->input_rvolume, + chip->input_lvolume, + USER_ALSA); + if (error) { + stm_error(" : set input volume failed\n"); + return changed; + } + changed = 1; + } + + return changed; +} + +/* +**************************************************************************************** +* playback sink control * +**************************************************************************************** +*/ + +static struct snd_kcontrol_new u8500_playback_sink_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 0, + .name = "PCM Playback Sink", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xffff, + .info = u8500_playback_sink_info, + .get = u8500_playback_sink_get, + .put = u8500_playback_sink_put +}; + +/** +* u8500_playback_sink_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_playback_sink_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_OUTPUT_DEVICE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_OUTPUT_DEVICE) + uinfo->value.enumerated.item = NUMBER_OUTPUT_DEVICE - 1; + strcpy(uinfo->value.enumerated.name, + codec_dest_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_playback_sink_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_playback_sink_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->output_device; + return 0; +} + +/** +* u8500_playback_sink_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_playback_sink_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0, error; + + if (chip->output_device != uinfo->value.enumerated.item[0]) { + chip->output_device = uinfo->value.enumerated.item[0]; + error = + u8500_acodec_select_output(chip->output_device, + USER_ALSA, chip->tdm8_ch_mode); + if (error) { + stm_error(" : select output failed\n"); + return changed; + } + changed = 1; + } + return changed; +} + +/* +**************************************************************************************** +* capture src control * +**************************************************************************************** +*/ + +static struct snd_kcontrol_new u8500_capture_src_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 1, + .name = "PCM Capture Source", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xffff, + .info = u8500_capture_src_ctrl_info, + .get = u8500_capture_src_ctrl_get, + .put = u8500_capture_src_ctrl_put +}; + +/** +* u8500_capture_src_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills capture device info into user structure. +*/ +static int u8500_capture_src_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_INPUT_DEVICE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_INPUT_DEVICE) + uinfo->value.enumerated.item = NUMBER_INPUT_DEVICE - 1; + strcpy(uinfo->value.enumerated.name, + codec_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_capture_src_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current capture device selected. +*/ +static int u8500_capture_src_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->input_device; + return 0; +} + +/** +* u8500_capture_src_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, +* +* This functions sets the capture device. +*/ +static int u8500_capture_src_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0, error; + + if (chip->input_device != uinfo->value.enumerated.item[0]) { + chip->input_device = uinfo->value.enumerated.item[0]; + error = + u8500_acodec_select_input(chip->input_device, USER_ALSA, + chip->tdm8_ch_mode); + if (error) { + stm_error(" : select input failed\n"); + return changed; + } + changed = 1; + } + return changed; +} + +/* +*************************************************************************************** +* analog lpbk control * +*************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_analog_lpbk_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .name = "Analog Loopback", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_analog_lpbk_info, + .get = u8500_analog_lpbk_get, + .put = u8500_analog_lpbk_put +}; + +/** +* u8500_analog_lpbk_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_analog_lpbk_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_LOOPBACK_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_LOOPBACK_STATE) + uinfo->value.enumerated.item = NUMBER_LOOPBACK_STATE - 1; + strcpy(uinfo->value.enumerated.name, + lpbk_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_analog_lpbk_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_analog_lpbk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->analog_lpbk; + return 0; +} + +/** +* u8500_analog_lpbk_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_analog_lpbk_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + if (chip->analog_lpbk != uinfo->value.enumerated.item[0]) { + chip->analog_lpbk = uinfo->value.enumerated.item[0]; + + error = + u8500_acodec_toggle_analog_lpbk(chip->analog_lpbk, + USER_ALSA); + + if (AB8500_CODEC_OK != error) { + stm_error + (" : select u8500_acodec_set_analog_lpbk_state failed\n"); + return changed; + } + changed = 1; + } + return changed; +} + +/* +**************************************************************************************** +* digital lpbk control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_digital_lpbk_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .name = "Digital Loopback", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_digital_lpbk_info, + .get = u8500_digital_lpbk_get, + .put = u8500_digital_lpbk_put +}; + +/** +* u8500_digital_lpbk_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_digital_lpbk_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_LOOPBACK_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_LOOPBACK_STATE) + uinfo->value.enumerated.item = NUMBER_LOOPBACK_STATE - 1; + strcpy(uinfo->value.enumerated.name, + lpbk_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_digital_lpbk_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_digital_lpbk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->digital_lpbk; + return 0; +} + +/** +* u8500_analog_lpbk_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_digital_lpbk_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + if (chip->digital_lpbk != uinfo->value.enumerated.item[0]) { + chip->digital_lpbk = uinfo->value.enumerated.item[0]; + + error = u8500_acodec_toggle_digital_lpbk(chip->digital_lpbk, + chip->output_device, + chip->input_device, + USER_ALSA, + chip->tdm8_ch_mode); + + /*if((error = u8500_acodec_set_output_volume(chip->output_device,50,50,USER_ALSA))) + { + stm_error(" : set output volume failed\n"); + return error; + } + + if ((error = u8500_acodec_set_input_volume(chip->input_device,50,50,USER_ALSA))) + { + stm_error(" : set input volume failed\n"); + return error; + } */ + + if (AB8500_CODEC_OK != error) { + stm_error + (" : select u8500_acodec_set_digital_lpbk_state failed\n"); + return changed; + } + changed = 1; + } + return changed; +} + +/* +**************************************************************************************** +* playback switch control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_playback_switch_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 0, + .name = "PCM Playback Mute", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_playback_switch_ctrl_info, + .get = u8500_playback_switch_ctrl_get, + .put = u8500_playback_switch_ctrl_put +}; + +/** +* u8500_playback_switch_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_playback_switch_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_SWITCH_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_SWITCH_STATE) + uinfo->value.enumerated.item = NUMBER_SWITCH_STATE - 1; + strcpy(uinfo->value.enumerated.name, + switch_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_playback_switch_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_playback_switch_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->playback_switch; + return 0; +} + +/** +* u8500_playback_switch_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_playback_switch_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + if (chip->playback_switch != uinfo->value.enumerated.item[0]) { + chip->playback_switch = uinfo->value.enumerated.item[0]; + + error = + u8500_acodec_toggle_playback_mute_control(chip-> + output_device, + chip-> + playback_switch, + USER_ALSA); + + if (AB8500_CODEC_OK != error) { + stm_error + (" : select u8500_playback_switch_ctrl_put failed\n"); + return changed; + } + changed = 1; + } + return changed; +} + +/* +**************************************************************************************** +* Capture switch control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_capture_switch_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 1, + .name = "PCM Capture Mute", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_capture_switch_ctrl_info, + .get = u8500_capture_switch_ctrl_get, + .put = u8500_capture_switch_ctrl_put +}; + +/** +* u8500_capture_switch_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_capture_switch_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_SWITCH_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_SWITCH_STATE) + uinfo->value.enumerated.item = NUMBER_SWITCH_STATE - 1; + strcpy(uinfo->value.enumerated.name, + switch_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_capture_switch_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_capture_switch_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->capture_switch; + return 0; +} + +/** +* u8500_capture_switch_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_capture_switch_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + if (chip->capture_switch != uinfo->value.enumerated.item[0]) { + chip->capture_switch = uinfo->value.enumerated.item[0]; + + error = + u8500_acodec_toggle_capture_mute_control(chip->input_device, + chip-> + capture_switch, + USER_ALSA); + + if (AB8500_CODEC_OK != error) { + stm_error + (" : select u8500_capture_switch_ctrl_put failed\n"); + return changed; + } + changed = 1; + } + return changed; +} + +/* +**************************************************************************************** +* playback power control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_playback_power_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 0, + .name = "PCM Playback Power", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_playback_power_ctrl_info, + .get = u8500_playback_power_ctrl_get, + .put = u8500_playback_power_ctrl_put +}; + +/** +* u8500_playback_power_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_playback_power_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_POWER_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_POWER_STATE) + uinfo->value.enumerated.item = NUMBER_POWER_STATE - 1; + strcpy(uinfo->value.enumerated.name, + power_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_playback_power_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_playback_power_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = + u8500_acodec_get_dest_power_state(chip->output_device); + return 0; +} + +/** +* u8500_playback_power_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_playback_power_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + t_u8500_bool_state power_state; + + power_state = u8500_acodec_get_dest_power_state(chip->output_device); + + if (power_state != uinfo->value.enumerated.item[0]) { + power_state = uinfo->value.enumerated.item[0]; + + error = + u8500_acodec_set_dest_power_cntrl(chip->output_device, + power_state); + + if (AB8500_CODEC_OK != error) { + stm_error + (" : select u8500_acodec_set_dest_power_cntrl failed\n"); + return changed; + } + + /* configure the volume settings for the acodec */ + if ((error = + u8500_acodec_set_output_volume(chip->output_device, + chip->output_lvolume, + chip->output_rvolume, + USER_ALSA))) { + stm_error(" : set output volume failed\n"); + return error; + } + changed = 1; + } + return changed; +} + +/* +**************************************************************************************** +* capture power control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_capture_power_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 0, + .name = "PCM Capture Power", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_capture_power_ctrl_info, + .get = u8500_capture_power_ctrl_get, + .put = u8500_capture_power_ctrl_put +}; + +/** +* u8500_capture_power_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_capture_power_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_POWER_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_POWER_STATE) + uinfo->value.enumerated.item = NUMBER_POWER_STATE - 1; + strcpy(uinfo->value.enumerated.name, + power_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_capture_power_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_capture_power_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = + u8500_acodec_get_src_power_state(chip->input_device); + return 0; +} + +/** +* u8500_capture_power_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_capture_power_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + t_u8500_bool_state power_state; + + power_state = u8500_acodec_get_src_power_state(chip->input_device); + + if (power_state != uinfo->value.enumerated.item[0]) { + power_state = uinfo->value.enumerated.item[0]; + + error = + u8500_acodec_set_src_power_cntrl(chip->input_device, + power_state); + + if (AB8500_CODEC_OK != error) { + stm_error + (" : select u8500_acodec_set_src_power_cntrl failed\n"); + return changed; + } + changed = 1; + } + return changed; +} + +/* +**************************************************************************************** +* TDM 8 channel mode control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_tdm_mode_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .subdevice = 0, + .name = "TDM 8 Channel Mode", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_tdm_mode_ctrl_info, + .get = u8500_tdm_mode_ctrl_get, + .put = u8500_tdm_mode_ctrl_put +}; + +/** +* u8500_tdm_mode_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_tdm_mode_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_TDM_MODE_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_TDM_MODE_STATE) + uinfo->value.enumerated.item = NUMBER_TDM_MODE_STATE - 1; + strcpy(uinfo->value.enumerated.name, + tdm_mode_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_tdm_mode_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_tdm_mode_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->tdm8_ch_mode; + return 0; +} + +/** +* u8500_tdm_mode_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_tdm_mode_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + chip->tdm8_ch_mode = uinfo->value.enumerated.item[0]; + + if (ENABLE == chip->tdm8_ch_mode) + printk("\n TDM 8 channel mode enabled\n"); + else + printk("\n TDM 8 channel mode disabled\n"); + + changed = 1; + + return changed; +} + +/* +**************************************************************************************** +* Direct Rendering Mode control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_direct_rendering_mode_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .name = "Direct Rendering Mode", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_direct_rendering_mode_ctrl_info, + .get = u8500_direct_rendering_mode_ctrl_get, + .put = u8500_direct_rendering_mode_ctrl_put +}; + +/** +* u8500_direct_rendering_mode_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_direct_rendering_mode_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info + *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_DIRECT_RENDERING_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_DIRECT_RENDERING_STATE) + uinfo->value.enumerated.item = + NUMBER_DIRECT_RENDERING_STATE - 1; + strcpy(uinfo->value.enumerated.name, + direct_rendering_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_direct_rendering_mode_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_direct_rendering_mode_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value + *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->direct_rendering_mode; + return 0; +} + +/** +* u8500_direct_rendering_mode_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_direct_rendering_mode_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value + *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + chip->direct_rendering_mode = uinfo->value.enumerated.item[0]; + + if (ENABLE == chip->direct_rendering_mode) { + stm_gpio_altfuncenable(GPIO_ALT_MSP_1); + printk("\n stm_gpio_altfuncenable for GPIO_ALT_MSP_1\n"); + printk("\n Direct Rendering mode enabled\n"); + } else { + stm_gpio_altfuncdisable(GPIO_ALT_MSP_1); + printk("\n stm_gpio_altfuncdisable for GPIO_ALT_MSP_1\n"); + printk("\n Direct Rendering mode disabled\n"); + } + + changed = 1; + + return changed; +} + +/* +**************************************************************************************** +* PCM Rendering Mode control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_pcm_rendering_mode_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .name = "PCM Rendering Mode", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_pcm_rendering_mode_ctrl_info, + .get = u8500_pcm_rendering_mode_ctrl_get, + .put = u8500_pcm_rendering_mode_ctrl_put +}; + +/** +* u8500_pcm_rendering_mode_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_pcm_rendering_mode_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_PCM_RENDERING_STATE; + uinfo->count = 3; + if (uinfo->value.enumerated.item >= NUMBER_PCM_RENDERING_STATE) + uinfo->value.enumerated.item = NUMBER_PCM_RENDERING_STATE - 1; + strcpy(uinfo->value.enumerated.name, + pcm_rendering_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_pcm_rendering_mode_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_pcm_rendering_mode_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->burst_fifo_mode; + uinfo->value.enumerated.item[1] = chip->fm_playback_mode; + uinfo->value.enumerated.item[2] = chip->fm_tx_mode; + return 0; +} + +/** +* u8500_pcm_rendering_mode_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_pcm_rendering_mode_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + if (RENDERING_PENDING == uinfo->value.enumerated.item[0]) { + return changed; + } + if (chip->burst_fifo_mode != uinfo->value.enumerated.item[0]) { + chip->burst_fifo_mode = uinfo->value.enumerated.item[0]; + u8500_acodec_set_burst_mode_fifo(chip->burst_fifo_mode); + } + + chip->fm_playback_mode = uinfo->value.enumerated.item[1]; + chip->fm_tx_mode = uinfo->value.enumerated.item[2]; + + changed = 1; + + return changed; +} + +#if 0 /* DUMP REGISTER CONTROL */ +/* +**************************************************************************************** +* dump registers control * +**************************************************************************************** +*/ + +struct snd_kcontrol_new u8500_dump_register_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 0, + .name = "", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_dump_register_ctrl_info, + .get = u8500_dump_register_ctrl_get, + .put = u8500_dump_register_ctrl_put +}; + +/** +* u8500_dump_register_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_dump_register_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_PCM_RENDERING_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_PCM_RENDERING_STATE) + uinfo->value.enumerated.item = NUMBER_PCM_RENDERING_STATE - 1; + strcpy(uinfo->value.enumerated.name, + pcm_rendering_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_dump_register_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_dump_register_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = chip->burst_fifo_mode; + uinfo->value.enumerated.item[1] = chip->fm_playback_mode; + uinfo->value.enumerated.item[2] = chip->fm_tx_mode; + return 0; +} + +/** +* u8500_dump_register_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_dump_register_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + + if (RENDERING_PENDING == uinfo->value.enumerated.item[0]) { + return changed; + } + if (chip->burst_fifo_mode != uinfo->value.enumerated.item[0]) { + chip->burst_fifo_mode = uinfo->value.enumerated.item[0]; + //u8500_acodec_set_burst_mode_fifo(chip->burst_fifo_mode); + } + + chip->fm_playback_mode = uinfo->value.enumerated.item[1]; + chip->fm_tx_mode = uinfo->value.enumerated.item[2]; + + changed = 1; + + return changed; +} + +#endif /* DUMP REGISTER CONTROL */ + +/* Hardware description , this structure (struct snd_pcm_hardware ) + * contains the definitions of the fundamental hardware configuration. + * This configuration will be applied on the runtime structure + */ +static struct snd_pcm_hardware snd_u8500_playback_hw = { + .info = + (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), + .formats = + SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE | + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_U24_BE | + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE | + SNDRV_PCM_FMTBIT_S32_BE | SNDRV_PCM_FMTBIT_U32_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = MIN_RATE_PLAYBACK, + .rate_max = MAX_RATE_PLAYBACK, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = NMDK_BUFFER_SIZE, + .period_bytes_min = 128, + .period_bytes_max = PAGE_SIZE, + .periods_min = NMDK_BUFFER_SIZE / PAGE_SIZE, + .periods_max = NMDK_BUFFER_SIZE / 128 +}; + +static struct snd_pcm_hardware snd_u8500_capture_hw = { + .info = + (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), + .formats = + SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE | + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_U24_BE | + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE | + SNDRV_PCM_FMTBIT_S32_BE | SNDRV_PCM_FMTBIT_U32_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = MIN_RATE_CAPTURE, + .rate_max = MAX_RATE_CAPTURE, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = NMDK_BUFFER_SIZE, + .period_bytes_min = 128, + .period_bytes_max = PAGE_SIZE, + .periods_min = NMDK_BUFFER_SIZE / PAGE_SIZE, + .periods_max = NMDK_BUFFER_SIZE / 128 +}; + +static struct snd_pcm_hw_constraint_list constraints_rate = { + .count = sizeof(u8500_acodec_rates) / sizeof(u8500_acodec_rates[0]), + .list = u8500_acodec_rates, + .mask = 0, +}; + +/** + * snd_u8500_alsa_pcm_close + * @substream - pointer to the playback/capture substream structure + * + * This routine is used by alsa framework to close a pcm stream . + * Here a dma pipe is disabled and freed. + */ +static int snd_u8500_alsa_pcm_close(struct snd_pcm_substream *substream) +{ + int stream_id, error = 0; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + audio_stream_t *ptr_audio_stream = NULL; + + stream_id = substream->pstr->stream; + ptr_audio_stream = &chip->stream[ALSA_PCM_DEV][stream_id]; + + if (ENABLE == chip->direct_rendering_mode) { + ptr_audio_stream->substream = NULL; + return 0; + } else { + stm_close_alsa(chip, ALSA_PCM_DEV, stream_id); + + /* reset the different variables to default */ + + ptr_audio_stream->active = 0; + ptr_audio_stream->period = 0; + ptr_audio_stream->periods = 0; + ptr_audio_stream->old_offset = 0; + ptr_audio_stream->substream = NULL; + if (!(--active_user)) { + /* Disable the MSP1 */ + error = u8500_acodec_unsetuser(USER_ALSA); + u8500_acodec_close(I2S_CLIENT_MSP1, ACODEC_DISABLE_ALL); + } else { + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) + u8500_acodec_close(I2S_CLIENT_MSP1, + ACODEC_DISABLE_TRANSMIT); + else if (stream_id == SNDRV_PCM_STREAM_CAPTURE) + u8500_acodec_close(I2S_CLIENT_MSP1, + ACODEC_DISABLE_RECEIVE); + } + + stm_hw_free(substream); + + return error; + } +} + +void my_write(u32 address, u8 data) +{ + ab8500_write(AB8500_AUDIO, address, data); +} + +void dsp_configure_audio_codec(void) +{ + //4500 config for both record DMIC1&2 and playback HS stereo + //data width is 16 bits + + my_write(0x200, 0x02); // Start-up audio unreset + my_write(0x20B, 0x10); // Start-up audio clk audio enable + my_write(0x383, 0x06); // Start-up audio Vaudio supply + + my_write(0xD00, 0x88); // General power up=0x88 + my_write(0xD01, 0x00); // Software Reset=0x0 + my_write(0xD02, 0xC0); // Digital AD Channels Enable=0xC0 + my_write(0xD03, 0xC0); // Digital DA Channels Enable=0xC0 + my_write(0xD04, 0x00); // Low Power and Conf=0x0 + my_write(0xD05, 0x0F); // Line in Conf=0xF + my_write(0xD06, 0xC0); // Analog Inputs Enable=0xC0 + my_write(0xD07, 0x30); // ADC Enable=0x30 + my_write(0xD08, 0x30); // Analog Output Enable=0x30 + my_write(0xD09, 0x30); // Digital Output Enable=0x30 + my_write(0xD0A, 0x4F); // Mute Enable=0x4F + my_write(0xD0B, 0x7F); // Short Circuit Disable=0x7F + my_write(0xD0C, 0x80); // Power-up for Headset=0x80 + my_write(0xD0D, 0x00); // Envelope Threshold=0x0 + my_write(0xD0E, 0x00); // Envelope Decay Time=0x0 + my_write(0xD0F, 0xF0); // Class-D Configuration=0xF0 + my_write(0xD10, 0x32); // PWM VIBNL Configuration=0x32 + my_write(0xD11, 0x32); // PWM VIBPL Configuration=0x32 + my_write(0xD12, 0x32); // PWM VIBNR Configuration=0x32 + my_write(0xD13, 0x32); // PWM VIBPR Configuration=0x32 + my_write(0xD14, 0x00); // Microphone 1 Gain=0x0 + my_write(0xD15, 0x00); // Microphone 2 Gain=0x0 + my_write(0xD16, 0x00); // Left line-in and HS Analog Gain=0x0 + my_write(0xD17, 0x00); // Right line-in and HS Analog Gain=0x0 + my_write(0xD18, 0x1F); // Line-in to HSL Gain=0x1F + my_write(0xD19, 0x1F); // Line-in to HSR Gain=0x1F + my_write(0xD1A, 0xF0); // AD Channel Filters Configuration=0xF0 + my_write(0xD1B, 0x85); // TDM Configuration 1=0x85 + my_write(0xD1C, 0x94); // TDM Configuration 2=0x94 + my_write(0xD1D, 0x02); // TDM loopback control=0x2 + my_write(0xD1E, 0x00); // TDM format=0x0 + my_write(0xD1F, 0x10); // AD Data allocation in Slot 0 to 1=0x10 + my_write(0xD20, 0xCC); // AD Data allocation in Slot 2 to 3=0xCC + my_write(0xD21, 0xCC); // AD Data allocation in Slots 4 to 5=0xCC + my_write(0xD22, 0xCC); // AD Data allocation in Slots 6 to 7=0xCC + my_write(0xD23, 0xCC); // AD Data allocation in Slots 8 to 9=0xCC + my_write(0xD24, 0xCC); // AD Data allocation in Slots 10 to 11=0xCC + my_write(0xD25, 0xCC); // AD Data allocation in Slots 12 to 13=0xCC + my_write(0xD26, 0xCC); // AD Data allocation in Slots 14 to 15=0xCC + my_write(0xD27, 0xCC); // AD Data allocation in Slots 16 to 17=0xCC + my_write(0xD28, 0xCC); // AD Data allocation in Slots 18 to 19=0xCC + my_write(0xD29, 0xCC); // AD Data allocation in Slots 20 to 21=0xCC + my_write(0xD2A, 0xCC); // AD Data allocation in Slots 22 to 23=0xCC + my_write(0xD2B, 0xCC); // AD Data allocation in Slots 24 to 25=0xCC + my_write(0xD2C, 0xCC); // AD Data allocation in Slots 26 to 27=0xCC + my_write(0xD2D, 0xCC); // AD Data allocation in Slots 28 to 29=0xCC + my_write(0xD2E, 0xCC); // AD Data allocation in Slots 30 to 31=0xCC + my_write(0xD2F, 0x00); // AD slot 0/7 tristate=0x0 + my_write(0xD30, 0x00); // AD slot 8/15 tristate=0x0 + my_write(0xD31, 0x00); // AD slot 16/23 tristate=0x0 + my_write(0xD32, 0x00); // AD slot 24/31 tristate=0x0 + my_write(0xD33, 0x08); // Slots selection for DA path 1=0x8 + my_write(0xD34, 0x09); // Slots selection for DA path 2=0x9 + my_write(0xD35, 0x00); // Slots selection for DA path 3=0x0 + my_write(0xD36, 0x00); // Slots selection for DA path 4=0x0 + my_write(0xD37, 0x00); // Slots selection for DA path 5=0x0 + my_write(0xD38, 0x00); // Slots selection for DA path 6=0x0 + my_write(0xD39, 0x00); // IRQ mask lsb=0x0 + my_write(0xD3A, 0x00); // IRQ status lsb=0x0 + my_write(0xD3B, 0x00); // IRQ mask msb=0x0 + my_write(0xD3C, 0x00); // IRQ status msb=0x0 + my_write(0xD3D, 0x00); // Fade speed=0x0 + my_write(0xD3E, 0x00); // DMIC decimator filter=0x0 + my_write(0xD3F, 0xF0); // muxing lsb=0xF0 + my_write(0xD40, 0x00); // muxing msb=0x0 + my_write(0xD41, 0x1F); // AD1 Digital Gain=0x1F + my_write(0xD42, 0x1F); // AD2 Digital Gain=0x1F + my_write(0xD43, 0x1F); // AD3 Digital Gain=0x1F + my_write(0xD44, 0x1F); // AD4 Digital Gain=0x1F + my_write(0xD45, 0x1F); // AD5 Digital Gain=0x1F + my_write(0xD46, 0x1F); // AD6 Digital Gain=0x1F + my_write(0xD47, 0x00); // DA1 digital Gain=0x00 + my_write(0xD48, 0x00); // DA2 digital Gain=0x00 + my_write(0xD49, 0x3F); // DA3 digital Gain=0x3F + my_write(0xD4A, 0x3F); // DA4 digital Gain=0x3F + my_write(0xD4B, 0x3F); // DA5 digital Gain=0x3F + my_write(0xD4C, 0x3F); // DA6 digital Gain=0x3F + my_write(0xD4D, 0x3F); // AD1 loopback to HFL digital gain=0x3F + my_write(0xD4E, 0x3F); // AD2 loopback to HFR digital gain=0x3F + my_write(0xD4F, 0x08); // HSL and EAR digital gain=0x8 + my_write(0xD50, 0x08); // HSR digital gain=0x8 + my_write(0xD51, 0x1F); // Side tone FIR1 gain=0x1F + my_write(0xD52, 0x1F); // Side tone FIR2 gain=0x1F + my_write(0xD53, 0x00); // ANC filter control=0x0 + my_write(0xD54, 0x00); // ANC Warped Delay Line Shift=0x0 + my_write(0xD55, 0x00); // ANC FIR output Shift=0x0 + my_write(0xD56, 0x00); // ANC IIR output Shift=0x0 + my_write(0xD57, 0x00); // ANC FIR coefficients msb=0x0 + my_write(0xD58, 0x00); // ANC FIR coefficients lsb=0x0 + my_write(0xD59, 0x00); // ANC IIR coefficients msb=0x0 + my_write(0xD5A, 0x00); // ANC IIR coefficients lsb=0x0 + my_write(0xD5B, 0x00); // ANC Warp delay msb=0x0 + my_write(0xD5C, 0x00); // ANC Warp delay lsb=0x0 + my_write(0xD5D, 0x00); // ANC FIR peak register MSB=0x0 + my_write(0xD5E, 0x00); // ANC FIR peak register LSB=0x0 + my_write(0xD5F, 0x00); // ANC IIR peak register. MSB part=0x0 + my_write(0xD60, 0x00); // ANC IIR peak register. LSB part=0x0 + my_write(0xD61, 0x00); // Side tone FIR address=0x0 + my_write(0xD62, 0x00); // Side tone FIR coefficient MSB=0x0 + my_write(0xD63, 0x00); // Side tone FIR coefficient LSB=0x0 + my_write(0xD64, 0x00); // Filters control=0x0 + my_write(0xD65, 0x00); // Class D EMI Control=0x0 + my_write(0xD66, 0x00); // Class D control path=0x0 + my_write(0xD67, 0x00); // Class D control gain=0x0 + my_write(0xD68, 0x00); // Burst FIFO int control=0x0 + my_write(0xD69, 0x00); // Burst FIFO length=0x0 + my_write(0xD6A, 0x00); // Burst FIFO control=0x0 + my_write(0xD6B, 0x00); // Burst FIFO switch frame=0x0 + my_write(0xD6C, 0x00); // Burst FIFO wake up delay=0x0 + my_write(0xD6D, 0x00); // Burst FIFO samples number=0x0 + my_write(0xD70, 0x00); // CR112=0x0 + my_write(0xD71, 0x04); // CR113=0x4 + my_write(0xD72, 0x00); // CR114=0x0 + my_write(0xD73, 0x00); // CR115=0x0 + my_write(0xD74, 0x00); // CR116=0x0 + my_write(0xD75, 0x00); // CR117=0x0 + my_write(0xD76, 0x00); // CR118=0x0 + my_write(0xD77, 0x00); // CR119=0x0 + my_write(0xD78, 0x00); // CR120=0x0 + my_write(0xD79, 0x00); // CR121=0x0 + my_write(0xD7A, 0x00); // CR122=0x0 + my_write(0xD7B, 0x00); // CR123=0x0 +} + +static int configure_direct_rendering(struct snd_pcm_substream *substream) +{ + int error = 0, stream_id; + int status = 0; + struct snd_pcm_runtime *runtime = substream->runtime; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + audio_stream_t *ptr_audio_stream = NULL; + + stream_id = substream->pstr->stream; + + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { + runtime->hw = snd_u8500_playback_hw; + } else { + runtime->hw = snd_u8500_capture_hw; + } + + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x04))); //MSP_GCR + + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x08))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x0C))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x10))); //MSP + + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x30))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x34))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x38))); //MSP + + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x40))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x44))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x48))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x4C))); //MSP + + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x60))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x64))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x68))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x6C))); //MSP + + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x18))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x20))); //MSP + writel(0x0, ((char *)(IO_ADDRESS(U8500_MSP1_BASE) + 0x2C))); //MSP + + status = stm_gpio_altfuncenable(GPIO_ALT_MSP_1); + if (status) { + printk("Error in stm_gpio_altfuncenable, status is %d\n", + status); + } + + printk("\n stm_gpio_altfuncenable for GPIO_ALT_MSP_1\n"); + + dsp_configure_audio_codec(); + +#if DRIVER_DEBUG > 0 + { + dump_msp_registers(); + dump_acodec_registers(); + } +#endif + + ptr_audio_stream = &chip->stream[ALSA_PCM_DEV][stream_id]; + + ptr_audio_stream->substream = substream; + + FUNC_EXIT(); + return 0; +} + +/** + * snd_u8500_alsa_pcm_open + * @substream - pointer to the playback/capture substream structure + * + * This routine is used by alsa framework to open a pcm stream . + * Here a dma pipe is requested and device is configured(default). + */ +static int snd_u8500_alsa_pcm_open(struct snd_pcm_substream *substream) +{ + int error = 0, stream_id, status = 0; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + audio_stream_t *ptr_audio_stream = NULL; + + FUNC_ENTER(); + + if (ENABLE == chip->direct_rendering_mode) { + configure_direct_rendering(substream); + return 0; + } else { + stream_id = substream->pstr->stream; + status = u8500_acodec_open(I2S_CLIENT_MSP1, stream_id); + + if (status) { + printk("failed in getting open\n"); + return -1; + } + + if (!active_user) + error = u8500_acodec_setuser(USER_ALSA); + if (error) + return error; + else + active_user++; + + error = + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rate); + if (error < 0) { + stm_error + (": error initializing hw sample rate constraint\n"); + return error; + } + + /* configure the default sampling rate for the acodec */ + second_config = 0; + + if ((error = configure_rate(substream, ACODEC_CONFIG_REQUIRED))) + return error; + + /* Set the hardware configuration */ + stream_id = substream->pstr->stream; + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { + runtime->hw = snd_u8500_playback_hw; + /* configure the output sink for the acodec */ + if ((error = + u8500_acodec_select_output(chip->output_device, + USER_ALSA, + chip->tdm8_ch_mode))) { + stm_error(" : select output failed\n"); + return error; + } + + /* configure the volume settings for the acodec */ + if ((error = + u8500_acodec_set_output_volume(chip->output_device, + chip-> + output_lvolume, + chip-> + output_rvolume, + USER_ALSA))) { + stm_error(" : set output volume failed\n"); + return error; + } + } else { + runtime->hw = snd_u8500_capture_hw; + /* configure the input source for the acodec */ + if ((error = + u8500_acodec_select_input(chip->input_device, + USER_ALSA, + chip->tdm8_ch_mode))) { + stm_error(" : select input failed\n"); + return error; + } + /*u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_1,ENABLE); + u8500_acodec_set_src_power_cntrl(AB8500_CODEC_SRC_D_MICROPHONE_2,ENABLE); + + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_1, + chip->input_lvolume, + chip->input_rvolume, + USER_ALSA); + + u8500_acodec_set_input_volume(AB8500_CODEC_SRC_D_MICROPHONE_2, + chip->input_lvolume, + chip->input_rvolume, + USER_ALSA); + */ + + if ((error = + u8500_acodec_set_input_volume(chip->input_device, + chip->input_lvolume, + chip->input_rvolume, + USER_ALSA))) { + stm_error(" : set input volume failed\n"); + return error; + } + } + + u8500_acodec_set_burst_mode_fifo(chip->burst_fifo_mode); + +#if DRIVER_DEBUG > 0 + { + dump_msp_registers(); + dump_acodec_registers(); + } +#endif + + ptr_audio_stream = &chip->stream[ALSA_PCM_DEV][stream_id]; + + ptr_audio_stream->substream = substream; + + if (DISABLE == chip->direct_rendering_mode) { + stm_config_hw(chip, substream, ALSA_PCM_DEV, stream_id); + } + init_MUTEX(&(ptr_audio_stream->alsa_sem)); + init_completion(&(ptr_audio_stream->alsa_com)); + ptr_audio_stream->state = ALSA_STATE_UNPAUSE; + + FUNC_EXIT(); + return 0; + } +} + +/** + * snd_u8500_alsa_pcm_hw_params + * @substream - pointer to the playback/capture substream structure + * @hw_params - specifies the hw parameters like format/no of channels etc + * + * This routine is used by alsa framework to allocate a dma buffer + * used to transfer the data from user space to kernel space + * + */ +static int snd_u8500_alsa_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +} + +/** + * snd_u8500_alsa_pcm_hw_free + * @substream - pointer to the playback/capture substream structure + * + * This routine is used by alsa framework to deallocate a dma buffer + * allocated berfore by snd_u8500_alsa_pcm_hw_params + */ +static int snd_u8500_alsa_pcm_hw_free(struct snd_pcm_substream *substream) +{ + stm_hw_free(substream); + return 0; +} + +/** + * snd_u8500_alsa_pcm_prepare + * @substream - pointer to the playback/capture substream structure + * + * This callback is called whene the pcm is "prepared" Here is possible + * to set the format type ,sample rate ,etc.The callback is called as + * well everytime a recovery after an underrun happens. + */ + +static int snd_u8500_alsa_pcm_prepare(struct snd_pcm_substream *substream) +{ + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int error, stream_id; + + FUNC_ENTER(); + + if (chip->freq != runtime->rate || chip->channels != runtime->channels) { + stm_dbg(DBG_ST.alsa, " freq not same, %d %d\n", chip->freq, + runtime->rate); + stm_dbg(DBG_ST.alsa, " channels not same, %d %d\n", + chip->channels, runtime->channels); + if (chip->channels != runtime->channels) { + chip->channels = runtime->channels; + if ((error = + stm_config_hw(chip, substream, ALSA_PCM_DEV, + -1))) { + stm_dbg(DBG_ST.alsa, + "In func %s, stm_config_hw fails", + __FUNCTION__); + return error; + } + } + chip->freq = runtime->rate; + second_config = 1; + stream_id = substream->pstr->stream; + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) + u8500_acodec_close(I2S_CLIENT_MSP1, + ACODEC_DISABLE_TRANSMIT); + else if (stream_id == SNDRV_PCM_STREAM_CAPTURE) + u8500_acodec_close(I2S_CLIENT_MSP1, + ACODEC_DISABLE_RECEIVE); + + error = u8500_acodec_open(I2S_CLIENT_MSP1, stream_id); + if (error) { + printk("failed in getting open\n"); + return -1; + } + if ((error = + configure_rate(substream, ACODEC_CONFIG_NOT_REQUIRED))) { + stm_dbg(DBG_ST.alsa, "In func %s, configure_rate fails", + __FUNCTION__); + return error; + } + } + + FUNC_EXIT(); + return 0; +} + +/** + * snd_u8500_alsa_pcm_trigger + * @substream - pointer to the playback/capture substream structure + * @cmd - specifies the command : start/stop/pause/resume + * + * This callback is called whene the pcm is started ,stopped or paused + * The action is specified in the second argument, SND_PCM_TRIGGER_XXX in + * . + * This callback is atomic and the interrupts are disabled , so you can't + * call other functions that need interrupts without possible risks + */ +static int snd_u8500_alsa_pcm_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + int stream_id = substream->pstr->stream; + audio_stream_t *stream = NULL; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + int error = 0; + + FUNC_ENTER(); + + stream = &chip->stream[ALSA_PCM_DEV][stream_id]; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* Start the pcm engine */ + stm_dbg(DBG_ST.alsa, " TRIGGER START\n"); + if (stream->active == 0) { + stream->active = 1; + stm_trigger_alsa(stream); + break; + } + stm_error(": H/w is busy\n"); + return -EINVAL; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + stm_dbg(DBG_ST.alsa, " SNDRV_PCM_TRIGGER_PAUSE_PUSH\n"); + if (stream->active == 1) { + stm_pause_alsa(stream); + } + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + stm_dbg(DBG_ST.alsa, " SNDRV_PCM_TRIGGER_PAUSE_RELEASE\n"); + if (stream->active == 1) + stm_unpause_alsa(stream); + break; + case SNDRV_PCM_TRIGGER_STOP: + /* Stop the pcm engine */ + stm_dbg(DBG_ST.alsa, " TRIGGER STOP\n"); + if (stream->active == 1) + stm_stop_alsa(stream); + break; + default: + stm_error(": invalid command in pcm trigger\n"); + return -EINVAL; + } + + FUNC_EXIT(); + return error; +} + +/** + * snd_u8500_alsa_pcm_pointer + * @substream - pointer to the playback/capture substream structure + * + * This callback is called whene the pcm middle layer inquires the current + * hardware position on the buffer .The position is returned in frames + * ranged from 0 to buffer_size -1 + */ +static snd_pcm_uframes_t snd_u8500_alsa_pcm_pointer(struct snd_pcm_substream + *substream) +{ + unsigned int offset; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + audio_stream_t *stream = + &chip->stream[ALSA_PCM_DEV][substream->pstr->stream]; + struct snd_pcm_runtime *runtime = stream->substream->runtime; + + offset = bytes_to_frames(runtime, stream->old_offset); + if (offset < 0 || stream->old_offset < 0) + stm_dbg(DBG_ST.alsa, " Offset=%i %i\n", offset, + stream->old_offset); + + return offset; +} + +static struct snd_pcm_ops snd_u8500_alsa_playback_ops = { + .open = snd_u8500_alsa_pcm_open, + .close = snd_u8500_alsa_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_u8500_alsa_pcm_hw_params, + .hw_free = snd_u8500_alsa_pcm_hw_free, + .prepare = snd_u8500_alsa_pcm_prepare, + .trigger = snd_u8500_alsa_pcm_trigger, + .pointer = snd_u8500_alsa_pcm_pointer, +}; + +static struct snd_pcm_ops snd_u8500_alsa_capture_ops = { + .open = snd_u8500_alsa_pcm_open, + .close = snd_u8500_alsa_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_u8500_alsa_pcm_hw_params, + .hw_free = snd_u8500_alsa_pcm_hw_free, + .prepare = snd_u8500_alsa_pcm_prepare, + .trigger = snd_u8500_alsa_pcm_trigger, + .pointer = snd_u8500_alsa_pcm_pointer, +}; + +#ifdef CONFIG_U8500_ACODEC_POLL + +/** +* u8500_alsa_pio_start +* @stream - pointer to the playback/capture audio_stream_t structure +* +* This function sends/receive one chunck of stream data to/from MSP +*/ +static void u8500_alsa_pio_start(audio_stream_t * stream) +{ + unsigned int offset, dma_size, stream_id; + int ret_val; + struct snd_pcm_substream *substream = stream->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + stream_id = substream->pstr->stream; + + FUNC_ENTER(); + dma_size = frames_to_bytes(runtime, runtime->period_size); + offset = dma_size * stream->period; + stream->old_offset = offset; + + stm_dbg(DBG_ST.alsa, " Transfer started\n"); + stm_dbg(DBG_ST.alsa, " address = %x size=%d\n", + (runtime->dma_addr + offset), dma_size); + + /* Send our stuff */ + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_send_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_send_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + else +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_receive_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_receive_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + + stream->period++; + stream->period %= runtime->periods; + stream->periods++; + + FUNC_EXIT(); + +} + +/** +* acodec_feeding_thread +* @data - void pointer to the playback/capture audio_stream_t structure +* +* This thread sends/receive data to MSP while stream is active +*/ +static int acodec_feeding_thread(void *data) +{ + audio_stream_t *stream = (audio_stream_t *) data; + + FUNC_ENTER(); + daemonize("acodec_feeding_thread"); + allow_signal(SIGKILL); + down(&stream->alsa_sem); + + while ((!signal_pending(current)) && (stream->active)) { + if (stream->state == ALSA_STATE_PAUSE) + wait_for_completion(&(stream->alsa_com)); + + u8500_alsa_pio_start(stream); + if (stream->substream) + snd_pcm_period_elapsed(stream->substream); + } + + up(&stream->alsa_sem); + + FUNC_EXIT(); + return 0; +} + +/** +* acodec_feeding_thread +* @stream - pointer to the playback/capture audio_stream_t structure +* +* This function creates a kernel thread . +*/ + +int spawn_acodec_feeding_thread(audio_stream_t * stream) +{ + pid_t pid; + + FUNC_ENTER(); + + pid = + kernel_thread(acodec_feeding_thread, stream, + CLONE_FS | CLONE_SIGHAND); + + FUNC_EXIT(); + return 0; +} +#endif + +/** + * dma_eot_handler + * @data - pointer to structure set in the dma callback handler + * + * This is the PCM tasklet handler linked to a pipe, its role is to tell + * the PCM middler layer whene the buffer position goes across the prescribed + * period size.To inform of this the snd_pcm_period_elapsed is called. + * + * this callback will be called in case of DMA_EVENT_TC only + */ +static void dma_eot_handler(void *data) +{ + audio_stream_t *stream = data; + + /* snd_pcm_period_elapsed() is _not_ to be protected + */ + stm_dbg(DBG_ST.alsa, + "One transfer complete.. going to start the next one\n"); + + if (stream->substream) + snd_pcm_period_elapsed(stream->substream); + if (stream->state == ALSA_STATE_PAUSE) + return; + if (stream->active == 1) { + u8500_alsa_dma_start(stream); + } +} + +/** + * u8500_alsa_dma_start - used to transmit or recive a dma chunk + * @stream - specifies the playback/record stream structure + */ +void u8500_alsa_dma_start(audio_stream_t * stream) +{ + unsigned int offset, dma_size, stream_id; + + struct snd_pcm_substream *substream = stream->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + u8500_acodec_chip_t *u8500_chip = NULL; + stream_id = substream->pstr->stream; + u8500_chip = snd_pcm_substream_chip(substream); + + dma_size = frames_to_bytes(runtime, runtime->period_size); + offset = dma_size * stream->period; + stream->old_offset = offset; + + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_send_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_send_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + else +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_receive_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_receive_data(I2S_CLIENT_MSP1, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + + stm_dbg(DBG_ST.alsa, " DMA Transfer started\n"); + stm_dbg(DBG_ST.alsa, " address = %x size=%d\n", + (runtime->dma_addr + offset), dma_size); + + stream->period++; + stream->period %= runtime->periods; + stream->periods++; +} + +/** +* u8500_audio_init +* @chip - pointer to u8500_acodec_chip_t structure. +* +* This function intialises the u8500 chip structure with default values +*/ +static void u8500_audio_init(u8500_acodec_chip_t * chip) +{ + audio_stream_t *ptr_audio_stream = NULL; + + ptr_audio_stream = + &chip->stream[ALSA_PCM_DEV][SNDRV_PCM_STREAM_PLAYBACK]; + /* Setup DMA stuff */ + strlcpy(ptr_audio_stream->id, "u8500 playback", + sizeof(ptr_audio_stream->id)); + ptr_audio_stream->stream_id = SNDRV_PCM_STREAM_PLAYBACK; + + /* default initialization for playback */ + ptr_audio_stream->active = 0; + ptr_audio_stream->period = 0; + ptr_audio_stream->periods = 0; + ptr_audio_stream->old_offset = 0; + + ptr_audio_stream = + &chip->stream[ALSA_PCM_DEV][SNDRV_PCM_STREAM_CAPTURE]; + strlcpy(ptr_audio_stream->id, "u8500 capture", + sizeof(ptr_audio_stream->id)); + ptr_audio_stream->stream_id = SNDRV_PCM_STREAM_CAPTURE; + + /* default initialization for capture */ + ptr_audio_stream->active = 0; + ptr_audio_stream->period = 0; + ptr_audio_stream->periods = 0; + ptr_audio_stream->old_offset = 0; + + chip->freq = DEFAULT_SAMPLE_RATE; + chip->channels = 1; + chip->input_lvolume = DEFAULT_GAIN; + chip->input_rvolume = DEFAULT_GAIN; + chip->output_lvolume = DEFAULT_VOLUME; + chip->output_rvolume = DEFAULT_VOLUME; + chip->output_device = DEFAULT_OUTPUT_DEVICE; + chip->input_device = DEFAULT_INPUT_DEVICE; + chip->analog_lpbk = DEFAULT_LOOPBACK_STATE; + chip->digital_lpbk = DEFAULT_LOOPBACK_STATE; + chip->playback_switch = DEFAULT_SWITCH_STATE; + chip->capture_switch = DEFAULT_SWITCH_STATE; + chip->tdm8_ch_mode = DEFAULT_TDM8_CH_MODE_STATE; + chip->direct_rendering_mode = DEFAULT_DIRECT_RENDERING_STATE; + chip->burst_fifo_mode = DEFAULT_BURST_FIFO_STATE; + chip->fm_playback_mode = DEFAULT_FM_PLAYBACK_STATE; + chip->fm_tx_mode = DEFAULT_FM_TX_STATE; + + //HDMI Default params set + chip->hdmi_params.sampling_freq = 48000; + chip->hdmi_params.channel_count = 2; +} + +/** + * snd_card_u8500_alsa_pcm_new - constructor for a new pcm cmponent + * @chip - pointer to chip specific data + * @device - specifies the card number + */ +static int snd_card_u8500_alsa_pcm_new(u8500_acodec_chip_t * chip, int device) +{ + struct snd_pcm *pcm; + int err; + + if ((err = snd_pcm_new(chip->card, "u8500", device, 1, 1, &pcm)) < 0) { + stm_error(": error in snd_pcm_new\n"); + return err; + } + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_u8500_alsa_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_u8500_alsa_capture_ops); + + pcm->private_data = chip; + pcm->info_flags = 0; + chip->pcm = pcm; + strcpy(pcm->name, "u8500_alsa"); + + u8500_audio_init(pcm->private_data); + return 0; +} + +static int u8500_register_alsa_controls(struct snd_card *card, + u8500_acodec_chip_t * u8500_chip) +{ + int error; + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_playback_vol_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_playback_vol_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_capture_vol_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_capture_vol_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_playback_sink_ctrl, + u8500_chip))) < 0) { + stm_error(": error initializing playback ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_capture_src_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_playback_sink_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_analog_lpbk_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_analog_lpbk_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_digital_lpbk_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_digital_lpbk_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_playback_switch_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_playback_switch_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_capture_switch_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_capture_switch_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_playback_power_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_playback_power_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_capture_power_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_capture_power_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_tdm_mode_ctrl, u8500_chip))) < 0) { + stm_error + (": error initializing u8500_tdm_mode_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_direct_rendering_mode_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_direct_rendering_mode_ctrl interface \n\n"); + return (-1); + } + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_pcm_rendering_mode_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_pcm_rendering_mode_ctrl interface \n\n"); + return (-1); + } + + return 0; +} + +static int __init u8500_alsa_probe(struct platform_device *devptr) +{ + //static int card_count=0; + int error; + struct snd_card *card, *hdmi_card; + u8500_acodec_chip_t *u8500_chip; + + /*Set currently active users to 0 */ + active_user = 0; + + error = snd_card_create(0, NULL, THIS_MODULE, sizeof(u8500_acodec_chip_t), &card); + if (error < 0) { + stm_error(": error in snd_card_create\n"); + return error; + } + + u8500_chip = (u8500_acodec_chip_t *) card->private_data; + u8500_chip->card = card; + + if ((error = snd_card_u8500_alsa_pcm_new(u8500_chip, 0)) < 0) { + stm_error(": pcm interface can't be initialized\n\n"); + goto nodev; + } + + if ((error = snd_card_u8500_alsa_hdmi_new(u8500_chip, 1)) < 0) { + stm_error(": alsa HDMI interface can't be initialized\n\n"); + goto nodev; + } + + if (u8500_register_alsa_controls(card, u8500_chip) < 0) { + goto nodev; + } + + if (u8500_register_alsa_hdmi_controls(card, u8500_chip) < 0) { + goto nodev; + } +#if 0 + ///////////////////////////////$ H D M I $////////////////////////////////////// + + if (card_count == 1) { + hdmi_card = + snd_card_new(1, NULL, THIS_MODULE, + sizeof(u8500_acodec_chip_t)); + if (hdmi_card == NULL) { + stm_error(": error in hdmi - snd_card_new\n"); + return -ENOMEM; + } + + u8500_chip = (u8500_acodec_chip_t *) hdmi_card->private_data; + u8500_chip->card = hdmi_card; + + if ((error = snd_card_u8500_alsa_hdmi_new(u8500_chip, 0)) < 0) { + stm_error + (": alsa HDMI interface can't be initialized\n\n"); + goto nodev; + } + + if (u8500_register_alsa_hdmi_controls(card, u8500_chip) < 0) { + goto nodev; + } + } +#endif //////////////////////////////////////////////////////// + + /*char driver[16]; driver name + char shortname[32]; short name of this soundcard + char longname[80]; name of this soundcard + char mixername[80]; mixer name + char components[80]; card components delimited withspace */ + + strcpy(card->driver, "u8500 alsa"); + strcpy(card->shortname, "u8500 alsa pcm hdmi driver"); + strcpy(card->longname, "u8500 alsa pcm hdmi driver"); + + snd_card_set_dev(card, &devptr->dev); + + if ((error = snd_card_register(card)) == 0) { + stm_info("u8500 audio support running..\n"); + platform_set_drvdata(devptr, card); + return 0; + } + + nodev: + snd_card_free(card); + return error; +} + +static int __devexit u8500_alsa_remove(struct platform_device *devptr) +{ + snd_card_free(platform_get_drvdata(devptr)); + platform_set_drvdata(devptr, NULL); + stm_info("u8500 audio support stopped\n"); + + /*Set currently active users to 0 */ + active_user = 0; + + return 0; +} + +static struct platform_driver u8500_alsa_driver = { + .probe = u8500_alsa_probe, + .remove = __devexit_p(u8500_alsa_remove), + .driver = { + .name = U8500_ALSA_DRIVER, + }, +}; + +/** +* u8500_alsa_init - Entry function of AB8500 alsa driver +* +* This function registers u8500 alsa driver with linux framework +*/ +static int __init u8500_alsa_init(void) +{ + int err; + + if ((err = platform_driver_register(&u8500_alsa_driver)) < 0) + return err; + device = + platform_device_register_simple(U8500_ALSA_DRIVER, -1, NULL, 0); + if (IS_ERR(device)) { + platform_driver_unregister(&u8500_alsa_driver); + return PTR_ERR(device); + } + //DBG_ST.acodec = 1; + //DBG_ST.alsa = 1; + + return 0; +} + +static void __exit u8500_alsa_exit(void) +{ + platform_device_unregister(device); + platform_driver_unregister(&u8500_alsa_driver); +} + +module_init(u8500_alsa_init); +module_exit(u8500_alsa_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AB8500 ALSA driver"); diff --git a/sound/arm/u8500_alsa_ab8500.h b/sound/arm/u8500_alsa_ab8500.h new file mode 100644 index 00000000000..dda802c2156 --- /dev/null +++ b/sound/arm/u8500_alsa_ab8500.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Deepak Karda + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _U8500_ALSA_H_ +#define _U8500_ALSA_H_ + +#ifdef CONFIG_U8500_AB8500_CUT10 +#include +//#include +#else +//#include +#include +#endif +#include + +#define DEFAULT_SAMPLE_RATE 48000 +#define NMDK_BUFFER_SIZE (64*1024) +#define U8500_ALSA_DRIVER "u8500_alsa" + +#define MAX_NUMBER_OF_DEVICES 3 /* ALSA_PCM, ALSA_BT, ALSA_HDMI */ +#define MAX_NUMBER_OF_STREAMS 2 /* PLAYBACK, CAPTURE */ + +#define ALSA_PCM_DEV 0 +#define ALSA_BT_DEV 2 +#define ALSA_HDMI_DEV 1 + +/* Debugging stuff */ +#ifndef CONFIG_DEBUG_USER +#define DEBUG_LEVEL 0 +#else +#define DEBUG_LEVEL 10 +#endif + +#if DEBUG_LEVEL > 0 +static int u8500_acodec_debug = DEBUG_LEVEL; +#define DEBUG(n, args...) do { if (u8500_acodec_debug>(n)) printk(args); } while (0) +#else +#define DEBUG(n, args...) do { } while (0) +#endif +enum alsa_state { + ALSA_STATE_PAUSE, + ALSA_STATE_UNPAUSE +}; + +/* audio stream definition */ +typedef struct audio_stream_s { + char id[64]; /* module identifier string */ + int stream_id; /* stream identifier */ + int status; + int active; /* we are using this stream for transfer now */ + int period; /* current transfer period */ + int periods; /* current count of periods registerd in the DMA engine */ + enum alsa_state state; + unsigned int old_offset; + struct snd_pcm_substream *substream; + unsigned int exchId; + snd_pcm_uframes_t played_frame; + struct semaphore alsa_sem; + struct completion alsa_com; + +} audio_stream_t; + +typedef struct hdmi_params_s { + int sampling_freq; + int channel_count; +} hdmi_params_t; + +/* chip structure definition */ +typedef struct u8500_acodec_s { + struct snd_card *card; + struct snd_pcm *pcm; + struct snd_pcm *pcm_hdmi; + struct snd_pcm *pcm_bt; + unsigned int freq; + unsigned int channels; + unsigned int input_lvolume; + unsigned int input_rvolume; + unsigned int output_lvolume; + unsigned int output_rvolume; + t_ab8500_codec_src input_device; + t_ab8500_codec_dest output_device; + t_u8500_bool_state analog_lpbk; + t_u8500_bool_state digital_lpbk; + t_u8500_bool_state playback_switch; + t_u8500_bool_state capture_switch; + t_u8500_bool_state tdm8_ch_mode; + t_u8500_bool_state direct_rendering_mode; + t_u8500_pmc_rendering_state burst_fifo_mode; + t_u8500_pmc_rendering_state fm_playback_mode; + t_u8500_pmc_rendering_state fm_tx_mode; + audio_stream_t stream[MAX_NUMBER_OF_DEVICES][MAX_NUMBER_OF_STREAMS]; + hdmi_params_t hdmi_params; +} u8500_acodec_chip_t; + +void u8500_alsa_dma_start(audio_stream_t * stream); + +#if (defined(CONFIG_U8500_ACODEC_DMA) || defined(CONFIG_U8500_ACODEC_INTR)) + +#define stm_trigger_alsa(x) u8500_alsa_dma_start(x) +static void inline stm_pause_alsa(audio_stream_t * stream) +{ + if (stream->state == ALSA_STATE_UNPAUSE) { + stream->state = ALSA_STATE_PAUSE; + } + +} +static void inline stm_unpause_alsa(audio_stream_t * stream) +{ + if (stream->state == ALSA_STATE_PAUSE) { + stream->state = ALSA_STATE_UNPAUSE; + stm_trigger_alsa(stream); + } +} +static void inline stm_stop_alsa(audio_stream_t * stream) +{ + stream->active = 0; + stream->period = 0; + +} +static void inline stm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); +} + +#define stm_close_alsa(x, y,z) +#define stm_config_hw(w,x, y, z) 0 + +#else ////// CONFIG_U8500_ACODEC_POLL //////////// + +int spawn_acodec_feeding_thread(audio_stream_t * stream); +//static int configure_dmadev_acodec(struct snd_pcm_substream *substream); + +#define stm_trigger_alsa(x) spawn_acodec_feeding_thread(x) +#define stm_close_alsa(x, y,z) +#define stm_config_hw(w,x, y, z) 0 +#define stm_hw_free(x) +static void inline stm_pause_alsa(audio_stream_t * stream) +{ + stream->state = ALSA_STATE_PAUSE; +} +static void inline stm_unpause_alsa(audio_stream_t * stream) +{ + stream->state = ALSA_STATE_UNPAUSE; + complete(&stream->alsa_com); +} +static void inline stm_stop_alsa(audio_stream_t * stream) +{ + stream->active = 0; + stream->period = 0; + if (stream->state == ALSA_STATE_PAUSE) + complete(&stream->alsa_com); +} + +#endif +#endif /*END OF HEADER FILE */ diff --git a/sound/arm/u8500_alsa_hdmi.c b/sound/arm/u8500_alsa_hdmi.c new file mode 100644 index 00000000000..dfadc1ee624 --- /dev/null +++ b/sound/arm/u8500_alsa_hdmi.c @@ -0,0 +1,936 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), + * version 2. + */ + +/* This include must be defined at this point */ +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* alsa system */ +#include +#include +#include +#include +#include +#include "u8500_alsa_ab8500.h" +#include +#include + +#define ALSA_NAME "DRIVER ALSA HDMI" + +/* enables/disables debug msgs */ +#define DRIVER_DEBUG CONFIG_STM_ALSA_DEBUG +/* msg header represents this module */ +#define DRIVER_DEBUG_PFX ALSA_NAME +/* message level */ +#define DRIVER_DBG KERN_ERR +#define ELEMENT_SIZE 0 + +extern char *power_state_in_texts[NUMBER_POWER_STATE]; + +static int u8500_hdmi_power_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int u8500_hdmi_power_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); +static int u8500_hdmi_power_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo); + +void dump_msp2_registers(); + +#ifdef CONFIG_U8500_ACODEC_DMA + +static void u8500_alsa_hdmi_dma_start(audio_stream_t * stream); +#define stm_trigger_hdmi(x) u8500_alsa_hdmi_dma_start(x) +static void inline stm_pause_hdmi(audio_stream_t * stream) +{ + if (stream->state == ALSA_STATE_UNPAUSE) { + stream->state = ALSA_STATE_PAUSE; + } +} +static void inline stm_unpause_hdmi(audio_stream_t * stream) +{ + if (stream->state == ALSA_STATE_PAUSE) { + stream->state = ALSA_STATE_UNPAUSE; + stm_trigger_hdmi(stream); + } +} +static void inline stm_stop_hdmi(audio_stream_t * stream) +{ + stream->active = 0; + stream->period = 0; +} +#else /* Polling */ + +static int spawn_hdmi_feeding_thread(audio_stream_t * stream); +static int hdmi_feeding_thread(void *data); +static void u8500_hdmi_pio_start(audio_stream_t * stream); + +#define stm_trigger_hdmi(x) spawn_hdmi_feeding_thread(x); + +static void inline stm_pause_hdmi(audio_stream_t * stream) +{ + stream->state = ALSA_STATE_PAUSE; +} +static void inline stm_unpause_hdmi(audio_stream_t * stream) +{ + stream->state = ALSA_STATE_UNPAUSE; + complete(&stream->alsa_com); +} +static void inline stm_stop_hdmi(audio_stream_t * stream) +{ + stream->active = 0; + stream->period = 0; + if (stream->state == ALSA_STATE_PAUSE) + complete(&stream->alsa_com); +} + +#endif + +extern struct driver_debug_st DBG_ST; +extern struct i2sdrv_data *i2sdrv[MAX_I2S_CLIENTS]; + +static void u8500_audio_hdmi_init(u8500_acodec_chip_t * chip); +int u8500_register_alsa_hdmi_controls(struct snd_card *card, + u8500_acodec_chip_t * u8500_chip); +static int snd_u8500_alsa_hdmi_open(struct snd_pcm_substream *substream); +static int snd_u8500_alsa_hdmi_close(struct snd_pcm_substream *substream); +static int snd_u8500_alsa_hdmi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params); +static int snd_u8500_alsa_hdmi_hw_free(struct snd_pcm_substream *substream); +static int snd_u8500_alsa_hdmi_prepare(struct snd_pcm_substream *substream); +static int snd_u8500_alsa_hdmi_trigger(struct snd_pcm_substream *substream, + int cmd); +static snd_pcm_uframes_t snd_u8500_alsa_hdmi_pointer(struct snd_pcm_substream + *substream); +static int configure_hdmi_rate(struct snd_pcm_substream *); +static int configure_msp_hdmi(int sampling_freq, int channel_count); + +int u8500_hdmi_rates[] = { 32000, 44100, 48000, 64000, 88200, + 96000, 128000, 176100, 192000 +}; + +typedef enum { + HDMI_SAMPLING_FREQ_32KHZ = 32, + HDMI_SAMPLING_FREQ_44_1KHZ = 44, + HDMI_SAMPLING_FREQ_48KHZ = 48, + HDMI_SAMPLING_FREQ_64KHZ = 64, + HDMI_SAMPLING_FREQ_88_2KHZ = 88, + HDMI_SAMPLING_FREQ_96KHZ = 96, + HDMI_SAMPLING_FREQ_128KHZ = 128, + HDMI_SAMPLING_FREQ_176_1KHZ = 176, + HDMI_SAMPLING_FREQ_192KHZ = 192 +} t_hdmi_sample_freq; + +static struct snd_pcm_ops snd_u8500_alsa_hdmi_playback_ops = { + .open = snd_u8500_alsa_hdmi_open, + .close = snd_u8500_alsa_hdmi_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_u8500_alsa_hdmi_hw_params, + .hw_free = snd_u8500_alsa_hdmi_hw_free, + .prepare = snd_u8500_alsa_hdmi_prepare, + .trigger = snd_u8500_alsa_hdmi_trigger, + .pointer = snd_u8500_alsa_hdmi_pointer, +}; + +static struct snd_pcm_ops snd_u8500_alsa_hdmi_capture_ops = { + .open = snd_u8500_alsa_hdmi_open, + .close = snd_u8500_alsa_hdmi_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_u8500_alsa_hdmi_hw_params, + .hw_free = snd_u8500_alsa_hdmi_hw_free, + .prepare = snd_u8500_alsa_hdmi_prepare, + .trigger = snd_u8500_alsa_hdmi_trigger, + .pointer = snd_u8500_alsa_hdmi_pointer, +}; + +/* Hardware description , this structure (struct snd_pcm_hardware ) + * contains the definitions of the fundamental hardware configuration. + * This configuration will be applied on the runtime structure + */ +static struct snd_pcm_hardware snd_u8500_hdmi_playback_hw = { + .info = + (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), + .formats = + SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = MIN_RATE_PLAYBACK, + .rate_max = MAX_RATE_PLAYBACK, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = NMDK_BUFFER_SIZE, + .period_bytes_min = 128, + .period_bytes_max = PAGE_SIZE, + .periods_min = NMDK_BUFFER_SIZE / PAGE_SIZE, + .periods_max = NMDK_BUFFER_SIZE / 128 +}; + +static struct snd_pcm_hardware snd_u8500_hdmi_capture_hw = { + .info = + (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), + .formats = + SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = MIN_RATE_CAPTURE, + .rate_max = MAX_RATE_CAPTURE, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = NMDK_BUFFER_SIZE, + .period_bytes_min = 128, + .period_bytes_max = PAGE_SIZE, + .periods_min = NMDK_BUFFER_SIZE / PAGE_SIZE, + .periods_max = NMDK_BUFFER_SIZE / 128 +}; + +static struct snd_pcm_hw_constraint_list constraints_hdmi_rate = { + .count = sizeof(u8500_hdmi_rates) / sizeof(u8500_hdmi_rates[0]), + .list = u8500_hdmi_rates, + .mask = 0, +}; + +/** + * snd_card_u8500_alsa_hdmi_new - constructor for a new pcm cmponent + * @chip - pointer to chip specific data + * @device - specifies the card number + */ +int snd_card_u8500_alsa_hdmi_new(u8500_acodec_chip_t * chip, int device) +{ + struct snd_pcm *pcm; + int err; + + if ((err = + snd_pcm_new(chip->card, "u8500_hdmi", device, 1, 1, &pcm)) < 0) { + stm_error(" : error in snd_pcm_new\n"); + return err; + } + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_u8500_alsa_hdmi_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_u8500_alsa_hdmi_capture_ops); + + pcm->private_data = chip; + pcm->info_flags = 0; + chip->pcm_hdmi = pcm; + strcpy(pcm->name, "u8500_alsa_hdmi"); + + u8500_audio_hdmi_init(pcm->private_data); + return 0; +} + +/** +* u8500_audio_hdmi_init +* @chip - pointer to u8500_acodec_chip_t structure. +* +* This function intialises the u8500 chip structure with default values +*/ +static void u8500_audio_hdmi_init(u8500_acodec_chip_t * chip) +{ + audio_stream_t *ptr_audio_stream = NULL; + + ptr_audio_stream = + &chip->stream[ALSA_HDMI_DEV][SNDRV_PCM_STREAM_PLAYBACK]; + /* Setup DMA stuff */ + + strlcpy(ptr_audio_stream->id, "u8500 hdmi playback", + sizeof(ptr_audio_stream->id)); + + ptr_audio_stream->stream_id = SNDRV_PCM_STREAM_PLAYBACK; + + /* default initialization for playback */ + ptr_audio_stream->active = 0; + ptr_audio_stream->period = 0; + ptr_audio_stream->periods = 0; + ptr_audio_stream->old_offset = 0; + + ptr_audio_stream = + &chip->stream[ALSA_HDMI_DEV][SNDRV_PCM_STREAM_CAPTURE]; + + strlcpy(ptr_audio_stream->id, "u8500 hdmi capture", + sizeof(ptr_audio_stream->id)); + + ptr_audio_stream->stream_id = SNDRV_PCM_STREAM_CAPTURE; + + /* default initialization for capture */ + ptr_audio_stream->active = 0; + ptr_audio_stream->period = 0; + ptr_audio_stream->periods = 0; + ptr_audio_stream->old_offset = 0; + +} + +/** + * snd_u8500_alsa_hdmi_open + * @substream - pointer to the playback/capture substream structure + * + * This routine is used by alsa framework to open a pcm stream . + * Here a dma pipe is requested and device is configured(default). + */ +static int snd_u8500_alsa_hdmi_open(struct snd_pcm_substream *substream) +{ + int error = 0, stream_id, status = 0; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + audio_stream_t *ptr_audio_stream = NULL; + + stream_id = substream->pstr->stream; + error = u8500_acodec_setuser(USER_ALSA); + status = u8500_acodec_open(I2S_CLIENT_MSP2, stream_id); + if (status) { + printk("failed in getting open\n"); + return (-1); + } + + error = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_hdmi_rate); + if (error < 0) { + stm_error + (": error initializing hdmi hw sample rate constraint\n"); + return error; + } + + if ((error = configure_hdmi_rate(substream))) + return error; + + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { + runtime->hw = snd_u8500_hdmi_playback_hw; + } else { + runtime->hw = snd_u8500_hdmi_capture_hw; + } + + ptr_audio_stream = &chip->stream[ALSA_HDMI_DEV][stream_id]; + + ptr_audio_stream->substream = substream; + + stm_config_hw(chip, substream, ALSA_HDMI_DEV, stream_id); + init_MUTEX(&(ptr_audio_stream->alsa_sem)); + init_completion(&(ptr_audio_stream->alsa_com)); + + ptr_audio_stream->state = ALSA_STATE_UNPAUSE; + return 0; +} + +/** + * snd_u8500_alsa_hdmi_close + * @substream - pointer to the playback/capture substream structure + * + * This routine is used by alsa framework to close a pcm stream . + * Here a dma pipe is disabled and freed. + */ + +static int snd_u8500_alsa_hdmi_close(struct snd_pcm_substream *substream) +{ + int stream_id, error = 0; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + audio_stream_t *ptr_audio_stream = NULL; + + stream_id = substream->pstr->stream; + ptr_audio_stream = &chip->stream[ALSA_HDMI_DEV][stream_id]; + + stm_close_alsa(chip, ALSA_HDMI_DEV, stream_id); + + /* reset the different variables to default */ + + ptr_audio_stream->active = 0; + ptr_audio_stream->period = 0; + ptr_audio_stream->periods = 0; + ptr_audio_stream->old_offset = 0; + ptr_audio_stream->substream = NULL; + + /* Disable the MSP2 */ + error = u8500_acodec_unsetuser(USER_ALSA); + u8500_acodec_close(I2S_CLIENT_MSP2, ACODEC_DISABLE_ALL); + + return error; + +} + +/** + * snd_u8500_alsa_hdmi_hw_params + * @substream - pointer to the playback/capture substream structure + * @hw_params - specifies the hw parameters like format/no of channels etc + * + * This routine is used by alsa framework to allocate a dma buffer + * used to transfer the data from user space to kernel space + * + */ +static int snd_u8500_alsa_hdmi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +} + +/** + * snd_u8500_alsa_hdmi_hw_free + * @substream - pointer to the playback/capture substream structure + * + * This routine is used by alsa framework to deallocate a dma buffer + * allocated berfore by snd_u8500_alsa_pcm_hw_params + */ +static int snd_u8500_alsa_hdmi_hw_free(struct snd_pcm_substream *substream) +{ + stm_hw_free(substream); + return 0; +} + +/** + * snd_u8500_alsa_hdmi_pointer + * @substream - pointer to the playback/capture substream structure + * + * This callback is called whene the pcm middle layer inquires the current + * hardware position on the buffer .The position is returned in frames + * ranged from 0 to buffer_size -1 + */ +static snd_pcm_uframes_t snd_u8500_alsa_hdmi_pointer(struct snd_pcm_substream + *substream) +{ + unsigned int offset; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + audio_stream_t *stream = + &chip->stream[ALSA_HDMI_DEV][substream->pstr->stream]; + struct snd_pcm_runtime *runtime = stream->substream->runtime; + + offset = bytes_to_frames(runtime, stream->old_offset); + if (offset < 0 || stream->old_offset < 0) + stm_dbg(DBG_ST.alsa, " Offset=%i %i\n", offset, + stream->old_offset); + + return offset; +} + +/** + * snd_u8500_alsa_hdmi_prepare + * @substream - pointer to the playback/capture substream structure + * + * This callback is called whene the pcm is "prepared" Here is possible + * to set the format type ,sample rate ,etc.The callback is called as + * well everytime a recovery after an underrun happens. + */ + +static int snd_u8500_alsa_hdmi_prepare(struct snd_pcm_substream *substream) +{ + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int error; + + if (chip->hdmi_params.sampling_freq != runtime->rate + || chip->hdmi_params.channel_count != runtime->channels) { + stm_dbg(DBG_ST.alsa, " freq not same, %d %d\n", + chip->hdmi_params.sampling_freq, runtime->rate); + stm_dbg(DBG_ST.alsa, " channels not same, %d %d\n", + chip->hdmi_params.channel_count, runtime->channels); + if (chip->hdmi_params.channel_count != runtime->channels) { + chip->hdmi_params.channel_count = runtime->channels; + if ((error = + stm_config_hw(chip, substream, ALSA_HDMI_DEV, + -1))) { + stm_dbg(DBG_ST.alsa, + "In func %s, stm_config_hw fails", + __FUNCTION__); + return error; + } + } + chip->hdmi_params.sampling_freq = runtime->rate; + if ((error = configure_hdmi_rate(substream))) { + stm_dbg(DBG_ST.alsa, "In func %s, configure_rate fails", + __FUNCTION__); + return error; + } + } + + return 0; +} + +/** + * snd_u8500_alsa_hdmi_trigger + * @substream - pointer to the playback/capture substream structure + * @cmd - specifies the command : start/stop/pause/resume + * + * This callback is called whene the pcm is started ,stopped or paused + * The action is specified in the second argument, SND_PCM_TRIGGER_XXX in + * . + * This callback is atomic and the interrupts are disabled , so you can't + * call other functions that need interrupts without possible risks + */ +static int snd_u8500_alsa_hdmi_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + int stream_id = substream->pstr->stream; + audio_stream_t *stream = NULL; + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + int error = 0; + + stream = &chip->stream[ALSA_HDMI_DEV][stream_id]; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* Start the pcm engine */ + stm_dbg(DBG_ST.alsa, " TRIGGER START\n"); + if (stream->active == 0) { + stream->active = 1; + stm_trigger_hdmi(stream); + break; + } + stm_error(": H/w is busy\n"); + return -EINVAL; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + stm_dbg(DBG_ST.alsa, " SNDRV_PCM_TRIGGER_PAUSE_PUSH\n"); + if (stream->active == 1) { + stm_pause_hdmi(stream); + } + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + stm_dbg(DBG_ST.alsa, " SNDRV_PCM_TRIGGER_PAUSE_RELEASE\n"); + if (stream->active == 1) + stm_unpause_hdmi(stream); + break; + case SNDRV_PCM_TRIGGER_STOP: + /* Stop the pcm engine */ + stm_dbg(DBG_ST.alsa, " TRIGGER STOP\n"); + if (stream->active == 1) + stm_stop_hdmi(stream); + break; + default: + stm_error(": invalid command in pcm trigger\n"); + return -EINVAL; + } + + return error; + +} + +struct snd_kcontrol_new u8500_hdmi_power_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .device = 1, + .subdevice = 0, + .name = "HDMI Power", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .private_value = 0xfff, + .info = u8500_hdmi_power_ctrl_info, + .get = u8500_hdmi_power_ctrl_get, + .put = u8500_hdmi_power_ctrl_put +}; + +/** +* u8500_hdmi_power_ctrl_info +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions fills playback device info into user structure. +*/ +static int u8500_hdmi_power_ctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = NUMBER_POWER_STATE; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= NUMBER_POWER_STATE) + uinfo->value.enumerated.item = NUMBER_POWER_STATE - 1; + strcpy(uinfo->value.enumerated.name, + power_state_in_texts[uinfo->value.enumerated.item]); + return 0; +} + +/** +* u8500_hdmi_power_ctrl_get +* @kcontrol - pointer to the snd_kcontrol structure +* @uinfo - pointer to the snd_ctl_elem_info structure, this is filled by the function +* +* This functions returns the current playback device selected. +*/ +static int u8500_hdmi_power_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + uinfo->value.enumerated.item[0] = 0; + return 0; +} + +/** +* u8500_hdmi_power_ctrl_put +* @kcontrol - pointer to the snd_kcontrol structure +* @ . +* +* This functions sets the playback device. +*/ +static int u8500_hdmi_power_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uinfo) +{ + u8500_acodec_chip_t *chip = + (u8500_acodec_chip_t *) snd_kcontrol_chip(kcontrol); + int changed = 0; + t_ab8500_codec_error error; + t_u8500_bool_state power_state; + + power_state = uinfo->value.enumerated.item[0]; + + changed = 1; + + return changed; +} + +int u8500_register_alsa_hdmi_controls(struct snd_card *card, + u8500_acodec_chip_t * u8500_chip) +{ + int error; + + if ((error = + snd_ctl_add(card, + snd_ctl_new1(&u8500_hdmi_power_ctrl, + u8500_chip))) < 0) { + stm_error + (": error initializing u8500_hdmi_power_ctrl interface \n\n"); + return (-1); + } + + return 0; +} + +/** +* configure_hdmi_rate +* @substream - pointer to the playback/capture substream structure +* +* This functions configures audio codec in to stream frequency frequency +*/ +static int configure_hdmi_rate(struct snd_pcm_substream *substream) +{ + t_hdmi_sample_freq hdmi_sampling_freq; + + u8500_acodec_chip_t *chip = snd_pcm_substream_chip(substream); + + switch (chip->hdmi_params.sampling_freq) { + case 32000: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_32KHZ; + break; + case 44100: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_44_1KHZ; + break; + case 48000: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_48KHZ; + break; + case 64000: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_64KHZ; + break; + case 88200: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_88_2KHZ; + break; + case 96000: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_96KHZ; + break; + case 128000: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_128KHZ; + break; + case 176100: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_176_1KHZ; + break; + case 192000: + hdmi_sampling_freq = HDMI_SAMPLING_FREQ_192KHZ; + default: + stm_error("not supported frequnecy\n"); + return -EINVAL; + } + + configure_msp_hdmi(hdmi_sampling_freq, chip->hdmi_params.channel_count); + + return 0; + +} + +static int configure_msp_hdmi(int sampling_freq, int channel_count) +{ + struct i2s_device *i2s_dev = i2sdrv[I2S_CLIENT_MSP2]->i2s; + struct msp_config msp_config; + t_ab8500_codec_error error_status = AB8500_CODEC_OK; + + memset(&msp_config, 0, sizeof(msp_config)); + + + if (i2sdrv[I2S_CLIENT_MSP2]->flag) { + stm_dbg(DBG_ST.acodec, " I2S controller not available\n"); + return -1; + } + + /* MSP configuration */ + + msp_config.tx_clock_sel = 0; + msp_config.rx_clock_sel = 0; + + msp_config.tx_frame_sync_sel = 0; + msp_config.rx_frame_sync_sel = 0; + + msp_config.input_clock_freq = MSP_INPUT_FREQ_48MHZ; + msp_config.srg_clock_sel = 0; + + msp_config.rx_frame_sync_pol = RX_FIFO_SYNC_HI; + msp_config.tx_frame_sync_pol = TX_FIFO_SYNC_HI; + + msp_config.rx_fifo_config = 0; + msp_config.tx_fifo_config = TX_FIFO_ENABLE; + + msp_config.spi_clk_mode = SPI_CLK_MODE_NORMAL; + msp_config.spi_burst_mode = 0; + msp_config.tx_data_enable = 0; + msp_config.loopback_enable = 0; + msp_config.default_protocol_desc = 1; + msp_config.direction = MSP_TRANSMIT_MODE; + msp_config.protocol = MSP_I2S_PROTOCOL; + msp_config.frame_size = ELEMENT_SIZE; + msp_config.frame_freq = sampling_freq; + msp_config.def_elem_len = 0; + /* enable msp for both tr and rx mode with dma data transfer. + THIS IS NOW DONE SEPARATELY from SAA. */ + msp_config.data_size = MSP_DATA_SIZE_16BIT; + +#ifdef CONFIG_U8500_ACODEC_DMA + msp_config.work_mode = MSP_DMA_MODE; +#elif defined(CONFIG_U8500_ACODEC_POLL) + msp_config.work_mode = MSP_POLLING_MODE; +#else + msp_config.work_mode = MSP_INTERRUPT_MODE; +#endif + msp_config.default_protocol_desc = 0; + + msp_config.protocol_desc.rx_phase_mode = MSP_DUAL_PHASE; + msp_config.protocol_desc.tx_phase_mode = MSP_DUAL_PHASE; + msp_config.protocol_desc.rx_phase2_start_mode = + MSP_PHASE2_START_MODE_FRAME_SYNC; + msp_config.protocol_desc.tx_phase2_start_mode = + MSP_PHASE2_START_MODE_FRAME_SYNC; + msp_config.protocol_desc.rx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + msp_config.protocol_desc.tx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + msp_config.protocol_desc.rx_frame_length_1 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.rx_frame_length_2 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.tx_frame_length_1 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.tx_frame_length_2 = MSP_FRAME_LENGTH_1; + msp_config.protocol_desc.rx_element_length_1 = MSP_ELEM_LENGTH_16; + msp_config.protocol_desc.rx_element_length_2 = MSP_ELEM_LENGTH_16; + msp_config.protocol_desc.tx_element_length_1 = MSP_ELEM_LENGTH_16; + msp_config.protocol_desc.tx_element_length_2 = MSP_ELEM_LENGTH_16; + msp_config.protocol_desc.rx_data_delay = MSP_DELAY_1; + msp_config.protocol_desc.tx_data_delay = MSP_DELAY_1; + msp_config.protocol_desc.rx_clock_pol = MSP_RISING_EDGE; + msp_config.protocol_desc.tx_clock_pol = 0; + msp_config.protocol_desc.rx_frame_sync_pol = + MSP_FRAME_SYNC_POL_ACTIVE_HIGH; + msp_config.protocol_desc.tx_frame_sync_pol = + MSP_FRAME_SYNC_POL_ACTIVE_HIGH; + msp_config.protocol_desc.rx_half_word_swap = MSP_HWS_NO_SWAP; + msp_config.protocol_desc.tx_half_word_swap = MSP_HWS_NO_SWAP; + msp_config.protocol_desc.compression_mode = MSP_COMPRESS_MODE_LINEAR; + msp_config.protocol_desc.expansion_mode = MSP_EXPAND_MODE_LINEAR; + msp_config.protocol_desc.spi_clk_mode = MSP_SPI_CLOCK_MODE_NON_SPI; + msp_config.protocol_desc.spi_burst_mode = MSP_SPI_BURST_MODE_DISABLE; + msp_config.protocol_desc.frame_period = 63; + msp_config.protocol_desc.frame_width = 31; + msp_config.protocol_desc.total_clocks_for_one_frame = 64; + msp_config.multichannel_configured = 0; + msp_config.multichannel_config.tx_multichannel_enable = 0; + /* Channel 1 and channel 3 */ + msp_config.multichannel_config.tx_channel_0_enable = 0x0000005; + msp_config.multichannel_config.tx_channel_1_enable = 0x0000000; + msp_config.multichannel_config.tx_channel_2_enable = 0x0000000; + msp_config.multichannel_config.tx_channel_3_enable = 0x0000000; + error_status = i2s_setup(i2s_dev->controller, &msp_config); + +#ifdef CONFIG_DEBUG + { + dump_msp2_registers(); + } +#endif + + if (error_status < 0) { + printk("error in msp enable, error_status is %d\n", + error_status); + return error_status; + } + + return 0; + +} + +#ifdef CONFIG_U8500_ACODEC_DMA +/** + * u8500_alsa_hdmi_dma_start - used to transmit or recive a dma chunk + * @stream - specifies the playback/record stream structure + */ +static void u8500_alsa_hdmi_dma_start(audio_stream_t * stream) +{ + unsigned int offset, dma_size, stream_id; + + struct snd_pcm_substream *substream = stream->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + + stream_id = substream->pstr->stream; + + dma_size = frames_to_bytes(runtime, runtime->period_size); + offset = dma_size * stream->period; + stream->old_offset = offset; + + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_send_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_send_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + else +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_receive_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_receive_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + + stm_dbg(DBG_ST.alsa, " DMA Transfer started\n"); + stm_dbg(DBG_ST.alsa, " address = %x size=%d\n", + (runtime->dma_addr + offset), dma_size); + + stream->period++; + stream->period %= runtime->periods; + stream->periods++; + + +} + +#else + +/** +* acodec_feeding_thread +* @stream - pointer to the playback/capture audio_stream_t structure +* +* This function creates a kernel thread . +*/ + +static int spawn_hdmi_feeding_thread(audio_stream_t * stream) +{ + pid_t pid; + + pid = + kernel_thread(hdmi_feeding_thread, stream, + CLONE_FS | CLONE_SIGHAND); + + return 0; +} + +/** +* hdmi_feeding_thread +* @data - void pointer to the playback/capture audio_stream_t structure +* +* This thread sends/receive data to MSP while stream is active +*/ +static int hdmi_feeding_thread(void *data) +{ + audio_stream_t *stream = (audio_stream_t *) data; + + daemonize("hdmi_feeding_thread"); + allow_signal(SIGKILL); + down(&stream->alsa_sem); + + while ((!signal_pending(current)) && (stream->active)) { + if (stream->state == ALSA_STATE_PAUSE) + wait_for_completion(&(stream->alsa_com)); + + u8500_hdmi_pio_start(stream); + if (stream->substream) + snd_pcm_period_elapsed(stream->substream); + } + + up(&stream->alsa_sem); + + return 0; +} + +/** +* u8500_hdmi_pio_start +* @stream - pointer to the playback/capture audio_stream_t structure +* +* This function sends/receive one chunck of stream data to/from MSP +*/ +static void u8500_hdmi_pio_start(audio_stream_t * stream) +{ + unsigned int offset, dma_size, stream_id; + struct snd_pcm_substream *substream = stream->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + stream_id = substream->pstr->stream; + + dma_size = frames_to_bytes(runtime, runtime->period_size); + offset = dma_size * stream->period; + stream->old_offset = offset; + + stm_dbg(DBG_ST.alsa, " Transfer started\n"); + stm_dbg(DBG_ST.alsa, " address = %x size=%d\n", + (runtime->dma_addr + offset), dma_size); + + /* Send our stuff */ + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_send_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_send_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + else +#ifdef CONFIG_U8500_ACODEC_DMA + u8500_acodec_receive_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_addr + offset), + dma_size, 1); +#else + u8500_acodec_receive_data(I2S_CLIENT_MSP2, + (void *)(runtime->dma_area + offset), + dma_size, 0); +#endif + + stream->period++; + stream->period %= runtime->periods; + stream->periods++; +} +#endif + +void dump_msp2_registers() +{ + int i; + + stm_dbg(DBG_ST.acodec, "\nMSP_2 base add = 0x%x\n", + (unsigned int)U8500_MSP2_BASE); + + for (i = 0; i < 0x40; i += 4) + stm_dbg(DBG_ST.acodec, "msp[0x%x]=0x%x\n", i, + readl((char *)(IO_ADDRESS(U8500_MSP2_BASE) + i))); + + return 0; +} -- cgit v1.2.3 From a2a3ec3bd918816e11a9631006cb60aae20596a6 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Tue, 19 Oct 2010 20:27:15 +0200 Subject: sound: add asoc support for ux500 platform This patch is based on the following work: cg29xx ASoc: The codec driver for cg29xx does now use the MFD driver for that chip. ST-Ericsson ID: 259 100 Author: Roger Nilsson Ux500 ASoc: Added support for the DSP_A format. ST-Ericsson ID: 259 074 Author: Roger Nilsson Ux500 ASoC: Added support for TDM. ST-Ericsson ID: 259 074 Author: Roger Nilsson Ux500 ASoC: HDMI-driver in Ux500 ALSA SoC-driver. Author: Ola Lilja Add a power management scheme for AB3550 and fix bugs that hinder simultaneous playback/capture. ST-Ericsson ID: WP 259100 Author: Xie Xiaolei msp: add configuration param for MSP_IODLY ST-Ericsson ID: CR261462 Author: Rabin Vincent sound: asoc: Added codec and machine drivers for cg29xx. Author: Ola Lilja Signed-off-by: Mian Yousaf Kaukab --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/ux500/Kconfig | 46 ++ sound/soc/ux500/Makefile | 20 + sound/soc/ux500/ux500_ab3550.c | 207 +++++++++ sound/soc/ux500/ux500_av8100.c | 164 +++++++ sound/soc/ux500/ux500_cg29xx.c | 177 ++++++++ sound/soc/ux500/ux500_msp_dai.c | 961 ++++++++++++++++++++++++++++++++++++++++ sound/soc/ux500/ux500_msp_dai.h | 56 +++ sound/soc/ux500/ux500_pcm.c | 376 ++++++++++++++++ sound/soc/ux500/ux500_pcm.h | 43 ++ 11 files changed, 2052 insertions(+) create mode 100644 sound/soc/ux500/Kconfig create mode 100644 sound/soc/ux500/Makefile create mode 100644 sound/soc/ux500/ux500_ab3550.c create mode 100644 sound/soc/ux500/ux500_av8100.c create mode 100644 sound/soc/ux500/ux500_cg29xx.c create mode 100644 sound/soc/ux500/ux500_msp_dai.c create mode 100644 sound/soc/ux500/ux500_msp_dai.h create mode 100644 sound/soc/ux500/ux500_pcm.c create mode 100644 sound/soc/ux500/ux500_pcm.h diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 91c985599d3..359eb0fd6d2 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -48,6 +48,7 @@ source "sound/soc/s6000/Kconfig" source "sound/soc/sh/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" +source "sound/soc/ux500/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 2feaf376e94..f5fe62111b8 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_SND_SOC) += s6000/ obj-$(CONFIG_SND_SOC) += sh/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ +obj-$(CONFIG_SND_SOC) += ux500/ diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig new file mode 100644 index 00000000000..52944f6fa64 --- /dev/null +++ b/sound/soc/ux500/Kconfig @@ -0,0 +1,46 @@ +# +# Ux500 SoC audio configuration +# + +config SND_SOC_UX500 + bool "SoC Audio support for Ux500 platform" + depends on SND_SOC && STM_I2S && STM_MSP_I2S + default n + help + Say Y if you want to add support for the codecs attached to + the I2S of the Ux500. You will also need + to select the audio codec to be supported in the driver. + +choice + prompt "Codec to be used in Ux500 ASoC driver" + depends on SND_SOC_UX500 + default SND_SOC_CG29XX + +config SND_SOC_UX500_AB3550 + bool "AB3550" + depends on AB3550_CORE + select SND_SOC_AB3550 + help + Say Y if you want to use AB3550 codec (Petronella MSA). + +config SND_SOC_UX500_CG29XX + bool "CG29xx" + select SND_SOC_CG29XX + help + Say Y if you want to use CG29xx codec (Combo chip). + +config SND_SOC_UX500_AV8100 + bool "AV8100" + depends on AV8100 + select SND_SOC_AV8100 + help + Say Y if you want to use AV8100 codec (HDMI chip). + +endchoice + +config SND_SOC_UX500_DEBUG + bool "Activate Ux500 platform debug-mode (pr_debug)" + depends on SND_SOC && STM_I2S && STM_MSP_I2S + default n + help + Say Y if you want to add debug level prints for Ux500 code-files. diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile new file mode 100644 index 00000000000..9c594d025ad --- /dev/null +++ b/sound/soc/ux500/Makefile @@ -0,0 +1,20 @@ +# Ux500 Platform Support + +ifdef CONFIG_SND_SOC_UX500_DEBUG +CFLAGS_av8100_audio.o := -DDEBUG +CFLAGS_ab3550.o := -DDEBUG +CFLAGS_cg29xx.o := -DDEBUG +CFLAGS_ux500_pcm.o := -DDEBUG +CFLAGS_ux500_msp_dai.o := -DDEBUG +CFLAGS_ux500_av8100.o := -DDEBUG +endif + +snd-soc-ux500-objs := ux500_pcm.o ux500_msp_dai.o +snd-soc-ux500-ab3550-objs := ux500_ab3550.o +snd-soc-ux500-cg29xx-objs := ux500_cg29xx.o +snd-soc-ux500-av8100-objs := ux500_av8100.o + +obj-$(CONFIG_SND_SOC_UX500) += snd-soc-ux500.o +obj-$(CONFIG_SND_SOC_UX500_AB3550) += snd-soc-ux500-ab3550.o +obj-$(CONFIG_SND_SOC_UX500_CG29XX) += snd-soc-ux500-cg29xx.o +obj-$(CONFIG_SND_SOC_UX500_AV8100) += snd-soc-ux500-av8100.o diff --git a/sound/soc/ux500/ux500_ab3550.c b/sound/soc/ux500/ux500_ab3550.c new file mode 100644 index 00000000000..103e8b2cfb5 --- /dev/null +++ b/sound/soc/ux500/ux500_ab3550.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ola Lilja ola.o.lilja@stericsson.com, + * Roger Nilsson roger.xr.nilsson@stericsson.com + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include "ux500_pcm.h" +#include "ux500_msp_dai.h" +#include "mach/hardware.h" +#include "../codecs/ab3550.h" + +static struct platform_device *ux500_ab3550_platform_device; + +#define AB3550_DAI_FMT_I2S_M (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM) +#define AB3550_DAI_FMT_I2S_S (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS) +#define AB3550_DAI_FMT AB3550_DAI_FMT_I2S_S + +static int ux500_ab3550_startup(struct snd_pcm_substream *substream) +{ + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Enter\n", + __func__); + return 0; +} + +static void ux500_ab3550_shutdown(struct snd_pcm_substream *substream) +{ + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Enter\n", + __func__); +} + +static int ux500_ab3550_hw_params( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ifid, ret = 0; + + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Enter\n", + __func__); + + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: substream->pcm->name = %s\n" + "substream->pcm->id = %s.\n" + "substream->name = %s.\n" + "substream->number = %d.\n", + __func__, + substream->pcm->name, + substream->pcm->id, + substream->name, + substream->number); + + for (ifid = 0; ifid < ARRAY_SIZE(ab3550_codec_dai); ifid++) { + if (strcmp(codec_dai->name, ab3550_codec_dai[ifid].name) == 0) + break; + } + + if (codec_dai->ops->set_fmt) { + ret = snd_soc_dai_set_fmt(codec_dai, AB3550_DAI_FMT); + if (ret < 0) { + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: snd_soc_dai_set_fmt failed with %d.\n", + __func__, + ret); + return ret; + } + + ret = snd_soc_dai_set_fmt(cpu_dai, AB3550_DAI_FMT); + + if (ret < 0) { + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: snd_soc_dai_set_fmt" + " failed with %d.\n", __func__, ret); + return ret; + } + } + + return ret; +} + +static struct snd_soc_ops ux500_ab3550_ops = { + .startup = ux500_ab3550_startup, + .shutdown = ux500_ab3550_shutdown, + .hw_params = ux500_ab3550_hw_params, +}; + +struct snd_soc_dai_link ux500_ab3550_dai_links[] = { + { + .name = "ab3550_0", + .stream_name = "ab3550_0", + .cpu_dai = &ux500_msp_dai[0], + .codec_dai = &ab3550_codec_dai[0], + .init = NULL, + .ops = &ux500_ab3550_ops, + }, + { + .name = "ab3550_1", + .stream_name = "ab3550_1", + .cpu_dai = &ux500_msp_dai[1], + .codec_dai = &ab3550_codec_dai[1], + .init = NULL, + .ops = &ux500_ab3550_ops, + }, +}; + +static struct snd_soc_card ux500_ab3550 = { + .name = "ab3550", + .probe = NULL, + .dai_link = ux500_ab3550_dai_links, + .num_links = ARRAY_SIZE(ux500_ab3550_dai_links), + .platform = &ux500_soc_platform, +}; + +struct snd_soc_device ux500_ab3550_drvdata = { + .card = &ux500_ab3550, + .codec_dev = &soc_codec_dev_ab3550, +}; + +static int __init mop500_ab3550_soc_init(void) +{ + int i; + int ret = 0; + + pr_debug("%s: Enter\n", + __func__); + pr_debug("%s: Card name: %s\n", + __func__, + ux500_ab3550_drvdata.card->name); + + for (i = 0; i < ARRAY_SIZE(ux500_ab3550_dai_links); i++) { + pr_debug("%s: DAI-link %d, name: %s\n", + __func__, + i, + ux500_ab3550_drvdata.card->dai_link[i].name); + pr_debug("%s: DAI-link %d, stream_name: %s\n", + __func__, + i, + ux500_ab3550_drvdata.card->dai_link[i].stream_name); + } + + pr_debug("%s: Allocate platform device (%s)\n", + __func__, + ux500_ab3550_drvdata.card->name); + ux500_ab3550_platform_device = platform_device_alloc("soc-audio", -1); + if (!ux500_ab3550_platform_device) + return -ENOMEM; + + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Set platform drvdata (%s)\n", + __func__, + ux500_ab3550_drvdata.card->name); + platform_set_drvdata( + ux500_ab3550_platform_device, + &ux500_ab3550_drvdata); + + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Add platform device (%s)\n", + __func__, + ux500_ab3550_drvdata.card->name); + ux500_ab3550_drvdata.dev = &ux500_ab3550_platform_device->dev; + + ret = platform_device_add(ux500_ab3550_platform_device); + if (ret) { + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Error: Failed to add platform device (%s)\n", + __func__, + ux500_ab3550_drvdata.card->name); + platform_device_put(ux500_ab3550_platform_device); + } + + return ret; +} +module_init(mop500_ab3550_soc_init); + +static void __exit mop500_ab3550_soc_exit(void) +{ + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Enter.\n", + __func__); + + dev_dbg(&ux500_ab3550_platform_device->dev, + "%s: Un-register platform device (%s)\n", + __func__, + ux500_ab3550_drvdata.card->name); + platform_device_unregister(ux500_ab3550_platform_device); +} +module_exit(mop500_ab3550_soc_exit); + +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ux500/ux500_av8100.c b/sound/soc/ux500/ux500_av8100.c new file mode 100644 index 00000000000..b6cced7f1e5 --- /dev/null +++ b/sound/soc/ux500/ux500_av8100.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ola Lilja (ola.o.lilja@stericsson.com) + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include + +#include "ux500_pcm.h" +#include "ux500_msp_dai.h" + +#include +#include + +#include "../codecs/av8100_audio.h" + +static struct platform_device *ux500_av8100_platform_device; + +static int ux500_av8100_hw_params( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret = 0; + + pr_debug("%s: Enter.\n", __func__); + + pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name); + pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id); + pr_debug("%s: substream->name = %s.\n", __func__, substream->name); + pr_debug("%s: substream->number = %d.\n", __func__, substream->number); + + if (cpu_dai->ops->set_fmt) { + dev_dbg(&ux500_av8100_platform_device->dev, + "%s: Setting format on codec_dai: " + "SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM.", + __func__); + ret = snd_soc_dai_set_fmt( + codec_dai, + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) { + dev_dbg(&ux500_av8100_platform_device->dev, + "%s: snd_soc_dai_set_fmt failed with %d.\n", + __func__, + ret); + return ret; + } + + dev_dbg(&ux500_av8100_platform_device->dev, + "%s: Setting format on cpu_dai: " + "SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM.", + __func__); + ret = snd_soc_dai_set_fmt( + cpu_dai, + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) { + dev_dbg(&ux500_av8100_platform_device->dev, + "%s: snd_soc_dai_set_fmt failed with %d.\n", + __func__, + ret); + return ret; + } + } + return ret; +} + +struct snd_soc_dai_link ux500_av8100_dai_links[] = { + { + .name = "hdmi", + .stream_name = "hdmi", + .cpu_dai = &ux500_msp_dai[2], + .codec_dai = &av8100_codec_dai[0], + .init = NULL, + .ops = (struct snd_soc_ops[]) { + { + .hw_params = ux500_av8100_hw_params, + } + } + }, +}; + +static struct snd_soc_card ux500_av8100 = { + .name = "hdmi", + .probe = NULL, + .dai_link = ux500_av8100_dai_links, + .num_links = ARRAY_SIZE(ux500_av8100_dai_links), + .platform = &ux500_soc_platform, +}; + +struct snd_soc_device ux500_av8100_drvdata = { + .card = &ux500_av8100, + .codec_dev = &soc_codec_dev_av8100, +}; + +static int __init ux500_av8100_soc_init(void) +{ + int ret = 0; + + pr_debug("%s: Enter.\n", __func__); + + pr_info("%s: Card name: %s\n", + __func__, + ux500_av8100_drvdata.card->name); + + pr_debug("%s: DAI-link 0, name: %s\n", + __func__, + ux500_av8100_drvdata.card->dai_link[0].name); + pr_debug("%s: DAI-link 0, stream_name: %s\n", + __func__, + ux500_av8100_drvdata.card->dai_link[0].stream_name); + + pr_debug("%s: Allocate platform device (%s).\n", + __func__, + ux500_av8100_drvdata.card->name); + ux500_av8100_platform_device = platform_device_alloc("soc-audio", -1); + if (!ux500_av8100_platform_device) + return -ENOMEM; + + pr_debug("%s: Set platform drvdata (%s).\n", + __func__, + ux500_av8100_drvdata.card->name); + platform_set_drvdata( + ux500_av8100_platform_device, + &ux500_av8100_drvdata); + ux500_av8100_drvdata.dev = &ux500_av8100_platform_device->dev; + + pr_debug("%s: Add platform device (%s).\n", + __func__, + ux500_av8100_drvdata.card->name); + ret = platform_device_add(ux500_av8100_platform_device); + if (ret) { + pr_err("%s: Error: Failed to add platform device (%s).\n", + __func__, + ux500_av8100_drvdata.card->name); + platform_device_put(ux500_av8100_platform_device); + } + + return ret; +} + +static void __exit ux500_av8100_soc_exit(void) +{ + pr_debug("%s: Enter.\n", __func__); + + pr_debug("%s: Unregister platform device (%s).\n", + __func__, + ux500_av8100_drvdata.card->name); + platform_device_unregister(ux500_av8100_platform_device); +} + +module_init(ux500_av8100_soc_init); +module_exit(ux500_av8100_soc_exit); + +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ux500/ux500_cg29xx.c b/sound/soc/ux500/ux500_cg29xx.c new file mode 100644 index 00000000000..0c74bbe4550 --- /dev/null +++ b/sound/soc/ux500/ux500_cg29xx.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Roger Nilsson roger.xr.nilsson@stericsson.com + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include "ux500_pcm.h" +#include "ux500_msp_dai.h" +#include "../codecs/cg29xx.h" + +#define UX500_CG29XX_DAI_SLOT_WIDTH 16 +#define UX500_CG29XX_DAI_SLOTS 2 +#define UX500_CG29XX_DAI_ACTIVE_SLOTS 0x01 + +static struct platform_device *ux500_cg29xx_platform_device; + +static int ux500_cg29xx_hw_params( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + + int err; + + pr_debug("%s: substream->pcm->name = %s.\n" + "substream->pcm->id = %s.\n" + "substream->name = %s.\n" + "substream->number = %d.\n", + __func__, + substream->pcm->name, + substream->pcm->id, + substream->name, + substream->number); + + err = snd_soc_dai_set_fmt( + codec_dai, + SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS); + + if (err) { + pr_err("%s: snd_soc_dai_set_fmt(codec)" + " failed with %d.\n", + __func__, + err); + goto out_err; + } + + err = snd_soc_dai_set_tdm_slot( + codec_dai, + 1 << CG29XX_DAI_SLOT0_SHIFT, + 1 << CG29XX_DAI_SLOT0_SHIFT, + UX500_CG29XX_DAI_SLOTS, + UX500_CG29XX_DAI_SLOT_WIDTH); + + if (err) { + pr_err("%s: cg29xx_set_tdm_slot(codec)" + " failed with %d.\n", + __func__, + err); + goto out_err; + } + + err = snd_soc_dai_set_fmt( + cpu_dai, + SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_NB_NF); + + if (err) { + pr_err("%s: snd_soc_dai_set_fmt(dai)" + " failed with %d.\n", + __func__, + err); + goto out_err; + } + + err = snd_soc_dai_set_tdm_slot(cpu_dai, + UX500_CG29XX_DAI_ACTIVE_SLOTS, + UX500_CG29XX_DAI_ACTIVE_SLOTS, + UX500_CG29XX_DAI_SLOTS, + UX500_CG29XX_DAI_SLOT_WIDTH); + + if (err) { + pr_err("%s: cg29xx_set_tdm_slot(dai)" + " failed with %d.\n", + __func__, + err); + goto out_err; + } + +out_err: + return err; +} + +static struct snd_soc_ops ux500_cg29xx_ops = { + .hw_params = ux500_cg29xx_hw_params, +}; + +struct snd_soc_dai_link ux500_cg29xx_dai_links[] = { + { + .name = "cg29xx_0", + .stream_name = "cg29xx_0", + .cpu_dai = &ux500_msp_dai[0], + .codec_dai = &cg29xx_codec_dai[1], + .init = NULL, + .ops = &ux500_cg29xx_ops, + }, +}; + +static struct snd_soc_card ux500_cg29xx = { + .name = "cg29xx", + .probe = NULL, + .dai_link = ux500_cg29xx_dai_links, + .num_links = ARRAY_SIZE(ux500_cg29xx_dai_links), + .platform = &ux500_soc_platform, +}; + +struct snd_soc_device ux500_cg29xx_drvdata = { + .card = &ux500_cg29xx, + .codec_dev = &soc_codec_dev_cg29xx, +}; + +static int __init ux500_cg29xx_soc_init(void) +{ + int err; + int i; + + for (i = 0; i < ARRAY_SIZE(ux500_cg29xx_dai_links); i++) { + pr_debug("%s: DAI-link %d, name: %s\n", + __func__, + i, + ux500_cg29xx_drvdata.card->dai_link[i].name); + } + + ux500_cg29xx_platform_device = + platform_device_alloc("soc-audio", -1); + if (!ux500_cg29xx_platform_device) + return -ENOMEM; + + platform_set_drvdata( + ux500_cg29xx_platform_device, + &ux500_cg29xx_drvdata); + + ux500_cg29xx_drvdata.dev = &ux500_cg29xx_platform_device->dev; + + err = platform_device_add(ux500_cg29xx_platform_device); + if (err) { + pr_err("%s: Error: Failed to add platform device (%s).\n", + __func__, + ux500_cg29xx_drvdata.card->name); + platform_device_put(ux500_cg29xx_platform_device); + } + + return err; +} +module_init(ux500_cg29xx_soc_init); + +static void __exit ux500_cg29xx_soc_exit(void) +{ + platform_device_unregister(ux500_cg29xx_platform_device); +} +module_exit(ux500_cg29xx_soc_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c new file mode 100644 index 00000000000..36836918a36 --- /dev/null +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -0,0 +1,961 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ola Lilja (ola.o.lilja@stericsson.com), + * Roger Nilsson (roger.xr.nilsson@stericsson.com) + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#include +#include +#include +#include "ux500_msp_dai.h" +#include "ux500_pcm.h" + +#include +#include +#include + +static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = { + { + .lock = __SPIN_LOCK_UNLOCKED(ux500_msp_dai_private[0].lock), + .i2s = NULL, + .fmt = 0, + .slots = 1, + .tx_mask = 0x01, + .rx_mask = 0x01, + .slot_width = 16, + }, + { + .lock = __SPIN_LOCK_UNLOCKED(ux500_msp_dai_private[1].lock), + .i2s = NULL, + .fmt = 0, + .slots = 1, + .tx_mask = 0x01, + .rx_mask = 0x01, + .slot_width = 16, + }, + { + .lock = __SPIN_LOCK_UNLOCKED(ux500_msp_dai_private[2].lock), + .i2s = NULL, + .fmt = 0, + .slots = 1, + .tx_mask = 0x01, + .rx_mask = 0x01, + .slot_width = 16, + }, +}; + +static int ux500_msp_dai_i2s_probe(struct i2s_device *i2s) +{ + unsigned long flags; + + pr_info("%s: Enter (chip_select = %d, i2s = %d).\n", + __func__, + (int)i2s->chip_select, (int)(i2s)); + + spin_lock_irqsave( + &ux500_msp_dai_private[i2s->chip_select].lock, + flags); + ux500_msp_dai_private[i2s->chip_select].i2s = i2s; + spin_unlock_irqrestore( + &ux500_msp_dai_private[i2s->chip_select].lock, + flags); + try_module_get(i2s->controller->dev.parent->driver->owner); + i2s_set_drvdata( + i2s, + (void *)&ux500_msp_dai_private[i2s->chip_select]); + + return 0; +} + +static int ux500_msp_dai_i2s_remove(struct i2s_device *i2s) +{ + unsigned long flags; + struct ux500_msp_dai_private *ux500_msp_dai_private = + i2s_get_drvdata(i2s); + + pr_debug("%s: Enter (chip_select = %d).\n", + __func__, + (int)i2s->chip_select); + + spin_lock_irqsave(&ux500_msp_dai_private->lock, flags); + + ux500_msp_dai_private->i2s = NULL; + i2s_set_drvdata(i2s, NULL); + spin_unlock_irqrestore( + &ux500_msp_dai_private->lock, + flags); + + pr_debug("%s: Calling module_put.\n", + __func__); + module_put(i2s->controller->dev.parent->driver->owner); + + return 0; +} + +static const struct i2s_device_id dev_id_table[] = { + { "i2s_device.0", 0, 0 }, + { "i2s_device.1", 0, 0 }, + { "i2s_device.2", 0, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2s, dev_id_table); + +static struct i2s_driver i2sdrv_i2s = { + .driver = { + .name = "ux500_asoc_i2s", + .owner = THIS_MODULE, + }, + .probe = ux500_msp_dai_i2s_probe, + .remove = __devexit_p(ux500_msp_dai_i2s_remove), + .id_table = dev_id_table, +}; + +int ux500_msp_dai_i2s_send_data(void *data, + size_t bytes, + int dai_idx) +{ + unsigned long flags; + struct ux500_msp_dai_private *dai_private = + &ux500_msp_dai_private[dai_idx]; + struct i2s_message message; + struct i2s_device *i2s_dev; + int ret = 0; + + pr_debug("%s: Enter MSP Index:%d bytes = %d).\n", + __func__, + dai_idx, + (int)bytes); + spin_lock_irqsave(&dai_private->lock, flags); + + i2s_dev = dai_private->i2s; + + if (!ux500_msp_dai[dai_idx].playback.active) { + pr_err("%s: The I2S controller is not available." + "MSP index:%d\n", + __func__, + dai_idx); + spin_unlock_irqrestore(&dai_private->lock, flags); + return ret; + } + + message.txbytes = bytes; + message.txdata = data; + message.rxbytes = 0; + message.rxdata = NULL; + message.dma_flag = 1; + + spin_unlock_irqrestore(&dai_private->lock, flags); + + ret = i2s_transfer(i2s_dev->controller, &message); + if (ret < 0) { + pr_err("%s: Error: i2s_transfer failed. MSP index: %d\n", + __func__, + dai_idx); + } + + return ret; +} + +int ux500_msp_dai_i2s_receive_data(void *data, + size_t bytes, + int dai_idx) +{ + unsigned long flags; + struct ux500_msp_dai_private *dai_private = + &ux500_msp_dai_private[dai_idx]; + struct i2s_message message; + struct i2s_device *i2s_dev; + int ret = 0; + + pr_debug("%s: Enter MSP Index: %d, bytes = %d).\n", + __func__, + dai_idx, + (int)bytes); + + spin_lock_irqsave(&dai_private->lock, flags); + + i2s_dev = dai_private->i2s; + + if (!ux500_msp_dai[dai_idx].capture.active) { + pr_err("%s: The MSP controller is not available." + "MSP index: %d\n", + __func__, + dai_idx); + spin_unlock_irqrestore(&dai_private->lock, flags); + return ret; + } + + message.rxbytes = bytes; + message.rxdata = data; + message.txbytes = 0; + message.txdata = NULL; + message.dma_flag = 1; + + spin_unlock_irqrestore(&dai_private->lock, flags); + + ret = i2s_transfer(i2s_dev->controller, &message); + if (ret < 0) { + pr_err("%s: Error: i2s_transfer failed. Msp index: %d\n", + __func__, + dai_idx); + } + + return ret; +} + +static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *msp_dai) +{ + struct ux500_msp_dai_private *dai_private = msp_dai->private_data; + + pr_info("%s: Enter (stream = %s).\n", + __func__, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "SNDRV_PCM_STREAM_PLAYBACK" : "SNDRV_PCM_STREAM_CAPTURE"); + if (dai_private == NULL) + return; + + pr_debug("%s: chip_select = %d.\n", + __func__, + (int)dai_private->i2s->chip_select); + + if (i2s_cleanup(dai_private->i2s->controller, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + DISABLE_TRANSMIT : DISABLE_RECEIVE)) { + + pr_err("%s: Error closing i2s for %s.\n", + __func__, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "playback" : "capture"); + } + return; +} + +static int ux500_msp_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *msp_dai) +{ + struct ux500_msp_dai_private *dai_private = + &ux500_msp_dai_private[msp_dai->id]; + + pr_info("%s: MSP Index: %d.\n", + __func__, + msp_dai->id); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + msp_dai->playback.active : msp_dai->capture.active) { + pr_err("%s: A %s stream is already active.\n", + __func__, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "PLAYBACK" : "CAPTURE"); + return -EBUSY; + } + + msp_dai->private_data = dai_private; + + if (dai_private->i2s == NULL) { + pr_err("%s: MSP index: %d" + "i2sdrv.i2s == NULL\n", + __func__, + msp_dai->id); + return -1; + } + + if (dai_private->i2s->controller == NULL) { + pr_err("%s: MSP index: %d" + "i2sdrv.i2s->controller == NULL.\n", + __func__, + msp_dai->id); + return -1; + } + + return 0; +} + +static void ux500_msp_dai_setup_multichannel( + struct ux500_msp_dai_private *private, + struct msp_config *msp_config) +{ + struct msp_multichannel_config *multi = + &msp_config->multichannel_config; + + if (private->slots > 1) { + msp_config->multichannel_configured = 1; + + multi->tx_multichannel_enable = true; + multi->rx_multichannel_enable = true; + multi->rx_comparison_enable_mode = MSP_COMPARISON_DISABLED; + + multi->tx_channel_0_enable = private->tx_mask; + multi->tx_channel_1_enable = 0; + multi->tx_channel_2_enable = 0; + multi->tx_channel_3_enable = 0; + + multi->rx_channel_0_enable = private->rx_mask; + multi->rx_channel_1_enable = 0; + multi->rx_channel_2_enable = 0; + multi->rx_channel_3_enable = 0; + + pr_debug("%s: Multichannel enabled." + "Slots: %d TX: %u RX: %u\n", + __func__, + private->slots, + multi->tx_channel_0_enable, + multi->rx_channel_0_enable); + } +} + +static void ux500_msp_dai_setup_frameper( + struct ux500_msp_dai_private *private, + unsigned int rate, + struct msp_protocol_desc *prot_desc) +{ + switch (private->slots) { + default: + case 1: + switch (rate) { + case 8000: + prot_desc->frame_period = + FRAME_PER_SINGLE_SLOT_8_KHZ; + break; + case 16000: + prot_desc->frame_period = + FRAME_PER_SINGLE_SLOT_16_KHZ; + break; + case 44100: + prot_desc->frame_period = + FRAME_PER_SINGLE_SLOT_44_1_KHZ; + break; + case 48000: + default: + prot_desc->frame_period = + FRAME_PER_SINGLE_SLOT_48_KHZ; + break; + } + break; + + case 2: + prot_desc->frame_period = FRAME_PER_2_SLOTS; + break; + + case 8: + prot_desc->frame_period = + FRAME_PER_8_SLOTS; + break; + + case 16: + prot_desc->frame_period = + FRAME_PER_16_SLOTS; + break; + } + + prot_desc->total_clocks_for_one_frame = + prot_desc->frame_period+1; + + pr_debug("%s: Total clocks per frame: %u\n", + __func__, + prot_desc->total_clocks_for_one_frame); +} + +static void ux500_msp_dai_setup_framing_pcm( + struct ux500_msp_dai_private *private, + unsigned int rate, + struct msp_protocol_desc *prot_desc) +{ + u32 frame_length = MSP_FRAME_LENGTH_1; + prot_desc->frame_width = 0; + + switch (private->slots) { + default: + case 1: + frame_length = MSP_FRAME_LENGTH_1; + break; + + case 2: + frame_length = MSP_FRAME_LENGTH_2; + break; + + case 8: + frame_length = MSP_FRAME_LENGTH_8; + break; + + case 16: + frame_length = MSP_FRAME_LENGTH_16; + break; + } + + prot_desc->tx_frame_length_1 = frame_length; + prot_desc->rx_frame_length_1 = frame_length; + prot_desc->tx_frame_length_2 = frame_length; + prot_desc->rx_frame_length_2 = frame_length; + + prot_desc->tx_element_length_1 = MSP_ELEM_LENGTH_16; + prot_desc->rx_element_length_1 = MSP_ELEM_LENGTH_16; + prot_desc->tx_element_length_2 = MSP_ELEM_LENGTH_16; + prot_desc->rx_element_length_2 = MSP_ELEM_LENGTH_16; + + ux500_msp_dai_setup_frameper(private, rate, prot_desc); +} + +static void ux500_msp_dai_setup_clocking( + unsigned int fmt, + struct msp_config *msp_config) +{ + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + default: + case SND_SOC_DAIFMT_NB_NF: + msp_config->tx_frame_sync_pol = + MSP_FRAME_SYNC_POL(MSP_FRAME_SYNC_POL_ACTIVE_HIGH); + msp_config->rx_frame_sync_pol = + MSP_FRAME_SYNC_POL_ACTIVE_HIGH << RFSPOL_SHIFT; + break; + + case SND_SOC_DAIFMT_NB_IF: + msp_config->tx_frame_sync_pol = + MSP_FRAME_SYNC_POL(MSP_FRAME_SYNC_POL_ACTIVE_LOW); + msp_config->rx_frame_sync_pol = + MSP_FRAME_SYNC_POL_ACTIVE_LOW << RFSPOL_SHIFT; + break; + } + + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) { + pr_debug("%s: Codec is MASTER.\n", + __func__); + + msp_config->rx_frame_sync_sel = 0; + msp_config->tx_frame_sync_sel = 1 << TFSSEL_SHIFT; + msp_config->tx_clock_sel = 0; + msp_config->rx_clock_sel = 0; + msp_config->srg_clock_sel = 0x2 << SCKSEL_SHIFT; + } else { + pr_debug("%s: Codec is SLAVE.\n", + __func__); + + msp_config->tx_clock_sel = TX_CLK_SEL_SRG; + msp_config->tx_frame_sync_sel = TX_SYNC_SRG_PROG; + msp_config->rx_clock_sel = RX_CLK_SEL_SRG; + msp_config->rx_frame_sync_sel = RX_SYNC_SRG; + msp_config->srg_clock_sel = 1 << SCKSEL_SHIFT; + } +} + +static void ux500_msp_dai_compile_prot_desc_pcm( + unsigned int fmt, + struct msp_protocol_desc *prot_desc) +{ + prot_desc->rx_phase_mode = MSP_SINGLE_PHASE; + prot_desc->tx_phase_mode = MSP_SINGLE_PHASE; + prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE; + prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE; + prot_desc->rx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + prot_desc->tx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + prot_desc->rx_data_delay = MSP_DELAY_0; + prot_desc->tx_data_delay = MSP_DELAY_0; + + if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A) { + pr_debug("%s: DSP_A.\n", + __func__); + prot_desc->tx_clock_pol = MSP_FALLING_EDGE; + prot_desc->rx_clock_pol = MSP_FALLING_EDGE; + } else { + pr_debug("%s: DSP_B.\n", + __func__); + prot_desc->tx_clock_pol = MSP_RISING_EDGE; + prot_desc->rx_clock_pol = MSP_RISING_EDGE; + } + + prot_desc->rx_half_word_swap = MSP_HWS_NO_SWAP; + prot_desc->tx_half_word_swap = MSP_HWS_NO_SWAP; + prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR; + prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR; + prot_desc->spi_clk_mode = MSP_SPI_CLOCK_MODE_NON_SPI; + prot_desc->spi_burst_mode = MSP_SPI_BURST_MODE_DISABLE; + prot_desc->frame_sync_ignore = MSP_FRAME_SYNC_IGNORE; +} + +static void ux500_msp_dai_compile_prot_desc_i2s( + struct msp_protocol_desc *prot_desc) +{ + prot_desc->rx_phase_mode = MSP_DUAL_PHASE; + prot_desc->tx_phase_mode = MSP_DUAL_PHASE; + prot_desc->rx_phase2_start_mode = + MSP_PHASE2_START_MODE_FRAME_SYNC; + prot_desc->tx_phase2_start_mode = + MSP_PHASE2_START_MODE_FRAME_SYNC; + prot_desc->rx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + prot_desc->tx_bit_transfer_format = MSP_BTF_MS_BIT_FIRST; + prot_desc->rx_data_delay = MSP_DELAY_0; + prot_desc->tx_data_delay = MSP_DELAY_0; + + prot_desc->rx_frame_length_1 = MSP_FRAME_LENGTH_1; + prot_desc->rx_frame_length_2 = MSP_FRAME_LENGTH_1; + prot_desc->tx_frame_length_1 = MSP_FRAME_LENGTH_1; + prot_desc->tx_frame_length_2 = MSP_FRAME_LENGTH_1; + prot_desc->rx_element_length_1 = MSP_ELEM_LENGTH_16; + prot_desc->rx_element_length_2 = MSP_ELEM_LENGTH_16; + prot_desc->tx_element_length_1 = MSP_ELEM_LENGTH_16; + prot_desc->tx_element_length_2 = MSP_ELEM_LENGTH_16; + + prot_desc->rx_clock_pol = MSP_RISING_EDGE; + prot_desc->tx_clock_pol = MSP_RISING_EDGE; + + prot_desc->tx_half_word_swap = MSP_HWS_NO_SWAP; + prot_desc->rx_half_word_swap = MSP_HWS_NO_SWAP; + prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR; + prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR; + prot_desc->spi_clk_mode = MSP_SPI_CLOCK_MODE_NON_SPI; + prot_desc->spi_burst_mode = MSP_SPI_BURST_MODE_DISABLE; + prot_desc->frame_sync_ignore = MSP_FRAME_SYNC_IGNORE; +} + +static void ux500_msp_dai_compile_msp_config( + struct snd_pcm_substream *substream, + struct ux500_msp_dai_private *private, + unsigned int rate, + struct msp_config *msp_config) +{ + struct msp_protocol_desc *prot_desc = &msp_config->protocol_desc; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int fmt = private->fmt; + + memset(msp_config, 0, sizeof(*msp_config)); + + msp_config->input_clock_freq = UX500_MSP_INTERNAL_CLOCK_FREQ; + msp_config->tx_fifo_config = TX_FIFO_ENABLE; + msp_config->rx_fifo_config = RX_FIFO_ENABLE; + msp_config->spi_clk_mode = SPI_CLK_MODE_NORMAL; + msp_config->spi_burst_mode = 0; + msp_config->handler = ux500_pcm_dma_eot_handler; + msp_config->tx_callback_data = + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + substream : NULL; + msp_config->rx_callback_data = + substream->stream == SNDRV_PCM_STREAM_CAPTURE ? + substream : NULL; + msp_config->def_elem_len = 1; + msp_config->direction = + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + MSP_TRANSMIT_MODE : MSP_RECEIVE_MODE; + msp_config->data_size = MSP_DATA_BITS_32; + msp_config->work_mode = MSP_DMA_MODE; + msp_config->frame_freq = rate; + + /* To avoid division by zero in I2S-driver (i2s_setup) */ + prot_desc->total_clocks_for_one_frame = 1; + + pr_debug("%s: rate: %u channels: %d.\n", + __func__, + rate, + runtime->channels); + switch (fmt & + (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { + + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: + pr_debug("%s: SND_SOC_DAIFMT_I2S.\n", + __func__); + + msp_config->default_protocol_desc = 1; + msp_config->protocol = MSP_I2S_PROTOCOL; + break; + + default: + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: + pr_debug("%s: SND_SOC_DAIFMT_I2S.\n", + __func__); + + msp_config->data_size = MSP_DATA_BITS_16; + msp_config->protocol = MSP_I2S_PROTOCOL; + + ux500_msp_dai_compile_prot_desc_i2s(prot_desc); + break; + + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM: + pr_debug("%s: PCM format.\n", + __func__); + msp_config->data_size = MSP_DATA_BITS_16; + msp_config->protocol = MSP_PCM_PROTOCOL; + + ux500_msp_dai_compile_prot_desc_pcm(fmt, prot_desc); + ux500_msp_dai_setup_multichannel(private, msp_config); + ux500_msp_dai_setup_framing_pcm(private, rate, prot_desc); + break; + } + + ux500_msp_dai_setup_clocking(fmt, msp_config); +} + +static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *msp_dai) +{ + int ret = 0; + unsigned long flags_private; + struct ux500_msp_dai_private *dai_private = msp_dai->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct msp_config msp_config; + + pr_debug("%s: Enter (stream = %p - %s, chip_select = %d).\n", + __func__, + substream, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "SNDRV_PCM_STREAM_PLAYBACK" : "SNDRV_PCM_STREAM_CAPTURE", + (int)dai_private->i2s->chip_select); + + pr_debug("%s: Setting up dai with rate %u.\n", + __func__, + runtime->rate); + spin_lock_irqsave(&dai_private->lock, flags_private); + ux500_msp_dai_compile_msp_config(substream, dai_private, + runtime->rate, &msp_config); + spin_unlock_irqrestore(&dai_private->lock, flags_private); + + ret = i2s_setup(dai_private->i2s->controller, &msp_config); + if (ret < 0) { + pr_err("u8500_msp_dai_prepare: i2s_setup failed! " + "ret = %d\n", ret); + goto cleanup; + } + +cleanup: + return ret; +} + +static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *msp_dai) +{ + unsigned int mask, slots_active; + struct ux500_msp_dai_private *private = msp_dai->private_data; + + pr_debug("%s: Enter stream: %s, MSP index: %d.\n", + __func__, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "SNDRV_PCM_STREAM_PLAYBACK" : + "SNDRV_PCM_STREAM_CAPTURE", + (int)private->i2s->chip_select); + + switch (private->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + if (params_channels(params) != 2) { + pr_err("%s: The I2S requires " + "that the channel count of the substream " + "is two. Substream channels: %d.\n", + __func__, + params_channels(params)); + return -EINVAL; + } + break; + case SND_SOC_DAIFMT_DSP_B: + case SND_SOC_DAIFMT_DSP_A: + + mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + private->tx_mask : + private->rx_mask; + + slots_active = hweight32(mask); + + pr_debug("TDM slots active: %d", slots_active); + + if (params_channels(params) != slots_active) { + pr_err("%s: The PCM format requires " + "that the channel count of the substream " + "matches the number of active slots.\n" + "Number of active slots: %d\n" + "Substream channels: %d.\n", + __func__, + slots_active, + params_channels(params)); + return -EINVAL; + } + break; + + default: + break; + } + + return 0; +} + +static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *msp_dai, + unsigned int fmt) +{ + struct ux500_msp_dai_private *dai_private = + msp_dai->private_data; + + pr_debug("%s: MSP index: %d: Enter.\n", + __func__, + (int)dai_private->i2s->chip_select); + + switch (fmt & + (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: + break; + + default: + pr_err("Unsupported DAI format (0x%x)!\n", + fmt); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + case SND_SOC_DAIFMT_NB_IF: + break; + + default: + pr_err("Unsupported DAI format (0x%x)!\n", + fmt); + return -EINVAL; + } + + dai_private->fmt = fmt; + return 0; +} + +static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, + int slot_width) +{ + struct ux500_msp_dai_private *private = + dai->private_data; + unsigned int cap; + + if (!(slots == 1 || slots == 2 || slots == 8 || slots == 16)) { + pr_err("%s - error: slots %d Supported values are 1/2/8/16.\n", + __func__, + slots); + return -EINVAL; + } + private->slots = slots; + + if (!(slot_width == 16)) { + pr_err("%s - error: slot_width %d Supported value is 16.\n", + __func__, + slot_width); + return -EINVAL; + } + private->slot_width = slot_width; + + switch (slots) { + default: + case 1: + cap = 0x01; + break; + case 2: + cap = 0x03; + break; + case 8: + cap = 0xFF; + break; + case 16: + cap = 0xFFFF; + break; + } + + private->tx_mask = tx_mask & cap; + private->rx_mask = rx_mask & cap; + + return 0; +} + +static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *msp_dai) +{ + unsigned long flags; + int ret = 0; + struct ux500_msp_dai_private *dai_private = + msp_dai->private_data; + + pr_debug("%s: Enter (stream = %p - %s," + " chip_select = %d, cmd = %d).\n", + __func__, + substream, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "SNDRV_PCM_STREAM_PLAYBACK" : + "SNDRV_PCM_STREAM_CAPTURE", + (int)dai_private->i2s->chip_select, + cmd); + + spin_lock_irqsave(&dai_private->lock, flags); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = 0; + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = 0; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + ret = 0; + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = 0; + break; + default: + ret = -EINVAL; + break; + } + + spin_unlock_irqrestore(&dai_private->lock, flags); + return ret; +} + +struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI] = { + { + .name = "ux500_i2s-0", + .id = 0, + .suspend = NULL, + .resume = NULL, + .playback = { + .channels_min = UX500_MSP_MIN_CHANNELS, + .channels_max = UX500_MSP_MAX_CHANNELS, + .rates = UX500_I2S_RATES, + .formats = UX500_I2S_FORMATS, + }, + .capture = { + .channels_min = UX500_MSP_MIN_CHANNELS, + .channels_max = UX500_MSP_MAX_CHANNELS, + .rates = UX500_I2S_RATES, + .formats = UX500_I2S_FORMATS, + }, + .ops = (struct snd_soc_dai_ops[]) { + { + .set_sysclk = NULL, + .set_fmt = ux500_msp_dai_set_dai_fmt, + .set_tdm_slot = ux500_msp_dai_set_tdm_slot, + .startup = ux500_msp_dai_startup, + .shutdown = ux500_msp_dai_shutdown, + .prepare = ux500_msp_dai_prepare, + .trigger = ux500_msp_dai_trigger, + .hw_params = ux500_msp_dai_hw_params, + } + }, + .private_data = &ux500_msp_dai_private[0], + }, + { + .name = "ux500_i2s-1", + .id = 1, + .suspend = NULL, + .resume = NULL, + .playback = { + .channels_min = UX500_MSP_MIN_CHANNELS, + .channels_max = UX500_MSP_MAX_CHANNELS, + .rates = UX500_I2S_RATES, + .formats = UX500_I2S_FORMATS, + }, + .capture = { + .channels_min = UX500_MSP_MIN_CHANNELS, + .channels_max = UX500_MSP_MAX_CHANNELS, + .rates = UX500_I2S_RATES, + .formats = UX500_I2S_FORMATS, + }, + .ops = (struct snd_soc_dai_ops[]) { + { + .set_sysclk = NULL, + .set_fmt = ux500_msp_dai_set_dai_fmt, + .set_tdm_slot = ux500_msp_dai_set_tdm_slot, + .startup = ux500_msp_dai_startup, + .shutdown = ux500_msp_dai_shutdown, + .prepare = ux500_msp_dai_prepare, + .trigger = ux500_msp_dai_trigger, + .hw_params = ux500_msp_dai_hw_params, + } + }, + .private_data = &ux500_msp_dai_private[1], + }, + { + .name = "ux500_i2s-2", + .id = 2, + .suspend = NULL, + .resume = NULL, + .playback = { + .channels_min = UX500_MSP_MIN_CHANNELS, + .channels_max = UX500_MSP_MAX_CHANNELS, + .rates = UX500_I2S_RATES, + .formats = UX500_I2S_FORMATS, + }, + .capture = { + .channels_min = UX500_MSP_MIN_CHANNELS, + .channels_max = UX500_MSP_MAX_CHANNELS, + .rates = UX500_I2S_RATES, + .formats = UX500_I2S_FORMATS, + }, + .ops = (struct snd_soc_dai_ops[]) { + { + .set_sysclk = NULL, + .set_fmt = ux500_msp_dai_set_dai_fmt, + .set_tdm_slot = ux500_msp_dai_set_tdm_slot, + .startup = ux500_msp_dai_startup, + .shutdown = ux500_msp_dai_shutdown, + .prepare = ux500_msp_dai_prepare, + .trigger = ux500_msp_dai_trigger, + .hw_params = ux500_msp_dai_hw_params, + } + }, + .private_data = &ux500_msp_dai_private[2], + }, +}; +EXPORT_SYMBOL(ux500_msp_dai); + +static int __init ux500_msp_dai_init(void) +{ + int i; + int ret = 0; + + ret = i2s_register_driver(&i2sdrv_i2s); + if (ret < 0) { + pr_err("%s: Unable to register as a I2S driver.\n", + __func__); + return ret; + } + + for (i = 0; i < UX500_NBR_OF_DAI; i++) { + pr_debug("%s: Register MSP dai %d.\n", + __func__, + i); + ret = snd_soc_register_dai(&ux500_msp_dai[i]); + if (ret < 0) { + pr_err("Error: Failed to register MSP dai %d.\n", + i); + return ret; + } + } + + return ret; +} + +static void __exit ux500_msp_dai_exit(void) +{ + int i; + + pr_debug("%s: Enter.\n", __func__); + + i2s_unregister_driver(&i2sdrv_i2s); + + for (i = 0; i < UX500_NBR_OF_DAI; i++) + snd_soc_unregister_dai(&ux500_msp_dai[i]); +} + +module_init(ux500_msp_dai_init); +module_exit(ux500_msp_dai_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h new file mode 100644 index 00000000000..0ad8b380318 --- /dev/null +++ b/sound/soc/ux500/ux500_msp_dai.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ola Lilja ola.o.lilja@stericsson.com, + * Roger Nilsson roger.xr.nilsson@stericsson.com + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef UX500_msp_dai_H +#define UX500_msp_dai_H + +#include +#include +#include + +#define UX500_NBR_OF_DAI 3 + +#define UX500_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) + +#define UX500_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) + +#define FRAME_PER_SINGLE_SLOT_8_KHZ 31 +#define FRAME_PER_SINGLE_SLOT_16_KHZ 124 +#define FRAME_PER_SINGLE_SLOT_44_1_KHZ 63 +#define FRAME_PER_SINGLE_SLOT_48_KHZ 49 +#define FRAME_PER_2_SLOTS 31 +#define FRAME_PER_8_SLOTS 138 +#define FRAME_PER_16_SLOTS 277 + +#define UX500_MSP_INTERNAL_CLOCK_FREQ 40000000; +#define UX500_MSP_MIN_CHANNELS 1 +#define UX500_MSP_MAX_CHANNELS 8 + +struct ux500_msp_dai_private { + spinlock_t lock; + struct i2s_device *i2s; + unsigned int fmt; + unsigned int tx_mask; + unsigned int rx_mask; + int slots; + int slot_width; +}; + +extern struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI]; + +int ux500_msp_dai_i2s_send_data(void *data, size_t bytes, int dai_idx); +int ux500_msp_dai_i2s_receive_data(void *data, size_t bytes, int dai_idx); + +#endif diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c new file mode 100644 index 00000000000..6a5567e1445 --- /dev/null +++ b/sound/soc/ux500/ux500_pcm.c @@ -0,0 +1,376 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ola Lilja (ola.o.lilja@stericsson.com), + * Roger Nilsson (roger.xr.nilsson@stericsson.com) + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "ux500_pcm.h" +#include "ux500_msp_dai.h" + +static struct snd_pcm_hardware ux500_pcm_hw_playback = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK, + .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK, + .channels_min = UX500_PLATFORM_MIN_CHANNELS, + .channels_max = UX500_PLATFORM_MAX_CHANNELS, + .buffer_bytes_max = UX500_PLATFORM_BUFFER_SIZE, + .period_bytes_min = UX500_PLATFORM_MIN_PERIOD_BYTES, + .period_bytes_max = PAGE_SIZE, + .periods_min = UX500_PLATFORM_BUFFER_SIZE / PAGE_SIZE, + .periods_max = UX500_PLATFORM_BUFFER_SIZE / + UX500_PLATFORM_MIN_PERIOD_BYTES +}; + +static struct snd_pcm_hardware ux500_pcm_hw_capture = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, + .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, + .channels_min = UX500_PLATFORM_MIN_CHANNELS, + .channels_max = UX500_PLATFORM_MAX_CHANNELS, + .buffer_bytes_max = UX500_PLATFORM_BUFFER_SIZE, + .period_bytes_min = UX500_PLATFORM_MIN_PERIOD_BYTES, + .period_bytes_max = PAGE_SIZE, + .periods_min = UX500_PLATFORM_BUFFER_SIZE / PAGE_SIZE, + .periods_max = UX500_PLATFORM_BUFFER_SIZE / + UX500_PLATFORM_MIN_PERIOD_BYTES +}; + +static void ux500_pcm_dma_enqueue(struct snd_pcm_substream *substream) +{ + unsigned int dma_size; + struct snd_pcm_runtime *runtime = substream->runtime; + struct ux500_pcm_private *private = substream->runtime->private_data; + + pr_debug("%s: Enter MSP Index: %d.\n", + __func__, + private->msp_id); + + dma_size = frames_to_bytes(runtime, runtime->period_size); + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ux500_msp_dai_i2s_send_data( + (void *)(runtime->dma_addr + private->offset), + dma_size, + private->msp_id); + } else{ + ux500_msp_dai_i2s_receive_data( + (void *)(runtime->dma_addr + private->offset), + dma_size, + private->msp_id); + } + + private->period++; + private->period %= runtime->periods; + private->offset = + frames_to_bytes(runtime, runtime->period_size) * + private->period; +} + +static void ux500_pcm_dma_hw_free(struct device *dev, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_dma_buffer *buf = runtime->dma_buffer_p; + + if (runtime->dma_area == NULL) + return; + + if (buf != &substream->dma_buffer) { + dma_free_coherent( + buf->dev.dev, + buf->bytes, + buf->area, + buf->addr); + kfree(runtime->dma_buffer_p); + } + + snd_pcm_set_runtime_buffer(substream, NULL); +} + +void ux500_pcm_dma_eot_handler(void *data) +{ + struct snd_pcm_substream *substream = data; + struct snd_pcm_runtime *runtime; + struct ux500_pcm_private *private; + + pr_debug("%s: Enter\n", __func__); + + if (substream) { + runtime = substream->runtime; + private = substream->runtime->private_data; + + snd_pcm_period_elapsed(substream); + + if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) + ux500_pcm_dma_enqueue(substream); + } +} +EXPORT_SYMBOL(ux500_pcm_dma_eot_handler); + +static int ux500_pcm_open(struct snd_pcm_substream *substream) +{ + int stream_id = substream->pstr->stream; + struct snd_pcm_runtime *runtime = substream->runtime; + struct ux500_pcm_private *private; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + pr_info("%s: Enter\n", __func__); + + private = kzalloc(sizeof(struct ux500_pcm_private), GFP_KERNEL); + if (private == NULL) + return -ENOMEM; + + private->msp_id = rtd->dai->cpu_dai->id; + runtime->private_data = private; + + pr_debug("%s: Setting HW-config\n", __func__); + runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? + ux500_pcm_hw_playback : ux500_pcm_hw_capture; + + return 0; +} + +static int ux500_pcm_close(struct snd_pcm_substream *substream) +{ + struct ux500_pcm_private *private = substream->runtime->private_data; + + pr_info("%s: Enter\n", __func__); + + kfree(private); + + return 0; +} + +static int ux500_pcm_hw_params( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_dma_buffer *buf = runtime->dma_buffer_p; + int ret = 0; + int size; + + pr_info("%s: Enter\n", __func__); + + size = params_buffer_bytes(hw_params); + + if (buf) { + if (buf->bytes >= size) + goto out; + ux500_pcm_dma_hw_free(NULL, substream); + } + + if (substream->dma_buffer.area != NULL && + substream->dma_buffer.bytes >= size) { + buf = &substream->dma_buffer; + } else { + buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); + if (!buf) + goto nomem; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = NULL; + buf->area = dma_alloc_coherent( + NULL, + size, + &buf->addr, + GFP_KERNEL); + buf->bytes = size; + buf->private_data = NULL; + + if (!buf->area) + goto free; + } + snd_pcm_set_runtime_buffer(substream, buf); + ret = 1; + out: + runtime->dma_bytes = size; + return ret; + + free: + kfree(buf); + nomem: + return -ENOMEM; +} + +static int ux500_pcm_hw_free(struct snd_pcm_substream *substream) +{ + pr_debug("%s: Enter\n", __func__); + + ux500_pcm_dma_hw_free(NULL, substream); + + return 0; +} + +static int ux500_pcm_prepare(struct snd_pcm_substream *substream) +{ + pr_debug("%s: Enter\n", __func__); + + return 0; +} + +static int ux500_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int i; + struct ux500_pcm_private *private = substream->runtime->private_data; + + pr_debug("%s: Enter\n", __func__); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + for (i = 0; i < UX500_PLATFORM_PERIODS_QUEUED_DMA; i++) + ux500_pcm_dma_enqueue(substream); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + case SNDRV_PCM_TRIGGER_STOP: + pr_debug("%s: SNDRV_PCM_TRIGGER_STOP\n", __func__); + private->period = 0; + break; + + default: + pr_err("%s: Invalid command in pcm trigger\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static snd_pcm_uframes_t ux500_pcm_pointer(struct snd_pcm_substream *substream) +{ + unsigned int offset; + struct snd_pcm_runtime *runtime = substream->runtime; + struct ux500_pcm_private *private = substream->runtime->private_data; + + pr_debug("%s: Enter\n", __func__); + + offset = bytes_to_frames(runtime, private->offset); + if (offset < 0 || private->offset < 0) + pr_debug("%s: Offset=%i %i\n", + __func__, + offset, + private->offset); + + return offset; +} + +static int ux500_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + pr_debug("%s: Enter.\n", __func__); + + return dma_mmap_coherent( + NULL, + vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} + +static struct snd_pcm_ops ux500_pcm_ops = { + .open = ux500_pcm_open, + .close = ux500_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = ux500_pcm_hw_params, + .hw_free = ux500_pcm_hw_free, + .prepare = ux500_pcm_prepare, + .trigger = ux500_pcm_trigger, + .pointer = ux500_pcm_pointer, + .mmap = ux500_pcm_mmap +}; + +int ux500_pcm_new(struct snd_card *card, + struct snd_soc_dai *dai, + struct snd_pcm *pcm) +{ + pr_debug("%s: pcm = %d\n", __func__, (int)pcm); + + pcm->info_flags = 0; + strcpy(pcm->name, "UX500_PCM"); + + pr_debug("%s: pcm->name = %s.\n", __func__, pcm->name); + + return 0; +} + +static void ux500_pcm_free(struct snd_pcm *pcm) +{ + pr_debug("%s: Enter\n", __func__); +} + +static int ux500_pcm_suspend(struct snd_soc_dai *dai) +{ + pr_debug("%s: Enter\n", __func__); + + return 0; +} + +static int ux500_pcm_resume(struct snd_soc_dai *dai) +{ + pr_debug("%s: Enter\n", __func__); + + return 0; +} + +struct snd_soc_platform ux500_soc_platform = { + .name = "ux500-audio", + .pcm_ops = &ux500_pcm_ops, + .pcm_new = ux500_pcm_new, + .pcm_free = ux500_pcm_free, + .suspend = ux500_pcm_suspend, + .resume = ux500_pcm_resume, +}; +EXPORT_SYMBOL(ux500_soc_platform); + +static int __init ux500_pcm_init(void) +{ + int ret; + + pr_debug("%s: Register platform.\n", __func__); + ret = snd_soc_register_platform(&ux500_soc_platform); + if (ret < 0) + pr_debug("%s: Error: Failed to register platform!\n", + __func__); + + return 0; +} + +static void __exit ux500_pcm_exit(void) +{ + snd_soc_unregister_platform(&ux500_soc_platform); +} + +module_init(ux500_pcm_init); +module_exit(ux500_pcm_exit); + +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h new file mode 100644 index 00000000000..80f050128c8 --- /dev/null +++ b/sound/soc/ux500/ux500_pcm.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ola Lilja ola.o.lilja@stericsson.com, + * Roger Nilsson roger.xr.nilsson@stericsson.com + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#ifndef UX500_PCM_H +#define UX500_PCM_H + +#include + +#define UX500_PLATFORM_BUFFER_SIZE (64*1024) + +#define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000 +#define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000 +#define UX500_PLATFORM_MIN_RATE_CAPTURE 8000 +#define UX500_PLATFORM_MAX_RATE_CAPTURE 48000 + +#define UX500_PLATFORM_MIN_CHANNELS 1 +#define UX500_PLATFORM_MAX_CHANNELS 8 +#define UX500_PLATFORM_MIN_PERIOD_BYTES 128 + +#define UX500_PLATFORM_PERIODS_QUEUED_DMA 5 + +extern struct snd_soc_platform ux500_soc_platform; + +struct ux500_pcm_private { + int msp_id; + int stream_id; + int period; + unsigned int offset; +}; + +void ux500_pcm_dma_eot_handler(void *data); + +#endif -- cgit v1.2.3 From 17b710ae31105ed9b047aa58dce41c0ae2d63969 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 25 Mar 2011 10:50:33 +0100 Subject: sound: add asoc codec support for ux500 platform This patch is based on the following work: cg29xx ASoc: The codec driver for cg29xx does now use the MFD driver for that chip. ST-Ericsson ID: 259100 Author: Roger Nilsson Ux500 ASoC: HDMI-driver in Ux500 ALSA SoC-driver. Author: Ola Lilja Add a power management scheme for AB3550 and fix bugs that hinder simultaneous playback/capture. ST-Ericsson ID: WP 259100 Author: Xie Xiaolei sound: asoc: Added codec and machine drivers for cg29xx. Author: Ola Lilja SND: sound codec ab3550 abx500 updates Author: Mattias Wallin New ASoC driver for Fairbanks. Author: Ola Lilja Signed-off-by: Mian Yousaf Kaukab Conflicts: arch/arm/mach-ux500/Kconfig-arch sound/soc/codecs/Makefile --- sound/Kconfig | 20 + sound/soc/codecs/Kconfig | 12 + sound/soc/codecs/Makefile | 6 + sound/soc/codecs/ab3550.c | 1456 +++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/ab3550.h | 336 +++++++++ sound/soc/codecs/av8100_audio.c | 334 +++++++++ sound/soc/codecs/av8100_audio.h | 22 + sound/soc/codecs/cg29xx.c | 778 +++++++++++++++++++++ sound/soc/codecs/cg29xx.h | 44 ++ 9 files changed, 3008 insertions(+) create mode 100644 sound/soc/codecs/ab3550.c create mode 100644 sound/soc/codecs/ab3550.h create mode 100644 sound/soc/codecs/av8100_audio.c create mode 100644 sound/soc/codecs/av8100_audio.h create mode 100644 sound/soc/codecs/cg29xx.c create mode 100644 sound/soc/codecs/cg29xx.h diff --git a/sound/Kconfig b/sound/Kconfig index fafe6f58eeb..1740aa5d6d3 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -48,6 +48,26 @@ choice endchoice +menu "Debug level for ux500 audio drivers" +config STM_ACODEC_DEBUG + int "STM ACODEC Debug Level" + depends on U8500_ACODEC + default 0 + help + Sets the ACODEC debug ON/OFF for U8500 SoC + * 0 OFF + * 1 ON + +config STM_ALSA_DEBUG + int "STM ALSA Debug Level" + depends on SND_U8500_ALSA || SND_U8500_ALSA_AB8500 + default 0 + help + Sets the ALSA debug ON/OFF for U8500 SoC + * 0 OFF + * 1 ON +endmenu + choice prompt "Driver mode" depends on U8500_ACODEC diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 59d8efaa17e..77410f13385 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -107,6 +107,9 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS select SND_SOC_WM9713 if SND_SOC_AC97_BUS + select SND_SOC_AB3550 + select SND_SOC_CG29XX + select SND_SOC_AV8100 help Normally ASoC codec drivers are only built if a machine driver which uses them is also built since they are only usable with a machine @@ -425,6 +428,15 @@ config SND_SOC_WM9712 config SND_SOC_WM9713 tristate +config SND_SOC_AB3550 + tristate + +config SND_SOC_CG29XX + tristate + +config SND_SOC_AV8100 + tristate + # Amp config SND_SOC_LM4857 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 6662eb0cdcc..65f9a79d8c6 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -1,4 +1,5 @@ snd-soc-88pm860x-objs := 88pm860x-codec.o +snd-soc-ab3550-objs := ab3550.o snd-soc-ac97-objs := ac97.o snd-soc-ad1836-objs := ad1836.o snd-soc-ad193x-objs := ad193x.o @@ -13,6 +14,8 @@ snd-soc-ak4535-objs := ak4535.o snd-soc-ak4641-objs := ak4641.o snd-soc-ak4642-objs := ak4642.o snd-soc-ak4671-objs := ak4671.o +snd-soc-av8100_audio-objs := av8100_audio.o +snd-soc-cg29xx-objs := cg29xx.o snd-soc-cq93vc-objs := cq93vc.o snd-soc-cs42l51-objs := cs42l51.o snd-soc-cs42l73-objs := cs42l73.o @@ -103,6 +106,7 @@ snd-soc-max9877-objs := max9877.o snd-soc-tpa6130a2-objs := tpa6130a2.o obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o +obj-$(CONFIG_SND_SOC_AB3550) += snd-soc-ab3550.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o @@ -119,6 +123,8 @@ obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o +obj-$(CONFIG_SND_SOC_AV8100) += snd-soc-av8100_audio.o +obj-$(CONFIG_SND_SOC_CG29XX) += snd-soc-cg29xx.o obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o diff --git a/sound/soc/codecs/ab3550.c b/sound/soc/codecs/ab3550.c new file mode 100644 index 00000000000..e0a4c6d7f06 --- /dev/null +++ b/sound/soc/codecs/ab3550.c @@ -0,0 +1,1456 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Xie Xiaolei , + * Roger Nilsson + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ab3550.h" + + +#define I2C_BANK 0 + +static struct device *ab3550_dev; +static struct snd_soc_codec *ab3550_codec; + +static u8 virtual_regs[] = { + 0, 0 +}; + +static void set_reg(u8 reg, u8 val) +{ + if (!ab3550_dev) { + pr_err("%s: The AB3550 codec driver not initialized.\n", + __func__); + return; + } + if (reg < AB3550_FIRST_REG) + return; + else if (reg <= AB3550_LAST_REG) { + abx500_set_register_interruptible( + ab3550_dev, I2C_BANK, reg, val); + } else if (reg - AB3550_LAST_REG - 1 < ARRAY_SIZE(virtual_regs)) { + virtual_regs[reg - AB3550_LAST_REG - 1] = val; + } +} + +static void mask_set_reg(u8 reg, u8 mask, u8 val) +{ + if (!ab3550_dev) { + pr_err("%s: The AB3550 codec driver not initialized.\n", + __func__); + return; + } + if (reg < AB3550_FIRST_REG) + return; + else if (reg <= AB3550_LAST_REG) { + abx500_mask_and_set_register_interruptible( + ab3550_dev, I2C_BANK, reg, mask, val); + } else if (reg - AB3550_LAST_REG - 1 < ARRAY_SIZE(virtual_regs)) { + virtual_regs[reg - AB3550_LAST_REG - 1] &= ~mask; + virtual_regs[reg - AB3550_LAST_REG - 1] |= val & mask; + } +} + +static u8 read_reg(u8 reg) +{ + if (!ab3550_dev) { + pr_err("%s: The AB3550 codec driver not initialized.\n", + __func__); + return 0; + } + if (reg < AB3550_FIRST_REG) + return 0; + else if (reg <= AB3550_LAST_REG) { + u8 val; + abx500_get_register_interruptible( + ab3550_dev, I2C_BANK, reg, &val); + return val; + } else if (reg - AB3550_LAST_REG - 1 < ARRAY_SIZE(virtual_regs)) + return virtual_regs[reg - AB3550_LAST_REG - 1]; + dev_warn(ab3550_dev, "%s: out-of-scope reigster %u.\n", + __func__, reg); + return 0; +} + +/* Components that can be powered up/down */ +enum enum_widget { + widget_ear = 0, + widget_auxo1, + widget_auxo2, + + widget_spkr, + widget_line1, + widget_line2, + + widget_dac1, + widget_dac2, + widget_dac3, + + widget_rx1, + widget_rx2, + widget_rx3, + + widget_mic1, + widget_mic2, + + widget_micbias1, + widget_micbias2, + + widget_apga1, + widget_apga2, + + widget_tx1, + widget_tx2, + + widget_adc1, + widget_adc2, + + widget_if0_dld_l, + widget_if0_dld_r, + widget_if0_uld_l, + widget_if0_uld_r, + widget_if1_dld_l, + widget_if1_dld_r, + widget_if1_uld_l, + widget_if1_uld_r, + + widget_mic1p1, + widget_mic1n1, + widget_mic1p2, + widget_mic1n2, + + widget_mic2p1, + widget_mic2n1, + widget_mic2p2, + widget_mic2n2, + + widget_clock, + + number_of_widgets +}; + +/* This is only meant for debugging */ +static const char *widget_names[] = { + "EAR", "AUXO1", "AUXO2", "SPKR", "LINE1", "LINE2", + "DAC1", "DAC2", "DAC3", + "RX1", "RX2", "RX3", + "MIC1", "MIC2", + "MIC-BIAS1", "MIC-BIAS2", + "APGA1", "APGA2", + "TX1", "TX2", + "ADC1", "ADC2", + "IF0-DLD-L", "IF0-DLD-R", "IF0-ULD-L", "IF0-ULD-R", + "IF1-DLD-L", "IF1-DLD-R", "IF1-ULD-L", "IF1-ULD-R", + "MIC1P1", "MIC1N1", "MIC1P2", "MIC1N2", + "MIC2P1", "MIC2N1", "MIC2P2", "MIC2N2", + "CLOCK" +}; + +struct widget_pm { + enum enum_widget widget; + u8 reg; + u8 shift; + + unsigned long source_list[BIT_WORD(number_of_widgets) + 1]; + unsigned long sink_list[BIT_WORD(number_of_widgets) + 1]; +}; + +static struct widget_pm widget_pm_array[] = { + {.widget = widget_ear, .reg = EAR, .shift = EAR_PWR_SHIFT}, + {.widget = widget_auxo1, .reg = AUXO1, .shift = AUXOx_PWR_SHIFT}, + {.widget = widget_auxo2, .reg = AUXO2, .shift = AUXOx_PWR_SHIFT}, + {.widget = widget_spkr, .reg = SPKR, .shift = SPKR_PWR_SHIFT}, + {.widget = widget_line1, .reg = LINE1, .shift = LINEx_PWR_SHIFT}, + {.widget = widget_line2, .reg = LINE2, .shift = LINEx_PWR_SHIFT}, + + {.widget = widget_dac1, .reg = RX1, .shift = DACx_PWR_SHIFT}, + {.widget = widget_dac2, .reg = RX2, .shift = DACx_PWR_SHIFT}, + {.widget = widget_dac3, .reg = RX3, .shift = DACx_PWR_SHIFT}, + + {.widget = widget_rx1, .reg = RX1, .shift = RXx_PWR_SHIFT}, + {.widget = widget_rx2, .reg = RX2, .shift = RXx_PWR_SHIFT}, + {.widget = widget_rx3, .reg = RX3, .shift = RXx_PWR_SHIFT}, + + {.widget = widget_mic1, .reg = MIC1_GAIN, .shift = MICx_PWR_SHIFT}, + {.widget = widget_mic2, .reg = MIC2_GAIN, .shift = MICx_PWR_SHIFT}, + + {.widget = widget_micbias1, .reg = MIC_BIAS1, + .shift = MBIAS_PWR_SHIFT}, + {.widget = widget_micbias2, .reg = MIC_BIAS2, + .shift = MBIAS_PWR_SHIFT}, + + {.widget = widget_apga1, .reg = ANALOG_LOOP_PGA1, + .shift = APGAx_PWR_SHIFT}, + {.widget = widget_apga2, .reg = ANALOG_LOOP_PGA2, + .shift = APGAx_PWR_SHIFT}, + + {.widget = widget_tx1, .reg = TX1, .shift = TXx_PWR_SHIFT}, + {.widget = widget_tx2, .reg = TX2, .shift = TXx_PWR_SHIFT}, + + {.widget = widget_adc1, .reg = TX1, .shift = ADCx_PWR_SHIFT}, + {.widget = widget_adc2, .reg = TX2, .shift = ADCx_PWR_SHIFT}, + + {.widget = widget_if0_dld_l, .reg = AB3550_VIRTUAL_REG1, + .shift = IF0_DLD_L_PW_SHIFT}, + {.widget = widget_if0_dld_r, .reg = AB3550_VIRTUAL_REG1, + .shift = IF0_DLD_R_PW_SHIFT}, + {.widget = widget_if0_uld_l, .reg = AB3550_VIRTUAL_REG1, + .shift = IF0_ULD_L_PW_SHIFT}, + {.widget = widget_if0_uld_r, .reg = AB3550_VIRTUAL_REG1, + .shift = IF0_ULD_R_PW_SHIFT}, + + {.widget = widget_if1_dld_l, .reg = AB3550_VIRTUAL_REG1, + .shift = IF1_DLD_L_PW_SHIFT}, + {.widget = widget_if1_dld_r, .reg = AB3550_VIRTUAL_REG1, + .shift = IF1_DLD_R_PW_SHIFT}, + {.widget = widget_if1_uld_l, .reg = AB3550_VIRTUAL_REG1, + .shift = IF1_ULD_L_PW_SHIFT}, + {.widget = widget_if1_uld_r, .reg = AB3550_VIRTUAL_REG1, + .shift = IF1_ULD_R_PW_SHIFT}, + + {.widget = widget_mic1p1, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC1P1_PW_SHIFT}, + {.widget = widget_mic1n1, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC1N1_PW_SHIFT}, + {.widget = widget_mic1p2, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC1P2_PW_SHIFT}, + {.widget = widget_mic1n2, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC1N2_PW_SHIFT}, + + {.widget = widget_mic2p1, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC2P1_PW_SHIFT}, + {.widget = widget_mic2n1, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC2N1_PW_SHIFT}, + {.widget = widget_mic2p2, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC2P2_PW_SHIFT}, + {.widget = widget_mic2n2, .reg = AB3550_VIRTUAL_REG2, + .shift = MIC2N2_PW_SHIFT}, + + {.widget = widget_clock, .reg = CLOCK, .shift = CLOCK_ENABLE_SHIFT}, +}; + +DEFINE_MUTEX(ab3550_pm_mutex); + +static struct { + enum enum_widget stack[number_of_widgets]; + int p; +} pm_stack; + +struct ab3550_dai_private { + unsigned int fmt; +}; + +#define pm_stack_as_bitmap ({ \ + unsigned long bitmap[BIT_WORD(number_of_widgets) + 1]; \ + int i; \ + memset(bitmap, 0, sizeof(bitmap)); \ + for (i = 0; i < pm_stack.p; i++) { \ + set_bit(pm_stack.stack[i], bitmap); \ + } \ + bitmap; \ + }) + +/* These are only meant to meet the obligations of DAPM */ +static const struct snd_soc_dapm_widget ab3550_dapm_widgets[] = { +}; + +static const struct snd_soc_dapm_route intercon[] = { +}; + + +static const char *enum_rx2_select[] = {"I2S0", "I2S1"}; +static const char *enum_i2s_input_select[] = { + "tri-state", "MIC1", "MIC2", "mute" +}; +static const char *enum_apga1_source[] = {"LINEIN1", "MIC1", "MIC2"}; +static const char *enum_apga2_source[] = {"LINEIN2", "MIC1", "MIC2"}; +static const char *enum_dac_side_tone[] = {"TX1", "TX2"}; +static const char *enum_dac_power_mode[] = {"100%", "75%", "55%"}; +static const char *enum_ear_power_mode[] = {"100%", "70%"}; +static const char *enum_auxo_power_mode[] = { + "100%", "67%", "50%", "25%", "auto" +}; +static const char *enum_onoff[] = {"Off", "On"}; +static const char *enum_mbias_hiz_option[] = {"GND", "HiZ"}; +static const char *enum_mbias2_output_voltage[] = {"2.0v", "2.2v"}; +static const char *enum_mic_input_impedance[] = { + "12.5 kohm", "25 kohm", "50 kohm" +}; +static const char *enum_hp_filter[] = {"HP3", "HP1", "bypass"}; +static const char *enum_i2s_word_length[] = {"16 bits", "24 bits"}; +static const char *enum_i2s_mode[] = {"Master Mode", "Slave Mode"}; +static const char *enum_i2s_tristate[] = {"Normal", "Tri-state"}; +static const char *enum_optional_resistor[] = {"disconnected", "connected"}; +static const char *enum_i2s_sample_rate[] = { + "8 kHz", "16 kHz", "44.1 kHz", "48 kHz" +}; +static const char *enum_signal_inversion[] = {"normal", "inverted"}; + +/* RX2 Select */ +static struct soc_enum soc_enum_rx2_select = + SOC_ENUM_SINGLE(RX2, 4, ARRAY_SIZE(enum_rx2_select), enum_rx2_select); + +/* I2S0 Input Select */ +static struct soc_enum soc_enum_i2s0_input_select = + SOC_ENUM_DOUBLE(INTERFACE0_DATA, 0, 2, + ARRAY_SIZE(enum_i2s_input_select), + enum_i2s_input_select); +/* I2S1 Input Select */ +static struct soc_enum soc_enum_i2s1_input_select = + SOC_ENUM_DOUBLE(INTERFACE1_DATA, 0, 2, + ARRAY_SIZE(enum_i2s_input_select), + enum_i2s_input_select); + +/* APGA1 Source */ +static struct soc_enum soc_enum_apga1_source = + SOC_ENUM_SINGLE(ANALOG_LOOP_PGA1, APGAx_MUX_SHIFT, + ARRAY_SIZE(enum_apga1_source), enum_apga1_source); + +/* APGA2 Source */ +static struct soc_enum soc_enum_apga2_source = + SOC_ENUM_SINGLE(ANALOG_LOOP_PGA2, APGAx_MUX_SHIFT, + ARRAY_SIZE(enum_apga2_source), enum_apga2_source); + +static struct soc_enum soc_enum_apga1_enable = + SOC_ENUM_SINGLE(ANALOG_LOOP_PGA1, APGAx_PWR_SHIFT, + ARRAY_SIZE(enum_onoff), enum_onoff); + +static struct soc_enum soc_enum_apga2_enable = + SOC_ENUM_SINGLE(ANALOG_LOOP_PGA2, APGAx_PWR_SHIFT, + ARRAY_SIZE(enum_onoff), enum_onoff); + +/* DAC1 Side Tone */ +static struct soc_enum soc_enum_dac1_side_tone = + SOC_ENUM_SINGLE(SIDETONE1_PGA, STx_MUX_SHIFT, + ARRAY_SIZE(enum_dac_side_tone), enum_dac_side_tone); + +/* DAC2 Side Tone */ +static struct soc_enum soc_enum_dac2_side_tone = + SOC_ENUM_SINGLE(SIDETONE2_PGA, STx_MUX_SHIFT, + ARRAY_SIZE(enum_dac_side_tone), enum_dac_side_tone); + +/* DAC1 Power Mode */ +static struct soc_enum soc_enum_dac1_power_mode = + SOC_ENUM_SINGLE(RX1, DACx_PWR_MODE_SHIFT, + ARRAY_SIZE(enum_dac_power_mode), enum_dac_power_mode); + +/* DAC2 Power Mode */ +static struct soc_enum soc_enum_dac2_power_mode = + SOC_ENUM_SINGLE(RX2, DACx_PWR_MODE_SHIFT, + ARRAY_SIZE(enum_dac_power_mode), enum_dac_power_mode); + +/* DAC3 Power Mode */ +static struct soc_enum soc_enum_dac3_power_mode = + SOC_ENUM_SINGLE(RX3, DACx_PWR_MODE_SHIFT, + ARRAY_SIZE(enum_dac_power_mode), enum_dac_power_mode); + +/* EAR Power Mode */ +static struct soc_enum soc_enum_ear_power_mode = + SOC_ENUM_SINGLE(EAR, EAR_PWR_MODE_SHIFT, + ARRAY_SIZE(enum_ear_power_mode), enum_ear_power_mode); + +/* AUXO Power Mode */ +static struct soc_enum soc_enum_auxo_power_mode = + SOC_ENUM_SINGLE(AUXO_PWR_MODE, AUXO_PWR_MODE_SHIFT, + ARRAY_SIZE(enum_auxo_power_mode), + enum_auxo_power_mode); + +/* MBIAS1 HiZ Option */ +static struct soc_enum soc_enum_mbias1_hiz_option = + SOC_ENUM_SINGLE(MIC_BIAS1, MBIAS_PDN_IMP_SHIFT, + ARRAY_SIZE(enum_mbias_hiz_option), + enum_mbias_hiz_option); + +/* MBIAS1 HiZ Option */ +static struct soc_enum soc_enum_mbias2_hiz_option = + SOC_ENUM_SINGLE(MIC_BIAS2, MBIAS_PDN_IMP_SHIFT, + ARRAY_SIZE(enum_mbias_hiz_option), + enum_mbias_hiz_option); + +/* MBIAS2 Output voltage */ +static struct soc_enum soc_enum_mbias2_output_voltage = + SOC_ENUM_SINGLE(MIC_BIAS2, MBIAS2_OUT_V_SHIFT, + ARRAY_SIZE(enum_mbias2_output_voltage), + enum_mbias2_output_voltage); + +static struct soc_enum soc_enum_mbias2_internal_resistor = + SOC_ENUM_SINGLE(MIC_BIAS2_VAD, MBIAS2_R_INT_SHIFT, + ARRAY_SIZE(enum_optional_resistor), + enum_optional_resistor); + +static struct soc_enum soc_enum_mic1_input_impedance = + SOC_ENUM_SINGLE(MIC1_GAIN, MICx_IN_IMP_SHIFT, + ARRAY_SIZE(enum_mic_input_impedance), + enum_mic_input_impedance); + +static struct soc_enum soc_enum_mic2_input_impedance = + SOC_ENUM_SINGLE(MIC2_GAIN, MICx_IN_IMP_SHIFT, + ARRAY_SIZE(enum_mic_input_impedance), + enum_mic_input_impedance); + +static struct soc_enum soc_enum_tx1_hp_filter = + SOC_ENUM_SINGLE(TX1, TXx_HP_FILTER_SHIFT, + ARRAY_SIZE(enum_hp_filter), + enum_hp_filter); + +static struct soc_enum soc_enum_tx2_hp_filter = + SOC_ENUM_SINGLE(TX2, TXx_HP_FILTER_SHIFT, + ARRAY_SIZE(enum_hp_filter), + enum_hp_filter); + +static struct soc_enum soc_enum_st1_hp_filter = + SOC_ENUM_SINGLE(SIDETONE1_PGA, STx_HP_FILTER_SHIFT, + ARRAY_SIZE(enum_hp_filter), + enum_hp_filter); + +static struct soc_enum soc_enum_st2_hp_filter = + SOC_ENUM_SINGLE(SIDETONE2_PGA, STx_HP_FILTER_SHIFT, + ARRAY_SIZE(enum_hp_filter), + enum_hp_filter); + +static struct soc_enum soc_enum_i2s0_word_length = + SOC_ENUM_SINGLE(INTERFACE0, I2Sx_WORDLENGTH_SHIFT, + ARRAY_SIZE(enum_i2s_word_length), + enum_i2s_word_length); + +static struct soc_enum soc_enum_i2s1_word_length = + SOC_ENUM_SINGLE(INTERFACE1, I2Sx_WORDLENGTH_SHIFT, + ARRAY_SIZE(enum_i2s_word_length), + enum_i2s_word_length); + +static struct soc_enum soc_enum_i2s0_mode = + SOC_ENUM_SINGLE(INTERFACE0, I2Sx_MODE_SHIFT, + ARRAY_SIZE(enum_i2s_mode), + enum_i2s_mode); + +static struct soc_enum soc_enum_i2s1_mode = + SOC_ENUM_SINGLE(INTERFACE1, I2Sx_MODE_SHIFT, + ARRAY_SIZE(enum_i2s_mode), + enum_i2s_mode); + +static struct soc_enum soc_enum_i2s0_tristate = + SOC_ENUM_SINGLE(INTERFACE0, I2Sx_TRISTATE_SHIFT, + ARRAY_SIZE(enum_i2s_tristate), + enum_i2s_tristate); + +static struct soc_enum soc_enum_i2s1_tristate = + SOC_ENUM_SINGLE(INTERFACE1, I2Sx_TRISTATE_SHIFT, + ARRAY_SIZE(enum_i2s_tristate), + enum_i2s_tristate); + +static struct soc_enum soc_enum_i2s0_pulldown_resistor = + SOC_ENUM_SINGLE(INTERFACE0, I2Sx_PULLDOWN_SHIFT, + ARRAY_SIZE(enum_optional_resistor), + enum_optional_resistor); + +static struct soc_enum soc_enum_i2s1_pulldown_resistor = + SOC_ENUM_SINGLE(INTERFACE1, I2Sx_PULLDOWN_SHIFT, + ARRAY_SIZE(enum_optional_resistor), + enum_optional_resistor); + +static struct soc_enum soc_enum_i2s0_sample_rate = + SOC_ENUM_SINGLE(INTERFACE0, I2Sx_SR_SHIFT, + ARRAY_SIZE(enum_i2s_sample_rate), + enum_i2s_sample_rate); + +static struct soc_enum soc_enum_i2s1_sample_rate = + SOC_ENUM_SINGLE(INTERFACE1, I2Sx_SR_SHIFT, + ARRAY_SIZE(enum_i2s_sample_rate), + enum_i2s_sample_rate); + +static struct soc_enum soc_enum_line1_inversion = + SOC_ENUM_SINGLE(LINE1, LINEx_INV_SHIFT, + ARRAY_SIZE(enum_signal_inversion), + enum_signal_inversion); + +static struct soc_enum soc_enum_line2_inversion = + SOC_ENUM_SINGLE(LINE2, LINEx_INV_SHIFT, + ARRAY_SIZE(enum_signal_inversion), + enum_signal_inversion); + +static struct soc_enum soc_enum_auxo1_inversion = + SOC_ENUM_SINGLE(AUXO1, AUXOx_INV_SHIFT, + ARRAY_SIZE(enum_signal_inversion), + enum_signal_inversion); + +static struct soc_enum soc_enum_auxo2_inversion = + SOC_ENUM_SINGLE(AUXO1, AUXOx_INV_SHIFT, + ARRAY_SIZE(enum_signal_inversion), + enum_signal_inversion); + +static struct soc_enum soc_enum_auxo1_pulldown_resistor = + SOC_ENUM_SINGLE(AUXO1, AUXOx_PULLDOWN_SHIFT, + ARRAY_SIZE(enum_optional_resistor), + enum_optional_resistor); + +static struct soc_enum soc_enum_auxo2_pulldown_resistor = + SOC_ENUM_SINGLE(AUXO1, AUXOx_PULLDOWN_SHIFT, + ARRAY_SIZE(enum_optional_resistor), + enum_optional_resistor); + +static struct snd_kcontrol_new ab3550_snd_controls[] = { + /* RX Routing */ + SOC_ENUM("RX2 Select", soc_enum_rx2_select), + SOC_SINGLE("LINE1 Adder", LINE1_ADDER, 0, 0x07, 0), + SOC_SINGLE("LINE2 Adder", LINE2_ADDER, 0, 0x07, 0), + SOC_SINGLE("EAR Adder", EAR_ADDER, 0, 0x07, 0), + SOC_SINGLE("SPKR Adder", SPKR_ADDER, 0, 0x07, 0), + SOC_SINGLE("AUXO1 Adder", AUXO1_ADDER, 0, 0x07, 0), + SOC_SINGLE("AUXO2 Adder", AUXO2_ADDER, 0, 0x07, 0), + /* TX Routing */ + SOC_SINGLE("MIC1 Input Select", MIC1_INPUT_SELECT, 0, 0xff, 0), + SOC_SINGLE("MIC2 Input Select", MIC1_INPUT_SELECT, 0, 0xff, 0), + SOC_SINGLE("MIC2 to MIC1", MIC2_TO_MIC1, 0, 0x03, 0), + SOC_ENUM("I2S0 Input Select", soc_enum_i2s0_input_select), + SOC_ENUM("I2S1 Input Select", soc_enum_i2s1_input_select), + /* Routing of Side Tone and Analop Loop */ + SOC_ENUM("APGA1 Source", soc_enum_apga1_source), + SOC_ENUM("APGA2 Source", soc_enum_apga2_source), + SOC_ENUM("APGA1 Enable", soc_enum_apga1_enable), + SOC_ENUM("APGA2 Enable", soc_enum_apga2_enable), + SOC_SINGLE("APGA1 Destination", APGA1_ADDER, 0, 0x3f, 0), + SOC_SINGLE("APGA2 Destination", APGA2_ADDER, 0, 0x3f, 0), + SOC_ENUM("DAC1 Side Tone", soc_enum_dac1_side_tone), + SOC_ENUM("DAC2 Side Tone", soc_enum_dac2_side_tone), + /* RX Volume Control */ + SOC_SINGLE("RX-DPGA1 Gain", RX1_DIGITAL_PGA, 0, 0x43, 0), + SOC_SINGLE("RX-DPGA2 Gain", RX1_DIGITAL_PGA, 0, 0x43, 0), + SOC_SINGLE("RX-DPGA3 Gain", RX3_DIGITAL_PGA, 0, 0x43, 0), + SOC_SINGLE("LINE1 Gain", LINE1, LINEx_GAIN_SHIFT, 0x0a, 0), + SOC_SINGLE("LINE2 Gain", LINE2, LINEx_GAIN_SHIFT, 0x0a, 0), + SOC_SINGLE("SPKR Gain", SPKR, SPKR_GAIN_SHIFT, 0x16, 0), + SOC_SINGLE("EAR Gain", EAR, EAR_GAIN_SHIFT, 0x0e, 0), + SOC_SINGLE("AUXO1 Gain", AUXO1, AUXOx_GAIN_SHIFT, 0x0c, 0), + SOC_SINGLE("AUXO2 Gain", AUXO2, AUXOx_GAIN_SHIFT, 0x0c, 0), + /* TX Volume Control */ + SOC_SINGLE("MIC1 Gain", MIC1_GAIN, MICx_GAIN_SHIFT, 0x0a, 0), + SOC_SINGLE("MIC2 Gain", MIC2_GAIN, MICx_GAIN_SHIFT, 0x0a, 0), + SOC_SINGLE("TX-DPGA1 Gain", TX_DIGITAL_PGA1, TXDPGAx_SHIFT, 0x0f, 0), + SOC_SINGLE("TX-DPGA2 Gain", TX_DIGITAL_PGA2, TXDPGAx_SHIFT, 0x0f, 0), + /* Volume Control of Side Tone and Analog Loop */ + SOC_SINGLE("ST-PGA1 Gain", SIDETONE1_PGA, STx_PGA_SHIFT, 0x0a, 0), + SOC_SINGLE("ST-PGA2 Gain", SIDETONE2_PGA, STx_PGA_SHIFT, 0x0a, 0), + SOC_SINGLE("APGA1 Gain", ANALOG_LOOP_PGA1, APGAx_GAIN_SHIFT, 0x1d, 0), + SOC_SINGLE("APGA2 Gain", ANALOG_LOOP_PGA2, APGAx_GAIN_SHIFT, 0x1d, 0), + /* RX Properties */ + SOC_ENUM("DAC1 Power Mode", soc_enum_dac1_power_mode), + SOC_ENUM("DAC2 Power Mode", soc_enum_dac2_power_mode), + SOC_ENUM("DAC3 Power Mode", soc_enum_dac3_power_mode), + SOC_ENUM("EAR Power Mode", soc_enum_ear_power_mode), + SOC_ENUM("AUXO Power Mode", soc_enum_auxo_power_mode), + SOC_ENUM("LINE1 Inversion", soc_enum_line1_inversion), + SOC_ENUM("LINE2 Inversion", soc_enum_line2_inversion), + SOC_ENUM("AUXO1 Inversion", soc_enum_auxo1_inversion), + SOC_ENUM("AUXO2 Inversion", soc_enum_auxo2_inversion), + SOC_ENUM("AUXO1 Pulldown Resistor", soc_enum_auxo1_pulldown_resistor), + SOC_ENUM("AUXO2 Pulldown Resistor", soc_enum_auxo2_pulldown_resistor), + /* TX Properties */ + SOC_SINGLE("MIC1 VMID", MIC1_VMID_SELECT, 0, 0xff, 0), + SOC_SINGLE("MIC2 VMID", MIC2_VMID_SELECT, 0, 0xff, 0), + SOC_ENUM("MBIAS1 HiZ Option", soc_enum_mbias1_hiz_option), + SOC_ENUM("MBIAS2 HiZ Option", soc_enum_mbias2_hiz_option), + SOC_ENUM("MBIAS2 Output Voltage", soc_enum_mbias2_output_voltage), + SOC_ENUM("MBIAS2 Internal Resistor", soc_enum_mbias2_internal_resistor), + SOC_ENUM("MIC1 Input Impedance", soc_enum_mic1_input_impedance), + SOC_ENUM("MIC2 Input Impedance", soc_enum_mic2_input_impedance), + SOC_ENUM("TX1 HP Filter", soc_enum_tx1_hp_filter), + SOC_ENUM("TX2 HP Filter", soc_enum_tx2_hp_filter), + /* Side Tone and Analog Loop Properties */ + SOC_ENUM("ST1 HP Filter", soc_enum_st1_hp_filter), + SOC_ENUM("ST2 HP Filter", soc_enum_st2_hp_filter), + /* I2S Interface Properties */ + SOC_ENUM("I2S0 Word Length", soc_enum_i2s0_word_length), + SOC_ENUM("I2S1 Word Length", soc_enum_i2s1_word_length), + SOC_ENUM("I2S0 Mode", soc_enum_i2s0_mode), + SOC_ENUM("I2S1 Mode", soc_enum_i2s1_mode), + SOC_ENUM("I2S0 tri-state", soc_enum_i2s0_tristate), + SOC_ENUM("I2S1 tri-state", soc_enum_i2s1_tristate), + SOC_ENUM("I2S0 Pulldown Resistor", soc_enum_i2s0_pulldown_resistor), + SOC_ENUM("I2S1 Pulldown Resistor", soc_enum_i2s1_pulldown_resistor), + SOC_ENUM("I2S0 Sample Rate", soc_enum_i2s0_sample_rate), + SOC_ENUM("I2S1 Sample Rate", soc_enum_i2s1_sample_rate), + SOC_SINGLE("Interface Loop", INTERFACE_LOOP, 0, 0x0f, 0), + SOC_SINGLE("Interface Swap", INTERFACE_SWAP, 0, 0x1f, 0), + /* Miscellaneous */ + SOC_SINGLE("Negative Charge Pump", NEGATIVE_CHARGE_PUMP, 0, 0x03, 0) +}; + +/* count the number of 1 */ +#define count_ones(x) ({ \ + int num; \ + for (num = 0; x; (x) &= (x) - 1, num++) \ + ; \ + num; \ + }) + +enum enum_power { + POWER_OFF = 0, + POWER_ON = 1 +}; + +enum enum_link { + UNLINK = 0, + LINK = 1 +}; + +static unsigned int ab3550_read_reg(struct snd_soc_codec *codec, + unsigned int reg); + +static enum enum_power get_widget_power_status(enum enum_widget widget) +{ + u8 val; + + if (widget >= number_of_widgets) + return POWER_OFF; + val = read_reg(widget_pm_array[widget].reg); + if (val & (1 << widget_pm_array[widget].shift)) + return POWER_ON; + else + return POWER_OFF; +} + +static int count_powered_neighbors(const unsigned long *neighbors) +{ + unsigned long i; + int n = 0; + for_each_set_bit(i, neighbors, number_of_widgets) { + if (get_widget_power_status(i) == POWER_ON) + n++; + } + return n; +} + +static int has_powered_neighbors(const unsigned long *neighbors) +{ + unsigned int i; + for_each_set_bit(i, neighbors, number_of_widgets) { + if (get_widget_power_status(i) == POWER_ON) + return 1; + } + return 0; +} + + +static int has_stacked_neighbors(const unsigned long *neighbors) +{ + unsigned long *stack_map = pm_stack_as_bitmap; + return bitmap_intersects(stack_map, neighbors, number_of_widgets); +} + +static void power_widget_unlocked(enum enum_power onoff, + enum enum_widget widget) +{ + enum enum_widget w; + int done; + + if (widget >= number_of_widgets) + return; + if (get_widget_power_status(widget) == onoff) + return; + + for (w = widget, done = 0; !done;) { + unsigned long i; + unsigned long *srcs = widget_pm_array[w].source_list; + unsigned long *sinks = widget_pm_array[w].sink_list; + + dev_dbg(ab3550_dev, "%s: processing widget %s.\n", + __func__, widget_names[w]); + if (onoff == POWER_ON && + !bitmap_empty(srcs, number_of_widgets) && + !has_powered_neighbors(srcs)) { + pm_stack.stack[pm_stack.p++] = w; + for_each_set_bit(i, srcs, number_of_widgets) { + pm_stack.stack[pm_stack.p++] = i; + } + w = pm_stack.stack[--pm_stack.p]; + continue; + } else if (onoff == POWER_OFF && + has_powered_neighbors(sinks)) { + int n = 0; + pm_stack.stack[pm_stack.p++] = w; + for_each_set_bit(i, sinks, number_of_widgets) { + if (count_powered_neighbors( + widget_pm_array[i].source_list) + == 1 && + get_widget_power_status(i) == POWER_ON) { + pm_stack.stack[pm_stack.p++] = i; + n++; + } + } + if (n) { + w = pm_stack.stack[--pm_stack.p]; + continue; + } else + --pm_stack.p; + } + mask_set_reg(widget_pm_array[w].reg, + 1 << widget_pm_array[w].shift, + onoff == POWER_ON ? 0xff : 0); + dev_dbg(ab3550_dev, "%s: widget %s powered %s.\n", + __func__, widget_names[w], + onoff == POWER_ON ? "on" : "off"); + + if (onoff == POWER_ON && + !bitmap_empty(sinks, number_of_widgets) && + !has_powered_neighbors(sinks) && + !has_stacked_neighbors(sinks)) { + for_each_set_bit(i, sinks, number_of_widgets) { + pm_stack.stack[pm_stack.p++] = i; + } + w = pm_stack.stack[--pm_stack.p]; + continue; + } else if (onoff == POWER_OFF) { + for_each_set_bit(i, srcs, number_of_widgets) { + if (!has_powered_neighbors( + widget_pm_array[i].sink_list) + && get_widget_power_status(i) == POWER_ON + && !test_bit(i, pm_stack_as_bitmap)) { + pm_stack.stack[pm_stack.p++] = i; + } + } + } + if (pm_stack.p > 0) + w = pm_stack.stack[--pm_stack.p]; + else + done = 1; + } +} + +static void power_widget_locked(enum enum_power onoff, + enum enum_widget widget) +{ + if (mutex_lock_interruptible(&ab3550_pm_mutex)) { + dev_warn(ab3550_dev, + "%s: Signal received while waiting on the PM mutex.\n", + __func__); + return; + } + power_widget_unlocked(onoff, widget); + mutex_unlock(&ab3550_pm_mutex); +} + +static void dump_registers(const char *where, ...) +{ + va_list ap; + va_start(ap, where); + do { + short reg = va_arg(ap, int); + if (reg < 0) + break; + dev_dbg(ab3550_dev, "%s from %s> 0x%02X : 0x%02X.\n", + __func__, where, reg, read_reg(reg)); + } while (1); + va_end(ap); +} + +/** + * update the link between two widgets. + * @op: 1 - connect; 0 - disconnect + * @src: source of the connection + * @sink: sink of the connection + */ +static int update_widgets_link(enum enum_link op, enum enum_widget src, + enum enum_widget sink, + u8 reg, u8 mask, u8 newval) +{ + int ret = 0; + + if (mutex_lock_interruptible(&ab3550_pm_mutex)) { + dev_warn(ab3550_dev, "%s: A signal is received while waiting on" + " the PM mutex.\n", __func__); + return -EINTR; + } + + switch (op << 2 | test_bit(sink, widget_pm_array[src].sink_list) << 1 | + test_bit(src, widget_pm_array[sink].source_list)) { + case 3: /* UNLINK, sink in sink_list, src in source_list */ + case 4: /* LINK, sink not in sink_list, src not in source_list */ + break; + default: + ret = -EINVAL; + goto end; + } + switch (((int)op) << 2 | get_widget_power_status(src) << 1 | + get_widget_power_status(sink)) { + case 3: /* op = 0, src on, sink on */ + if (count_powered_neighbors(widget_pm_array[sink].source_list) + == 1) + power_widget_unlocked(POWER_OFF, sink); + mask_set_reg(reg, mask, newval); + break; + case 6: /* op = 1, src on, sink off */ + mask_set_reg(reg, mask, newval); + power_widget_unlocked(POWER_ON, sink); + break; + default: + /* op = 0, src off, sink off */ + /* op = 0, src off, sink on */ + /* op = 0, src on, sink off */ + /* op = 1, src off, sink off */ + /* op = 1, src off, sink on */ + /* op = 1, src on, sink on */ + mask_set_reg(reg, mask, newval); + } + change_bit(sink, widget_pm_array[src].sink_list); + change_bit(src, widget_pm_array[sink].source_list); +end: + mutex_unlock(&ab3550_pm_mutex); + return ret; +}; + +static enum enum_widget apga_source_translate(u8 reg_value) +{ + switch (reg_value) { + case 1: + return widget_mic1; + case 2: + return widget_mic2; + default: + return number_of_widgets; + } +} + +static enum enum_widget adder_sink_translate(u8 reg) +{ + switch (reg) { + case EAR_ADDER: + return widget_ear; + case AUXO1_ADDER: + return widget_auxo1; + case AUXO2_ADDER: + return widget_auxo2; + case SPKR_ADDER: + return widget_spkr; + case LINE1_ADDER: + return widget_line1; + case LINE2_ADDER: + return widget_line2; + case APGA1_ADDER: + return widget_apga1; + case APGA2_ADDER: + return widget_apga2; + default: + return number_of_widgets; + } +} + +/** + This function is only called by the SOC framework to + set registers associated to the mixer controls. +*/ +static int ab3550_write_reg(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + if (reg < MIC_BIAS1 || reg > INTERFACE_SWAP) + return -EINVAL; + switch (reg) { + u8 diff, oldval; + case ANALOG_LOOP_PGA1: + case ANALOG_LOOP_PGA2: { + enum enum_widget apga = reg == ANALOG_LOOP_PGA1 ? + widget_apga1 : widget_apga2; + + oldval = read_reg(reg); + diff = value ^ oldval; + + /* The APGA is to be turned on/off. + The power bit and the other bits in the + same register won't be changed at the same time + since they belong to different controls. + */ + if (diff & (1 << APGAx_PWR_SHIFT)) { + power_widget_locked(value >> APGAx_PWR_SHIFT & 1, + apga); + } else if (diff & APGAx_MUX_MASK) { + enum enum_widget old_source = + apga_source_translate(oldval); + enum enum_widget new_source = + apga_source_translate(value); + update_widgets_link(UNLINK, old_source, apga, + reg, APGAx_MUX_MASK, 0); + update_widgets_link(LINK, new_source, apga, + reg, APGAx_MUX_MASK, value); + } else { + set_reg(reg, value); + } + break; + } + + case APGA1_ADDER: + case APGA2_ADDER: { + int i; + enum enum_widget apga; + enum enum_widget apga_dst[] = { + widget_auxo2, widget_auxo1, widget_ear, widget_spkr, + widget_line2, widget_line1 + }; + + apga = adder_sink_translate(reg); + oldval = read_reg(reg); + diff = value ^ oldval; + for (i = 0; diff; i++) { + if (!(diff & 1 << i)) + continue; + diff ^= 1 << i; + update_widgets_link(value >> i & 1, apga, apga_dst[i], + reg, 1 << i, value); + } + break; + } + + case EAR_ADDER: + case AUXO1_ADDER: + case AUXO2_ADDER: + case SPKR_ADDER: + case LINE1_ADDER: + case LINE2_ADDER: { + int i; + enum enum_widget widgets[] = { + widget_dac1, widget_dac2, widget_dac3, + }; + oldval = read_reg(reg); + diff = value ^ oldval; + for (i = 0; diff; i++) { + if (!(diff & 1 << i)) + continue; + diff ^= 1 << i; + update_widgets_link(value >> i & 1, widgets[i], + adder_sink_translate(reg), + reg, 1 << i, value); + } + break; + } + + default: + set_reg(reg, value); + } + return 0; +} + +static unsigned int ab3550_read_reg(struct snd_soc_codec *codec, + unsigned int reg) +{ + return read_reg(reg); +} + +static int ab3550_add_widgets(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, ab3550_dapm_widgets, + ARRAY_SIZE(ab3550_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); + + snd_soc_dapm_new_widgets(codec); + return 0; +} + +static void power_for_playback(enum enum_power onoff, int ifsel) +{ + dev_dbg(ab3550_dev, "%s: interface %d power %s.\n", __func__, + ifsel, onoff == POWER_ON ? "on" : "off"); + if (mutex_lock_interruptible(&ab3550_pm_mutex)) { + dev_warn(ab3550_dev, + "%s: Signal received while waiting on the PM mutex.\n", + __func__); + return; + } + power_widget_unlocked(onoff, ifsel == 0 ? + widget_if0_dld_l : widget_if1_dld_l); + power_widget_unlocked(onoff, ifsel == 0 ? + widget_if0_dld_r : widget_if1_dld_r); + mutex_unlock(&ab3550_pm_mutex); +} + +static void power_for_capture(enum enum_power onoff, int ifsel) +{ + dev_dbg(ab3550_dev, "%s: interface %d power %s", __func__, + ifsel, onoff == POWER_ON ? "on" : "off"); + if (mutex_lock_interruptible(&ab3550_pm_mutex)) { + dev_warn(ab3550_dev, + "%s: Signal received while waiting on the PM mutex.\n", + __func__); + return; + } + power_widget_unlocked(onoff, ifsel == 0 ? + widget_if0_uld_l : widget_if1_uld_l); + power_widget_unlocked(onoff, ifsel == 0 ? + widget_if0_uld_r : widget_if1_uld_r); + mutex_unlock(&ab3550_pm_mutex); +} + +static int ab3550_add_controls(struct snd_soc_codec *codec) +{ + int err = 0, i, n = ARRAY_SIZE(ab3550_snd_controls); + + pr_debug("%s: %s called.\n", __FILE__, __func__); + for (i = 0; i < n; i++) { + err = snd_ctl_add(codec->card, snd_ctl_new1( + &ab3550_snd_controls[i], codec)); + if (err < 0) { + pr_err("%s failed to add control No.%d of %d.\n", + __func__, i, n); + return err; + } + } + return err; +} + +static int ab3550_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params, + struct snd_soc_dai *dai) +{ + u8 val; + u8 reg = dai->id == 0 ? INTERFACE0 : INTERFACE1; + + if (!ab3550_dev) { + pr_err("%s: The AB3550 codec driver not initialized.\n", + __func__); + return -EAGAIN; + } + dev_info(ab3550_dev, "%s called.\n", __func__); + switch (params_rate(hw_params)) { + case 8000: + val = I2Sx_SR_8000Hz; + break; + case 16000: + val = I2Sx_SR_16000Hz; + break; + case 44100: + val = I2Sx_SR_44100Hz; + break; + case 48000: + val = I2Sx_SR_48000Hz; + break; + default: + return -EINVAL; + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + !dai->capture.active : !dai->playback.active) { + + mask_set_reg(reg, I2Sx_SR_MASK, val << I2Sx_SR_SHIFT); + if ((read_reg(reg) & I2Sx_MODE_MASK) == 0) { + mask_set_reg(reg, MASTER_GENx_PWR_MASK, + 1 << MASTER_GENx_PWR_SHIFT); + } + } + return 0; +} + +static int ab3550_pcm_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + dai->playback.active : dai->capture.active) { + + dev_err(ab3550_dev, "%s: A %s stream is already active.\n", + __func__, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "PLAYBACK" : "CAPTURE"); + return -EBUSY; + } + return 0; +} +static int ab3550_pcm_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + dev_info(ab3550_dev, "%s called.\n", __func__); + + /* Configure registers for either playback or capture */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + power_for_playback(POWER_ON, dai->id); + dump_registers(__func__, + dai->id == 0 ? INTERFACE0 : INTERFACE1, + RX1, RX2, SPKR, EAR, -1); + } else { + power_for_capture(POWER_ON, dai->id); + dump_registers(__func__, MIC_BIAS1, MIC_BIAS2, MIC1_GAIN, TX1, + dai->id == 0 ? INTERFACE0 : INTERFACE1, -1); + } + return 0; +} + +static void ab3550_pcm_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai* dai) +{ + u8 iface = dai->id == 0 ? INTERFACE0 : INTERFACE1; + dev_info(ab3550_dev, "%s called.\n", __func__); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + power_for_playback(POWER_OFF, dai->id); + } else { + power_for_capture(POWER_OFF, dai->id); + } + if (!dai->playback.active && !dai->capture.active && + (read_reg(iface) & I2Sx_MODE_MASK) == 0) + mask_set_reg(iface, MASTER_GENx_PWR_MASK, 0); +} + +static int ab3550_set_dai_sysclk(struct snd_soc_dai* dai, int clk_id, + unsigned int freq, int dir) +{ + return 0; +} + +static int ab3550_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + u8 iface = (codec_dai->id == 0) ? INTERFACE0 : INTERFACE1; + u8 val = 0; + dev_info(ab3550_dev, "%s called.\n", __func__); + + switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | + SND_SOC_DAIFMT_MASTER_MASK)) { + + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: + val |= 1 << I2Sx_MODE_SHIFT; + break; + + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: + break; + + default: + dev_warn(ab3550_dev, "AB3550_dai: unsupported DAI format " + "0x%x\n", fmt); + return -EINVAL; + } + if (codec_dai->playback.active && codec_dai->capture.active) { + if ((read_reg(iface) & I2Sx_MODE_MASK) == val) + return 0; + else { + dev_err(ab3550_dev, + "%s: DAI format set differently " + "by an existing stream.\n", __func__); + return -EINVAL; + } + } + mask_set_reg(iface, I2Sx_MODE_MASK, val); + return 0; +} + +struct snd_soc_dai ab3550_codec_dai[] = { + { + .name = "ab3550_0", + .id = 0, + .playback = { + .stream_name = "ab3550_0", + .channels_min = 2, + .channels_max = 2, + .rates = AB3550_SUPPORTED_RATE, + .formats = AB3550_SUPPORTED_FMT, + }, + .capture = { + .stream_name = "ab3550_0", + .channels_min = 2, + .channels_max = 2, + .rates = AB3550_SUPPORTED_RATE, + .formats = AB3550_SUPPORTED_FMT, + }, + .ops = (struct snd_soc_dai_ops[]) { + { + .startup = ab3550_pcm_startup, + .prepare = ab3550_pcm_prepare, + .hw_params = ab3550_pcm_hw_params, + .shutdown = ab3550_pcm_shutdown, + .set_sysclk = ab3550_set_dai_sysclk, + .set_fmt = ab3550_set_dai_fmt, + } + }, + .symmetric_rates = 1, + .private_data = NULL + }, + { + .name = "ab3550_1", + .id = 1, + .playback = { + .stream_name = "ab3550_1", + .channels_min = 2, + .channels_max = 2, + .rates = AB3550_SUPPORTED_RATE, + .formats = AB3550_SUPPORTED_FMT, + }, + .capture = { + .stream_name = "ab3550_1", + .channels_min = 2, + .channels_max = 2, + .rates = AB3550_SUPPORTED_RATE, + .formats = AB3550_SUPPORTED_FMT, + }, + .ops = (struct snd_soc_dai_ops[]) { + { + .startup = ab3550_pcm_startup, + .prepare = ab3550_pcm_prepare, + .hw_params = ab3550_pcm_hw_params, + .shutdown = ab3550_pcm_shutdown, + .set_sysclk = ab3550_set_dai_sysclk, + .set_fmt = ab3550_set_dai_fmt, + } + }, + .symmetric_rates = 1, + .private_data = NULL + } +}; +EXPORT_SYMBOL_GPL(ab3550_codec_dai); + +static int ab3550_codec_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + int ret; + + dev_info(&pdev->dev, "%s called. pdev = %p.\n", __func__, pdev); + if (!ab3550_codec) { + dev_err(&pdev->dev, "%s: Codec device not registered.\n", + __func__); + return -EAGAIN; + } + socdev->card->codec = ab3550_codec; + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + dev_err(&pdev->dev, "%s: Failed to create a new card " + "and new PCMs. error %d\n", __func__, ret); + goto err; + } + /* Add controls */ + if (ab3550_add_controls(ab3550_codec) < 0) + goto err; + ab3550_add_widgets(ab3550_codec); + return 0; + +err: + snd_soc_free_pcms(socdev); + return ret; +} + +static int ab3550_codec_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); + return 0; +} + +#ifdef CONFIG_PM +static int ab3550_codec_suspend(struct platform_device *pdev, + pm_message_t state) +{ + dev_dbg(ab3550_dev, "%s : pdev=%p.\n", __func__, pdev); + mask_set_reg(CLOCK, CLOCK_ENABLE_MASK, 0); + return 0; +} + +static int ab3550_codec_resume(struct platform_device *pdev) +{ + dev_dbg(ab3550_dev, "%s : pdev=%p.\n", __func__, pdev); + mask_set_reg(CLOCK, CLOCK_ENABLE_MASK, 0xff); + return 0; +} +#else +#define ab3550_codec_resume NULL +#define ab3550_codec_suspend NULL +#endif + +struct snd_soc_codec_device soc_codec_dev_ab3550 = { + .probe = ab3550_codec_probe, + .remove = ab3550_codec_remove, + .suspend = ab3550_codec_suspend, + .resume = ab3550_codec_resume +}; + +EXPORT_SYMBOL_GPL(soc_codec_dev_ab3550); + +static inline void init_playback_route(void) +{ + update_widgets_link(LINK, widget_if0_dld_l, widget_rx1, 0, 0, 0); + update_widgets_link(LINK, widget_rx1, widget_dac1, 0, 0, 0); + update_widgets_link(LINK, widget_dac1, widget_spkr, + SPKR_ADDER, DAC1_TO_ADDER_MASK, 0xff); + + update_widgets_link(LINK, widget_if0_dld_r, widget_rx2, + RX2, RX2_IF_SELECT_MASK, 0); + update_widgets_link(LINK, widget_rx2, widget_dac2, 0, 0, 0); + update_widgets_link(LINK, widget_dac2, widget_ear, + EAR_ADDER, DAC2_TO_ADDER_MASK, 0xff); +} + +static inline void init_capture_route(void) +{ + update_widgets_link(LINK, widget_micbias2, widget_mic1p1, + 0, 0, 0); + update_widgets_link(LINK, widget_micbias2, widget_mic1n1, + 0, 0, 0); + update_widgets_link(LINK, widget_mic1p1, widget_mic1, + MIC1_INPUT_SELECT, MICxP1_SEL_MASK, 0xff); + update_widgets_link(LINK, widget_mic1n1, widget_mic1, + MIC1_INPUT_SELECT, MICxN1_SEL_MASK, 0xff); + update_widgets_link(LINK, widget_mic1, widget_adc1, + 0, 0, 0); + update_widgets_link(LINK, widget_adc1, widget_tx1, + 0, 0, 0); + update_widgets_link(LINK, widget_tx1, widget_if0_uld_l, + INTERFACE0_DATA, I2Sx_L_DATA_MASK, + I2Sx_L_DATA_TX1_MASK); + update_widgets_link(LINK, widget_tx1, widget_if0_uld_r, + INTERFACE0_DATA, I2Sx_R_DATA_MASK, + I2Sx_R_DATA_TX1_MASK); +} + +static inline void init_playback_gain(void) +{ + mask_set_reg(RX1_DIGITAL_PGA, RXx_PGA_GAIN_MASK, + 0x40 << RXx_PGA_GAIN_SHIFT); + mask_set_reg(RX2_DIGITAL_PGA, RXx_PGA_GAIN_MASK, + 0x40 << RXx_PGA_GAIN_SHIFT); + mask_set_reg(EAR, EAR_GAIN_MASK, 0x06 << EAR_GAIN_SHIFT); + mask_set_reg(SPKR, SPKR_GAIN_MASK, 0x6 << SPKR_GAIN_SHIFT); +} + +static inline void init_capture_gain(void) +{ + mask_set_reg(MIC1_GAIN, MICx_GAIN_MASK, 0x06 << MICx_GAIN_SHIFT); + mask_set_reg(TX_DIGITAL_PGA1, TXDPGAx_MASK, 0x0f << TXDPGAx_SHIFT); +} + +static int __init ab3550_platform_probe(struct platform_device *pdev) +{ + int ret = 0; + int i; + u8 reg; + + pr_debug("%s invoked with pdev = %p.\n", __func__, pdev); + ab3550_dev = &pdev->dev; + /* Initialize the codec registers */ + for (reg = AB3550_FIRST_REG; reg <= AB3550_LAST_REG; reg++) + set_reg(reg, 0); + + mask_set_reg(CLOCK, CLOCK_REF_SELECT_MASK | CLOCK_ENABLE_MASK, + 1 << CLOCK_REF_SELECT_SHIFT | 1 << CLOCK_ENABLE_SHIFT); + init_playback_route(); + init_playback_gain(); + init_capture_route(); + init_capture_gain(); + memset(&pm_stack, 0, sizeof(pm_stack)); + + ab3550_codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (ab3550_codec == NULL) + return -ENOMEM; + ab3550_codec->name = "AB3550"; + ab3550_codec->owner = THIS_MODULE; + ab3550_codec->dai = ab3550_codec_dai; + ab3550_codec->num_dai = 2; + ab3550_codec->read = ab3550_read_reg; + ab3550_codec->write = ab3550_write_reg; + ab3550_codec->reg_cache_size = 0; + ab3550_codec->reg_cache = NULL; + INIT_LIST_HEAD(&ab3550_codec->dapm_widgets); + INIT_LIST_HEAD(&ab3550_codec->dapm_paths); + mutex_init(&ab3550_codec->mutex); + ret = snd_soc_register_codec(ab3550_codec); + if (ret) { + dev_err(ab3550_dev, "%s: Failed to register codec: %d.\n", + __func__, ret); + kfree(ab3550_codec); + } + + for (i = 0; !ret && i < ARRAY_SIZE(ab3550_codec_dai); i++) + ret = snd_soc_register_dai(ab3550_codec_dai + i); + if (ret && i == 1) { + snd_soc_unregister_codec(ab3550_codec); + kfree(ab3550_codec); + } + + return ret; +} + +static int ab3550_platform_remove(struct platform_device *pdev) +{ + int i; + + pr_debug("%s called.\n", __func__); + mask_set_reg(CLOCK, CLOCK_ENABLE_MASK, 0); + for (i = 0; i < ARRAY_SIZE(ab3550_codec_dai); i++) + snd_soc_unregister_dai(ab3550_codec_dai + i); + snd_soc_unregister_codec(ab3550_codec); + kfree(ab3550_codec); + ab3550_dev = NULL; + return 0; +} + +static int ab3550_platform_suspend(struct platform_device *pdev, + pm_message_t state) +{ + return 0; +} + +static int ab3550_platform_resume(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver ab3550_platform_driver = { + .driver = { + .name = "ab3550-codec", + .owner = THIS_MODULE, + }, + .probe = ab3550_platform_probe, + .remove = ab3550_platform_remove, + .suspend = ab3550_platform_suspend, + .resume = ab3550_platform_resume, +}; + + +static int __devinit ab3550_init(void) +{ + int ret1; + + pr_debug("%s called.\n", __func__); + + ab3550_dev = NULL; + ab3550_codec = NULL; + /* Register codec platform driver. */ + ret1 = platform_driver_register(&ab3550_platform_driver); + if (ret1 < 0) { + pr_debug("%s: Error %d: Failed to register codec platform " + "driver.\n", __func__, ret1); + } + return ret1; +} + +static void __devexit ab3550_exit(void) +{ + pr_debug("u8500_ab3550_init: Enter.\n"); + + /* Register codec platform driver. */ + pr_debug("%s: Un-register codec platform driver.\n", __func__); + platform_driver_unregister(&ab3550_platform_driver); +} + +module_init(ab3550_init); +module_exit(ab3550_exit); + +MODULE_DESCRIPTION("AB3550 Codec driver"); +MODULE_AUTHOR("Xie Xiaolei "); +MODULE_LICENSE("GPLv2"); diff --git a/sound/soc/codecs/ab3550.h b/sound/soc/codecs/ab3550.h new file mode 100644 index 00000000000..f553fdce96b --- /dev/null +++ b/sound/soc/codecs/ab3550.h @@ -0,0 +1,336 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Xie Xiaolei + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#ifndef AB3550_CODEC_REGISTERS_H +#define AB3550_CODEC_REGISTERS_H + +extern struct snd_soc_dai ab3550_codec_dai[2]; +extern struct snd_soc_codec_device soc_codec_dev_ab3550; + +#define AB3550_SUPPORTED_RATE (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) + +#define AB3550_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +/* MIC BIAS */ + +#define MIC_BIAS1 0X31 +#define MIC_BIAS2 0X32 +#define MBIAS2_OUT_V_MASK 0x04 +#define MBIAS2_OUT_V_SHIFT 2 +#define MBIAS_PWR_MASK 0x02 +#define MBIAS_PWR_SHIFT 1 +#define MBIAS_PDN_IMP_MASK 0x01 +#define MBIAS_PDN_IMP_SHIFT 0 + +#define MIC_BIAS2_VAD 0x33 +#define MBIAS2_R_INT_MASK 0x01 +#define MBIAS2_R_INT_SHIFT 0 + +/* MIC */ +#define MIC1_GAIN 0x34 +#define MIC2_GAIN 0x35 +#define MICx_GAIN_MASK 0xF0 +#define MICx_GAIN_SHIFT 4 +#define MICx_IN_IMP_MASK 0x0C +#define MICx_IN_IMP_SHIFT 2 +#define MICx_PWR_MASK 0x01 +#define MICx_PWR_SHIFT 0 + +#define MIC1_INPUT_SELECT 0x36 +#define MIC2_INPUT_SELECT 0x37 +#define MICxP1_SEL_MASK 0x80 +#define MICxP1_SEL_SHIFT 7 +#define MICxN1_SEL_MASK 0x40 +#define MICxN1_SEL_SHIFT 6 +#define MICxP2_SEL_MASK 0x20 +#define MICxP2_SEL_SHIFT 5 +#define MICxN2_SEL_MASK 0x10 +#define MICxN2_SEL_SHIFT 4 +#define LINEIN_SEL_MASK 0x03 +#define LINEIN_SEL_SHIFT 0 + +#define MIC1_VMID_SELECT 0x38 +#define MIC2_VMID_SELECT 0x39 +#define VMIDx_ENABLE_MASK 0xC0 +#define VMIDx_ENABLE_SHIFT 6 +#define VMIDx_LINEIN1_N_MASK 0x20 +#define VMIDx_LINEIN1_N_SHIFT 5 +#define VMIDx_LINEIN2_N_MASK 0x10 +#define VMIDx_LINEIN2_N_SHIFT 4 +#define VMIDx_MICxP1_MASK 0x08 +#define VMIDx_MICxP1_SHIFT 3 +#define VMIDx_MICxP2_MASK 0x04 +#define VMIDx_MICxP2_SHIFT 2 +#define VMIDx_MICxN1_MASK 0x02 +#define VMIDx_MICxN1_SHIFT 1 +#define VMIDx_MICxN2_MASK 0x01 +#define VMIDx_MICxN2_SHIFT 0 + +#define MIC2_TO_MIC1 0x3A +#define MIC2_TO_MIC1_MASK 0x03 +#define MIC2_TO_MIC1_SHIFT 0 + +/* Analog Loop */ +#define ANALOG_LOOP_PGA1 0x3B +#define ANALOG_LOOP_PGA2 0x3C +#define APGAx_GAIN_MASK 0xF8 +#define APGAx_GAIN_SHIFT 3 +#define APGAx_PWR_MASK 0x04 +#define APGAx_PWR_SHIFT 2 +#define APGAx_MUX_MASK 0x03 +#define APGAx_MUX_SHIFT 0 +#define APGAx_MUX_MIC1_MASK 0x01 +#define APGAx_MUX_MIC1_SHIFT 0 +#define APGAx_MUX_MIC2_MASK 0x02 +#define APGAx_MUX_MIC2_SHIFT 1 + + +#define APGA_VMID_SELECT 0x3D +#define VMID_APGA1_ENABLE_MASK 0xC0 +#define VMID_APGA1_ENABLE_SHIFT 6 +#define VMID_APGA1_LINEIN1_MASK 0x20 +#define VMID_APGA1_LINEIN1_SHIFT 5 +#define VMID_APGA2_ENABLE_MASK 0x0C +#define VMID_APGA2_ENABLE_SHIFT 2 +#define VMID_APGA2_LINEIN2_MASK 0x02 +#define VMID_APGA2_LINEIN2_SHIFT 1 + +/* Output Amplifiers */ +#define EAR 0x3E +#define EAR_PWR_MODE_MASK 0x20 +#define EAR_PWR_MODE_SHIFT 5 +#define EAR_PWR_MASK 0x10 +#define EAR_PWR_SHIFT 4 +#define EAR_GAIN_MASK 0x0F +#define EAR_GAIN_SHIFT 0 + +#define AUXO1 0x3F +#define AUXO2 0x40 +#define AUXOx_PWR_MASK 0x80 +#define AUXOx_PWR_SHIFT 7 +#define AUXOx_INV_MASK 0x40 +#define AUXOx_INV_SHIFT 6 +#define AUXOx_PULLDOWN_MASK 0x20 +#define AUXOx_PULLDOWN_SHIFT 5 +#define AUXOx_GAIN_MASK 0x0F +#define AUXOx_GAIN_SHIFT 0 + +#define AUXO_PWR_MODE 0x41 +#define AUT_PWR_MODE_MASK 0x04 +#define AUT_PWR_MODE_SHIFT 2 +#define AUXO_PWR_MODE_MASK 0x03 +#define AUXO_PWR_MODE_SHIFT 0 + +#define OFFSET_CANCEL 0x42 +#define SPKR_OFF_CANC_MASK 0x04 +#define SPKR_OFF_CANC_SHIFT 2 +#define AUXO_OFF_CANC_MASK 0x02 +#define AUXO_OFF_CANC_SHIFT 1 +#define OFFSET_CLOCK_MASK 0x01 +#define OFFSET_CLOCK_SHIFT 0 + +#define SPKR 0x43 +#define OVR_CURR_PROT_MASK 0x80 +#define OVR_CURR_PROT_SHIFT 7 +#define SPKR_PWR_MASK 0x40 +#define SPKR_PWR_SHIFT 6 +#define SPKR_GAIN_MASK 0x1F +#define SPKR_GAIN_SHIFT 0 + +#define LINE1 0x44 +#define LINE2 0x45 +#define LINEx_PWR_MASK 0x80 +#define LINEx_PWR_SHIFT 7 +#define LINEx_INV_MASK 0x40 +#define LINEx_INV_SHIFT 6 +#define VMID_BUFFx_MASK 0x10 +#define VMID_BUFFx_SHIFT 4 +#define LINEx_GAIN_MASK 0x0F +#define LINEx_GAIN_SHIFT 0 + +/* Analog loop Routing */ + +#define APGA1_ADDER 0x46 +#define APGA2_ADDER 0x47 +#define APGAx_TO_LINE1_MASK 0x20 +#define APGAx_TO_LINE1_SHIFT 0x5F +#define APGAx_TO_LINE2_MASK 0x10 +#define APGAx_TO_LINE2_SHIFT 4 +#define APGAx_TO_SPKR_MASK 0x08 +#define APGAx_TO_SPKR_SHIFT 3 +#define APGAx_TO_EAR_MASK 0x04 +#define APGAx_TO_EAR_SHIFT 2 +#define APGAx_TO_AUXO1_MASK 0x02 +#define APGAx_TO_AUXO1_SHIFT 1 +#define APGAx_TO_AUXO2_MASK 0x01 +#define APGAx_TO_AUXO2_SHIFT 0 +#define APGAx_ADDER_VALID_BITS_MASK 0x3F + +/* Output Amplifiers Routing */ + +#define EAR_ADDER 0x48 +#define AUXO1_ADDER 0x49 +#define AUXO2_ADDER 0x4A +#define SPKR_ADDER 0x4B +#define LINE1_ADDER 0x4C +#define LINE2_ADDER 0x4D +#define DAC3_TO_ADDER_MASK 0x04 +#define DAC3_TO_ADDER_SHIFT 2 +#define DAC2_TO_ADDER_MASK 0x02 +#define DAC2_TO_ADDER_SHIFT 1 +#define DAC1_TO_ADDER_MASK 0x01 +#define DAC1_TO_ADDER_SHIFT 0 + +#define EAR_TO_MIC2 0x4E +#define EAR_TO_MIC2_MASK 0x01 +#define EAR_TO_MIC2_SHIFT 0 + +#define SPKR_TO_MIC2 0x4F +#define SPKR_TO_MIC2_MASK 0x01 +#define SPKR_TO_MIC2_SHIFT 0 + +#define NEGATIVE_CHARGE_PUMP 0x50 +#define NCP_MODE_MASK 0x02 +#define NCP_MODE_SHIFT 1 +#define NCP_PWR_MASK 0x01 +#define NCP_PWR_SHIFT 0 + +#define TX1 0x51 +#define TX2 0x52 +#define TXx_HP_FILTER_MASK 0x0C +#define TXx_HP_FILTER_SHIFT 2 +#define TXx_PWR_MASK 0x02 +#define TXx_PWR_SHIFT 1 +#define ADCx_PWR_MASK 0x01 +#define ADCx_PWR_SHIFT 0 + +#define RX1 0x53 +#define RX2 0x54 +#define RX2_IF_SELECT_MASK 0x10 +#define RX2_IF_SELECT_SHIFT 4 +#define RX3 0x55 +#define RXx_PWR_MASK 0x08 +#define RXx_PWR_SHIFT 3 +#define DACx_PWR_MASK 0x04 +#define DACx_PWR_SHIFT 2 +#define DACx_PWR_MODE_MASK 0x03 +#define DACx_PWR_MODE_SHIFT 0 + +#define TX_DIGITAL_PGA1 0X56 +#define TX_DIGITAL_PGA2 0X57 +#define TXDPGAx_MASK 0x0F +#define TXDPGAx_SHIFT 0 + +#define RX1_DIGITAL_PGA 0x58 +#define RX2_DIGITAL_PGA 0x59 +#define RX3_DIGITAL_PGA 0x5A +#define RXx_PGA_GAIN_MASK 0x7F +#define RXx_PGA_GAIN_SHIFT 0 + +#define SIDETONE1_PGA 0x5B +#define SIDETONE2_PGA 0x5C +#define STx_HP_FILTER_MASK 0x60 +#define STx_HP_FILTER_SHIFT 5 +#define STx_MUX_MASK 0x10 +#define STx_MUX_SHIFT 4 +#define STx_PGA_MASK 0x0F +#define STx_PGA_SHIFT 0 + +/* clock */ + +#define CLOCK 0x5D +#define CLOCK_REF_SELECT_MASK 0x02 +#define CLOCK_REF_SELECT_SHIFT 1 +#define CLOCK_ENABLE_MASK 0x01 +#define CLOCK_ENABLE_SHIFT 0 + +/* Interface */ + +#define INTERFACE0 0x5E +#define INTERFACE1 0x60 +#define I2Sx_WORDLENGTH_MASK 0x40 +#define I2Sx_WORDLENGTH_SHIFT 6 +#define MASTER_GENx_PWR_MASK 0x20 +#define MASTER_GENx_PWR_SHIFT 5 +#define I2Sx_MODE_MASK 0x10 +#define I2Sx_MODE_SHIFT 4 +#define I2Sx_TRISTATE_MASK 0x08 +#define I2Sx_TRISTATE_SHIFT 3 +#define I2Sx_PULLDOWN_MASK 0x04 +#define I2Sx_PULLDOWN_SHIFT 2 +#define I2Sx_SR_MASK 0x03 +#define I2Sx_SR_SHIFT 0 +#define I2Sx_SR_8000Hz 0 +#define I2Sx_SR_16000Hz 1 +#define I2Sx_SR_44100Hz 2 +#define I2Sx_SR_48000Hz 3 + +#define INTERFACE0_DATA 0x5F +#define INTERFACE1_DATA 0x61 +#define I2Sx_L_DATA_MASK 0x0C +#define I2Sx_L_DATA_TX1_MASK 0x04 +#define I2Sx_L_DATA_TX2_MASK 0x08 +#define I2Sx_L_DATA_SHIFT 2 +#define I2Sx_R_DATA_MASK 0x03 +#define I2Sx_R_DATA_TX1_MASK 0x01 +#define I2Sx_R_DATA_TX2_MASK 0x02 +#define I2Sx_R_DATA_SHIFT 0 + +#define INTERFACE_LOOP 0x62 +#define I2S0_INT_LOOP_MASK 0x08 +#define I2S0_INT_LOOP_SHIFT 3 +#define I2S0_EXT_LOOP_MASK 0x04 +#define I2S0_EXT_LOOP_SHIFT 2 +#define I2S1_INT_LOOP_MASK 0x02 +#define I2S1_INT_LOOP_SHIFT 1 +#define I2S1_EXT_LOOP_MASK 0x01 +#define I2S1_EXT_LOOP_SHIFT 0 + +#define INTERFACE_SWAP 0x63 +#define RX_SWAP0_MASK 0x10 +#define RX_SWAP0_SHIFT 4 +#define RX_SWAP1_MASK 0x08 +#define RX_SWAP1_SHIFT 3 +#define IF_SWAP_MASK 0x04 +#define IF_SWAP_SHIFT 2 +#define IO_SWAP0_MASK 0x02 +#define IO_SWAP0_SHIFT 1 +#define IO_SWAP1_MASK 0x01 +#define IO_SWAP1_SHIFT 0 + +#define AB3550_FIRST_REG MIC_BIAS1 +#define AB3550_LAST_REG INTERFACE_SWAP + +#define AB3550_VIRTUAL_REG1 (AB3550_LAST_REG + 1) +#define IF0_DLD_L_PW_SHIFT 0 +#define IF0_DLD_R_PW_SHIFT 1 +#define IF0_ULD_L_PW_SHIFT 2 +#define IF0_ULD_R_PW_SHIFT 3 +#define IF1_DLD_L_PW_SHIFT 4 +#define IF1_DLD_R_PW_SHIFT 5 +#define IF1_ULD_L_PW_SHIFT 6 +#define IF1_ULD_R_PW_SHIFT 7 + +#define AB3550_VIRTUAL_REG2 (AB3550_LAST_REG + 2) +#define MIC1P1_PW_SHIFT 0 +#define MIC1N1_PW_SHIFT 1 +#define MIC1P2_PW_SHIFT 2 +#define MIC1N2_PW_SHIFT 3 +#define MIC2P1_PW_SHIFT 4 +#define MIC2N1_PW_SHIFT 5 +#define MIC2P2_PW_SHIFT 6 +#define MIC2N2_PW_SHIFT 7 + + +#endif diff --git a/sound/soc/codecs/av8100_audio.c b/sound/soc/codecs/av8100_audio.c new file mode 100644 index 00000000000..7bcb985b9eb --- /dev/null +++ b/sound/soc/codecs/av8100_audio.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ola Lilja (ola.o.lilja@stericsson.com) + * for ST-Ericsson. + * + * License terms: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include