Merge "ASoC: msm8960: Fix button detection voltage thresholds" into msm-3.4
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
new file mode 100644
index 0000000..51bf9e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -0,0 +1,57 @@
+Qualcomm QPNP Leds
+
+QPNP (Qualcomm Plug N Play) LEDs driver is used for
+controlling LEDs that are part of PMIC on Qualcomm reference
+platforms. The PMIC is connected to Host processor via
+SPMI bus. This driver supports various LED modules such as
+WLED (white LED), RGB LED and flash LED. The first version of
+the driver supports WLED and other features are added in the
+next versions.
+
+Required Properties:
+- compatible : should be "qcom,leds-qpnp"
+
+Each LED module is represented as a node of "leds-qpnp". This
+node will furthur contain the type of LED supported and its
+properties.
+
+Required properties:
+- qcom,id : must be one of values supported in enum qpnp_led
+- qcom,label : type of led that will be used, ie "wled"
+- qcom,max-current : maximum current that the LED can sustain
+= qcom,name : name the led will be called by in sysfs entry
+
+WLED is primarily used as display backlight. Display subsystem uses
+LED triggers for WLED to control the brightness as needed.
+
+Optional properties for WLED:
+- qcom,num-strings: number of wled strings supported
+- qcom,ovp_val: over voltage protection threshold,
+ follows enum wled_ovp_threshold
+- qcom,boost_curr_lim: boot currnet limit, follows enum wled_current_bost_limit
+- qcom,ctrl_delay_us: delay in activation of led
+- qcom,dig_mod_gen_en: digital module generator
+- qcom,cs_out_en: current sink output enable
+- qcom,op_fdbck: selection of output as feedback for the boost
+- qcom,cp_select: high pole capacitance
+- linux,default-trigger: trigger the led from external modules such as display
+- qcom,default-state: default state of the led, should be "on" or "off"
+
+Example:
+
+ qcom,leds@d800 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xD800 0x100>;
+ linux,default-trigger = "bkl-trigger"
+ qcom,label = "wled";
+ qcom,cs-out-en;
+ qcom,op-fdbck;
+ qcom,default-state "off";
+ qcom,max-current = <25>;
+ qcom,ctrl-delay-us = <0>;
+ qcom,boost-curr-lim = <3>;
+ qcom,cp-sel = <0>;
+ qcom,switch-freq = <2>;
+ qcom,ovp-val = <2>;
+ qcom,num-strings = <1>;
+ }
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 8aafeb5..a2087e4 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -206,6 +206,155 @@
},
};
+static struct gpiomux_setting cam_settings[] = {
+ {
+ .func = GPIOMUX_FUNC_1, /*active 1*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*i2c suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+ },
+};
+
+static struct msm_gpiomux_config msm_sensor_configs[] __initdata = {
+ {
+ .gpio = 15, /* CAM_MCLK0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 16, /* CAM_MCLK1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 17, /* CAM_MCLK2 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 18, /* WEBCAM1_RESET_N / CAM_MCLK3 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 19, /* CCI_I2C_SDA0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 20, /* CCI_I2C_SCL0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 21, /* CCI_I2C_SDA1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 22, /* CCI_I2C_SCL1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 23, /* FLASH_LED_EN */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 24, /* FLASH_LED_NOW */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 25, /* WEBCAM2_RESET_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 26, /* CAM_IRQ */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 27, /* OIS_SYNC */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 28, /* WEBCAM1_STANDBY */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 89, /* CAM1_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 90, /* CAM1_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 91, /* CAM2_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 92, /* CAM2_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+};
+
void __init msm_8974_init_gpiomux(void)
{
int rc;
@@ -225,4 +374,6 @@
ARRAY_SIZE(msm8974_slimbus_config));
msm_gpiomux_install(msm_touch_configs, ARRAY_SIZE(msm_touch_configs));
+
+ msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
}
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 59b3162..d1d85fc 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -396,7 +396,7 @@
sensor_board_info_ov8825.num_vreg = 0;
}
- if (machine_is_msm8625_evb()
+ if (machine_is_msm8625_evb() || machine_is_msm7627a_evb()
|| machine_is_msm8625_evt()) {
sensor_board_info_ov7692.cam_vreg =
ov7692_gpio_vreg;
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index fac3b1c..e21a645 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5113,27 +5113,26 @@
CLK_LOOKUP("csi_src_clk", csi0_clk_src.c, "fda08000.qcom,csid"),
CLK_LOOKUP("csi_phy_clk", camss_csi0phy_clk.c, "fda08000.qcom,csid"),
CLK_LOOKUP("csi_clk", camss_csi0_clk.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi0pix_clk.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi0rdi_clk.c, "fda08000.qcom,csid"),
CLK_LOOKUP("csi_ahb_clk", camss_csi1_ahb_clk.c, "fda08400.qcom,csid"),
CLK_LOOKUP("csi_src_clk", csi1_clk_src.c, "fda08400.qcom,csid"),
CLK_LOOKUP("csi_phy_clk", camss_csi1phy_clk.c, "fda08400.qcom,csid"),
CLK_LOOKUP("csi_clk", camss_csi1_clk.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi1pix_clk.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi1rdi_clk.c, "fda08400.qcom,csid"),
CLK_LOOKUP("csi_ahb_clk", camss_csi2_ahb_clk.c, "fda08800.qcom,csid"),
CLK_LOOKUP("csi_src_clk", csi2_clk_src.c, "fda08800.qcom,csid"),
CLK_LOOKUP("csi_phy_clk", camss_csi2phy_clk.c, "fda08800.qcom,csid"),
CLK_LOOKUP("csi_clk", camss_csi2_clk.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi2pix_clk.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi2rdi_clk.c, "fda08800.qcom,csid"),
CLK_LOOKUP("csi_ahb_clk", camss_csi3_ahb_clk.c, "fda08c00.qcom,csid"),
CLK_LOOKUP("csi_src_clk", csi3_clk_src.c, "fda08c00.qcom,csid"),
CLK_LOOKUP("csi_phy_clk", camss_csi3phy_clk.c, "fda08c00.qcom,csid"),
CLK_LOOKUP("csi_clk", camss_csi3_clk.c, "fda08c00.qcom,csid"),
- /* ISPIF clocks */
- CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda0a000.qcom,ispif"),
- CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda0a000.qcom,ispif"),
- CLK_LOOKUP("csi1_pix_clk", camss_csi1pix_clk.c, "fda0a000.qcom,ispif"),
- CLK_LOOKUP("csi1_rdi_clk", camss_csi1rdi_clk.c, "fda0a000.qcom,ispif"),
- CLK_LOOKUP("csi2_pix_clk", camss_csi2pix_clk.c, "fda0a000.qcom,ispif"),
- CLK_LOOKUP("csi2_rdi_clk", camss_csi2rdi_clk.c, "fda0a000.qcom,ispif"),
- CLK_LOOKUP("csi3_pix_clk", camss_csi3pix_clk.c, "fda0a000.qcom,ispif"),
- CLK_LOOKUP("csi3_rdi_clk", camss_csi3rdi_clk.c, "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi3pix_clk.c, "fda08c00.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi3rdi_clk.c, "fda08c00.qcom,csid"),
/*VFE clocks*/
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
"fda10000.qcom,vfe"),
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index e7d652b..0331919 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1851,6 +1851,7 @@
/* Part number for 1.2GHz part */
case 0x773:
case 0x774:
+ case 0x779:
case 0x781:
case 0x8D1:
cpu = MSM8625A;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 0511225..0867c1d 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -308,6 +308,19 @@
uint16_t i2c_queue;
};
+enum msm_camera_i2c_cmd_type {
+ MSM_CAMERA_I2C_CMD_WRITE,
+ MSM_CAMERA_I2C_CMD_POLL,
+};
+
+struct msm_camera_i2c_reg_conf {
+ uint16_t reg_addr;
+ uint16_t reg_data;
+ enum msm_camera_i2c_data_type dt;
+ enum msm_camera_i2c_cmd_type cmd_type;
+ int16_t mask;
+};
+
struct msm_camera_cci_i2c_write_cfg {
struct msm_camera_i2c_reg_conf *reg_conf_tbl;
enum msm_camera_i2c_reg_addr_type addr_type;
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h b/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h
new file mode 100644
index 0000000..188af9f
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h
@@ -0,0 +1,303 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _MACH_QDSP5_V2_ACDB_COMMANDS_H
+#define _MACH_QDSP5_V2_ACDB_COMMANDS_H
+
+#define ACDB_VOICE_NETWORK_ID_DEFAULT 0x00010037
+#define ACDB_INITIALISING 0
+#define ACDB_READY 1
+
+
+/* 4KB */
+#define ACDB_PAGE_SIZE 0x1000
+
+#define ACDB_CDMA_NB 0x0108b153
+#define ACDB_CDMA_WB 0x0108b154
+#define ACDB_GSM_NB 0x0108b155
+#define ACDB_GSM_WB 0x0108b156
+#define ACDB_WCDMA_NB 0x0108b157
+#define ACDB_WCDMA_WB 0x0108b158
+
+
+/* ACDB commands */
+
+
+/* struct acdb_cmd_install_device */
+#define ACDB_INSTALL_DEVICE 0x0108d245
+
+/* struct acdb_cmd_install_device */
+#define ACDB_UNINSTALL_DEVICE 0x0108d246
+
+/* struct acdb_cmd_device */
+#define ACDB_GET_DEVICE 0x0108bb92
+
+/* struct acdb_cmd_device */
+#define ACDB_SET_DEVICE 0x0108bb93
+
+/* struct acdb_cmd_get_device_table */
+#define ACDB_GET_DEVICE_TABLE 0x0108bb97
+
+/* struct acdb_cmd_get_device_capabilities */
+#define ACDB_GET_DEVICE_CAPABILITIES 0x0108f5ca
+
+/* struct acdb_cmd_get_device_info */
+#define ACDB_GET_DEVICE_INFO 0x0108f5cb
+
+/*command to intitialize ACDB based on codec type*/
+#define ACDB_CMD_INITIALIZE_FOR_ADIE 0x00011283
+
+
+/* ACDB Error codes */
+
+#define ACDB_RES_SUCCESS 0
+#define ACDB_RES_FAILURE -1
+#define ACDB_RES_BADPARM -2
+#define ACDB_RES_BADSTATE -3
+
+#define TGTVERS_MSM7x30_BRING_UP 0x00010064
+
+
+
+/* Algorithm Aspect IDs */
+
+#define IID_ENABLE_FLAG 0x0108b6b9
+
+
+#define IID_ENABLE_FLAG_SIZE 1
+#define IID_ECHO_CANCELLER_VERSION_SIZE 2
+#define IID_ECHO_CANCELLER_MODE_SIZE 2
+#define IID_ECHO_CANCELLER_NOISE_SUPPRESSOR_ENABLE_SIZE 1
+#define IID_ECHO_CANCELLER_PARAMETERS_SIZE 32
+#define IID_ECHO_CANCELLER_NEXTGEN_NB_PARAMETERS_SIZE (38 * 2)
+#define IID_ECHO_CANCELLER_NEXTGEN_WB_PARAMETERS_SIZE (38 * 2)
+#define IID_FLUENCE_PARAMETERS_SIZE 486
+#define IID_AFE_VOLUME_CONTROL_SIZE 6
+#define IID_GAIN_SIZE 2
+#define IID_VOICE_FIR_FILTER_SIZE 14
+#define IID_VOICE_IIR_FILTER_SIZE 114
+#define IID_RX_DBM_OFFSET_SIZE 2
+#define IID_AGC_SIZE 36
+#define IID_AVC_SIZE 80
+
+#define IID_AUDIO_IIR_COEFF_SIZE 100
+#define IID_MBADRC_PARAMETERS_SIZE 8
+#define IID_MBADRC_EXT_BUFF_SIZE 392
+#define IID_MBADRC_BAND_CONFIG_SIZE 100
+#define IID_QAFX_PARAMETERS_SIZE 2
+#define IID_QCONCERT_PARAMETERS_SIZE 2
+#define IID_AUDIO_AGC_PARAMETERS_SIZE 42
+#define IID_NS_PARAMETERS_SIZE 14
+
+#define IID_ECHO_CANCELLER_VERSION 0x00010042
+#define IID_ECHO_CANCELLER_MODE 0x00010043
+#define IID_ECHO_CANCELLER_NOISE_SUPPRESSOR_ENABLE 0x00010044
+#define IID_ECHO_CANCELLER_PARAMETERS 0x00010045
+#define IID_ECHO_CANCELLER_NEXTGEN_NB_PARAMETERS 0x00010046
+#define IID_ECHO_CANCELLER_NEXTGEN_WB_PARAMETERS 0x00010047
+#define IID_FLUENCE_PARAMETERS 0x00010048
+#define IID_AFE_VOLUME_CONTROL 0x00010049
+#define IID_GAIN 0x0001004A
+#define IID_VOICE_FIR_FILTER 0x0001004B
+#define IID_VOICE_IIR_FILTER 0x0001004C
+#define IID_AGC 0x0001004E
+#define IID_AVC 0x0001004F
+#define ABID_SIDETONE_GAIN 0x00010050
+#define ABID_TX_VOICE_GAIN 0x00010051
+#define ABID_TX_DTMF_GAIN 0x00010052
+#define ABID_CODEC_TX_GAIN 0x00010053
+#define ABID_HSSD 0x00010054
+#define ABID_TX_AGC 0x00010055
+#define ABID_TX_VOICE_FIR 0x00010056
+#define ABID_TX_VOICE_IIR 0x00010057
+#define ABID_ECHO_CANCELLER 0x00010058
+#define ABID_ECHO_CANCELLER_NB_LVHF 0x00010059
+#define ABID_ECHO_CANCELLER_WB_LVHF 0x0001005A
+#define ABID_FLUENCE 0x0001005B
+#define ABID_CODEC_RX_GAIN 0x0001005C
+#define ABID_RX_DBM_OFFSET 0x0001005D
+#define ABID_RX_AGC 0x0001005E
+#define ABID_AVC 0x0001005F
+#define ABID_RX_VOICE_FIR 0x00010060
+#define ABID_RX_VOICE_IIR 0x00010061
+#define ABID_AFE_VOL_CTRL 0x00010067
+
+
+/* AUDIO IDs */
+#define ABID_AUDIO_AGC_TX 0x00010068
+#define ABID_AUDIO_NS_TX 0x00010069
+#define ABID_VOICE_NS 0x0001006A
+#define ABID_AUDIO_IIR_TX 0x0001006B
+#define ABID_AUDIO_IIR_RX 0x0001006C
+#define ABID_AUDIO_MBADRC_RX 0x0001006E
+#define ABID_AUDIO_QAFX_RX 0x0001006F
+#define ABID_AUDIO_QCONCERT_RX 0x00010070
+#define ABID_AUDIO_STF_RX 0x00010071
+#define ABID_AUDIO_CALIBRATION_GAIN_RX 0x00011162
+#define ABID_AUDIO_CALIBRATION_GAIN_TX 0x00011149
+#define ABID_AUDIO_PBE_RX 0x00011197
+#define ABID_AUDIO_RMC_TX 0x00011226
+#define ABID_AUDIO_FLUENCE_TX 0x00011244
+
+
+#define IID_AUDIO_AGC_PARAMETERS 0x0001007E
+#define IID_NS_PARAMETERS 0x00010072
+#define IID_AUDIO_IIR_COEFF 0x00010073
+#define IID_MBADRC_EXT_BUFF 0x00010075
+#define IID_MBADRC_BAND_CONFIG 0x00010076
+#define IID_MBADRC_PARAMETERS 0x00010077
+#define IID_QAFX_PARAMETERS 0x00010079
+#define IID_QCONCERT_PARAMETERS 0x0001007A
+#define IID_STF_COEFF 0x0001007B
+#define IID_AUDIO_CALIBRATION_GAIN_RX 0x00011163
+#define IID_AUDIO_CALIBRATION_GAIN_TX 0x00011171
+#define IID_PBE_CONFIG_PARAMETERS 0x00011198
+#define IID_AUDIO_PBE_RX_ENABLE_FLAG 0x00011199
+#define IID_AUDIO_RMC_PARAM 0x00011227
+#define IID_AUDIO_FLUENCE_TX 0x00011245
+
+
+#define TOPID_RX_TOPOLOGY_1 0x00010062
+#define TOPID_TX_TOPOLOGY_1 0x00010063
+#define AFERID_INT_SINK 0x00010065
+#define AFERID_INT_SOURCE 0x00010066
+#define AFERID_NO_SINK 0x00000000
+#define AFERID_NULL_SINK 0x0108ea92
+
+
+struct acdb_cmd_install_device {
+ u32 command_id;
+ u32 device_id;
+ u32 topology_id;
+ u32 afe_routing_id;
+ u32 cad_routing_id; /* see "Sample Rate Bit Mask" below */
+ u32 sample_rate_mask;
+
+ /* represents device direction: Tx, Rx (aux pga - loopback) */
+ u8 device_type;
+ u8 channel_config; /* Mono or Stereo */
+ u32 adie_codec_path_id;
+};
+
+
+struct acdb_cmd_get_device_capabilities {
+ u32 command_id;
+ u32 total_bytes; /* Length in bytes allocated for buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+
+struct acdb_cmd_get_device_info {
+ u32 command_id;
+ u32 device_id;
+ u32 total_bytes; /* Length in bytes allocated for buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+struct acdb_cmd_device {
+ u32 command_id;
+ u32 device_id;
+ u32 network_id;
+ u32 sample_rate_id; /* Actual sample rate value */
+ u32 interface_id; /* See interface id's above */
+ u32 algorithm_block_id; /* See enumerations above */
+ u32 total_bytes; /* Length in bytes used by buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+struct acdb_cmd_get_device_table {
+ u32 command_id;
+ u32 device_id;
+ u32 network_id;
+ u32 sample_rate_id; /* Actual sample rate value */
+ u32 total_bytes; /* Length in bytes used by buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+struct acdb_result {
+ /* This field is populated in response to the */
+ /* ACDB_GET_DEVICE_CAPABILITIES command and indicates the total */
+ /* devices whose capabilities are copied to the physical memory. */
+ u32 total_devices;
+ u32 *buf; /* Physical Address of data */
+ u32 used_bytes; /* The size in bytes of the data */
+ u32 result; /* See ACDB Error codes above */
+};
+
+struct acdb_device_capability {
+ u32 device_id;
+ u32 sample_rate_mask; /* See "Sample Rate Bit Mask" below */
+};
+
+struct acdb_dev_info {
+ u32 cad_routing_id;
+ u32 sample_rate_mask; /* See "Sample Rate Bit Mask" below */
+ u32 adsp_device_id; /* QDSP6 device ID */
+ u32 device_type; /* Tx, Rx (aux pga - loopback) */
+ u32 channel_config; /* Mono or Stereo */
+ s32 min_volume; /* Min volume (mB) */
+ s32 max_volume; /* Max volume (mB) */
+};
+
+/*structure is used to intialize ACDB software on modem
+based on adie type detected*/
+struct acdb_cmd_init_adie {
+ u32 command_id;
+ u32 adie_type;
+};
+
+#define ACDB_CURRENT_ADIE_MODE_UNKNOWN 0
+#define ACDB_CURRENT_ADIE_MODE_TIMPANI 1
+#define ACDB_CURRENT_ADIE_MODE_MARIMBA 2
+
+/* Sample Rate Bit Mask */
+
+/* AUX PGA devices will have a sample rate mask of 0xFFFFFFFF */
+/* 8kHz 0x00000001 */
+/* 11.025kHz 0x00000002 */
+/* 12kHz 0x00000004 */
+/* 16kHz 0x00000008 */
+/* 22.5kHz 0x00000010 */
+/* 24kHz 0x00000020 */
+/* 32kHz 0x00000040 */
+/* 44.1kHz 0x00000080 */
+/* 48kHz 0x00000100 */
+
+
+/* Device type enumeration */
+enum {
+ RX_DEVICE = 1,
+ TX_DEVICE,
+ AUXPGA_DEVICE,
+ DEVICE_TYPE_MAX
+};
+
+#ifdef CONFIG_DEBUG_FS
+/*These are ABID used for RTC*/
+#define ABID_AUDIO_RTC_MBADRC_RX 0x0001118A
+#define ABID_AUDIO_RTC_VOLUME_PAN_RX 0x0001118C
+#define ABID_AUDIO_RTC_SPA 0x0001118E
+#define ABID_AUDIO_RTC_EQUALIZER_PARAMETERS 0x0001119F
+
+/*These are IID used for RTC*/
+#define IID_AUDIO_RTC_MBADRC_PARAMETERS 0x0001118B
+#define IID_AUDIO_RTC_VOLUME_PAN_PARAMETERS 0x0001118D
+#define IID_AUDIO_RTC_SPA_PARAMETERS 0x0001118F
+#define IID_AUDIO_RTC_EQUALIZER_PARAMETERS 0x0001119E
+#define IID_AUDIO_RTC_AGC_PARAMETERS 0x000111A7
+#define IID_AUDIO_RTC_TX_IIR_COEFF 0x000111A8
+
+#endif
+
+
+#endif
+
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
new file mode 100644
index 0000000..e1fc0cd
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H
+#define _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H
+
+/* Define ACDB device ID */
+#define ACDB_ID_HANDSET_SPKR 1
+#define ACDB_ID_HANDSET_MIC 2
+#define ACDB_ID_HEADSET_MIC 3
+#define ACDB_ID_HEADSET_SPKR_MONO 4
+#define ACDB_ID_HEADSET_SPKR_STEREO 5
+#define ACDB_ID_SPKR_PHONE_MIC 6
+#define ACDB_ID_SPKR_PHONE_MONO 7
+#define ACDB_ID_SPKR_PHONE_STEREO 8
+#define ACDB_ID_BT_SCO_MIC 9
+#define ACDB_ID_BT_SCO_SPKR 0x0A
+#define ACDB_ID_BT_A2DP_SPKR 0x0B
+#define ACDB_ID_BT_A2DP_TX 0x10
+#define ACDB_ID_TTY_HEADSET_MIC 0x0C
+#define ACDB_ID_TTY_HEADSET_SPKR 0x0D
+#define ACDB_ID_HEADSET_MONO_PLUS_SPKR_MONO_RX 0x11
+#define ACDB_ID_HEADSET_STEREO_PLUS_SPKR_STEREO_RX 0x14
+#define ACDB_ID_FM_TX_LOOPBACK 0x17
+#define ACDB_ID_FM_TX 0x18
+#define ACDB_ID_LP_FM_SPKR_PHONE_STEREO_RX 0x19
+#define ACDB_ID_LP_FM_HEADSET_SPKR_STEREO_RX 0x1A
+#define ACDB_ID_I2S_RX 0x20
+#define ACDB_ID_SPKR_PHONE_MIC_BROADSIDE 0x2B
+#define ACDB_ID_HANDSET_MIC_BROADSIDE 0x2C
+#define ACDB_ID_SPKR_PHONE_MIC_ENDFIRE 0x2D
+#define ACDB_ID_HANDSET_MIC_ENDFIRE 0x2E
+#define ACDB_ID_I2S_TX 0x30
+#define ACDB_ID_HDMI 0x40
+#define ACDB_ID_FM_RX 0x4F
+/*Replace the max device ID,if any new device is added Specific to RTC only*/
+#define ACDB_ID_MAX ACDB_ID_FM_RX
+
+/* ID used for virtual devices */
+#define PSEUDO_ACDB_ID 0xFFFF
+
+#endif /* _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h
new file mode 100644
index 0000000..5bad4fa
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h
@@ -0,0 +1,132 @@
+/* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _MACH_QDSP5_V2_AUDIO_ACDBI_H
+#define _MACH_QDSP5_V2_AUDIO_ACDBI_H
+
+#define DBOR_SIGNATURE 0x524F4244
+
+void acdb_rtc_set_err(u32 err_code);
+
+
+struct header {
+ u32 dbor_signature;
+ u32 abid;
+ u32 iid;
+ u32 data_len;
+};
+
+enum {
+ ACDB_AGC_BLOCK = 197,
+ ACDB_IIR_BLOCK = 245,
+ ACDB_MBADRC_BLOCK = 343
+};
+
+/* Structure to query for acdb parameter */
+struct acdb_get_block {
+ u32 acdb_id;
+ u32 sample_rate_id; /* Actual sample rate value */
+ u32 interface_id; /* Interface id's */
+ u32 algorithm_block_id; /* Algorithm block id */
+ u32 total_bytes; /* Length in bytes used by buffer for
+ configuration */
+ u32 *buf_ptr; /* Address for storing configuration
+ data */
+};
+
+struct acdb_agc_block {
+ u16 enable_status;
+ u16 comp_rlink_static_gain;
+ u16 comp_rlink_aig_flag;
+ u16 exp_rlink_threshold;
+ u16 exp_rlink_slope;
+ u16 comp_rlink_threshold;
+ u16 comp_rlink_slope;
+ u16 comp_rlink_aig_attack_k;
+ u16 comp_rlink_aig_leak_down;
+ u16 comp_rlink_aig_leak_up;
+ u16 comp_rlink_aig_max;
+ u16 comp_rlink_aig_min;
+ u16 comp_rlink_aig_release_k;
+ u16 comp_rlink_aig_sm_leak_rate_fast;
+ u16 comp_rlink_aig_sm_leak_rate_slow;
+ u16 comp_rlink_attack_k_msw;
+ u16 comp_rlink_attack_k_lsw;
+ u16 comp_rlink_delay;
+ u16 comp_rlink_release_k_msw;
+ u16 comp_rlink_release_k_lsw;
+ u16 comp_rlink_rms_trav;
+};
+
+
+struct iir_coeff_type {
+ u16 b0_lo;
+ u16 b0_hi;
+ u16 b1_lo;
+ u16 b1_hi;
+ u16 b2_lo;
+ u16 b2_hi;
+};
+
+struct iir_coeff_stage_a {
+ u16 a1_lo;
+ u16 a1_hi;
+ u16 a2_lo;
+ u16 a2_hi;
+};
+
+struct acdb_iir_block {
+ u16 enable_flag;
+ u16 stage_count;
+ struct iir_coeff_type stages[4];
+ struct iir_coeff_stage_a stages_a[4];
+ u16 shift_factor[4];
+ u16 pan[4];
+};
+
+struct mbadrc_band_config_type {
+ u16 mbadrc_sub_band_enable;
+ u16 mbadrc_sub_mute;
+ u16 mbadrc_comp_rms_tav;
+ u16 mbadrc_comp_threshold;
+ u16 mbadrc_comp_slop;
+ u16 mbadrc_comp_attack_msw;
+ u16 mbadrc_comp_attack_lsw;
+ u16 mbadrc_comp_release_msw;
+ u16 mbadrc_comp_release_lsw;
+ u16 mbadrc_make_up_gain;
+};
+
+struct mbadrc_parameter {
+ u16 mbadrc_enable;
+ u16 mbadrc_num_bands;
+ u16 mbadrc_down_sample_level;
+ u16 mbadrc_delay;
+};
+
+struct acdb_mbadrc_block {
+ u16 ext_buf[196];
+ struct mbadrc_band_config_type band_config[5];
+ struct mbadrc_parameter parameters;
+};
+
+struct acdb_ns_tx_block {
+ unsigned short ec_mode_new;
+ unsigned short dens_gamma_n;
+ unsigned short dens_nfe_block_size;
+ unsigned short dens_limit_ns;
+ unsigned short dens_limit_ns_d;
+ unsigned short wb_gamma_e;
+ unsigned short wb_gamma_n;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpp.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpp.h
new file mode 100644
index 0000000..bbd82a0
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpp.h
@@ -0,0 +1,93 @@
+/*arch/arm/mach-msm/qdsp5audpp.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 _MACH_QDSP5_AUDPP_H
+#define _MACH_QDSP5_AUDPP_H
+
+#include <mach/qdsp5/qdsp5audppcmdi.h>
+
+typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
+
+/* worst case delay of 1sec for response */
+#define MSM_AUD_DECODER_WAIT_MS 1000
+#define MSM_AUD_MODE_TUNNEL 0x00000100
+#define MSM_AUD_MODE_NONTUNNEL 0x00000200
+#define MSM_AUD_DECODER_MASK 0x0000FFFF
+#define MSM_AUD_OP_MASK 0xFFFF0000
+
+/*Playback mode*/
+#define NON_TUNNEL_MODE_PLAYBACK 1
+#define TUNNEL_MODE_PLAYBACK 0
+
+enum msm_aud_decoder_state {
+ MSM_AUD_DECODER_STATE_NONE = 0,
+ MSM_AUD_DECODER_STATE_FAILURE = 1,
+ MSM_AUD_DECODER_STATE_SUCCESS = 2,
+ MSM_AUD_DECODER_STATE_CLOSE = 3,
+};
+
+int audpp_adec_alloc(unsigned dec_attrb, const char **module_name,
+ unsigned *queueid);
+void audpp_adec_free(int decid);
+
+struct audpp_event_callback {
+ audpp_event_func fn;
+ void *private;
+};
+
+int audpp_register_event_callback(struct audpp_event_callback *eh);
+int audpp_unregister_event_callback(struct audpp_event_callback *eh);
+int is_audpp_enable(void);
+
+int audpp_enable(int id, audpp_event_func func, void *private);
+void audpp_disable(int id, void *private);
+
+int audpp_send_queue1(void *cmd, unsigned len);
+int audpp_send_queue2(void *cmd, unsigned len);
+int audpp_send_queue3(void *cmd, unsigned len);
+
+int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
+int audpp_pause(unsigned id, int pause);
+int audpp_flush(unsigned id);
+void audpp_avsync(int id, unsigned rate);
+unsigned audpp_avsync_sample_count(int id);
+unsigned audpp_avsync_byte_count(int id);
+int audpp_dsp_set_mbadrc(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_mbadrc *mbadrc);
+int audpp_dsp_set_eq(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_eqalizer *eq);
+int audpp_dsp_set_rx_iir(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_pcm *iir);
+
+int audpp_dsp_set_rx_srs_trumedia_g
+ (struct audpp_cmd_cfg_object_params_srstm_g *srstm);
+int audpp_dsp_set_rx_srs_trumedia_w
+ (struct audpp_cmd_cfg_object_params_srstm_w *srstm);
+int audpp_dsp_set_rx_srs_trumedia_c
+ (struct audpp_cmd_cfg_object_params_srstm_c *srstm);
+int audpp_dsp_set_rx_srs_trumedia_h
+ (struct audpp_cmd_cfg_object_params_srstm_h *srstm);
+int audpp_dsp_set_rx_srs_trumedia_p
+ (struct audpp_cmd_cfg_object_params_srstm_p *srstm);
+int audpp_dsp_set_rx_srs_trumedia_l
+ (struct audpp_cmd_cfg_object_params_srstm_l *srstm);
+
+int audpp_dsp_set_vol_pan(unsigned id,
+ audpp_cmd_cfg_object_params_volume *vol_pan);
+int audpp_dsp_set_qconcert_plus(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_qconcert *qconcert_plus);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
index 3115299..de30c65 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
@@ -530,6 +530,18 @@
unsigned short arm_to_dsp_buf_len;
} __attribute__((packed)) audpp_cmd_pcm_intf_send_buffer;
+#define AUDPP_CMD_PP_FEAT_QUERY_PARAMS 0x0003
+
+struct rtc_audpp_read_data {
+ unsigned short cmd_id;
+ unsigned short obj_id;
+ unsigned short feature_id;
+ unsigned short extbufsizemsw;
+ unsigned short extbufsizelsw;
+ unsigned short extpart;
+ unsigned short extbufstartmsw;
+ unsigned short extbufstartlsw;
+} __packed ;
/*
* Commands Related to uPAudPPCmd3Queue
@@ -564,6 +576,8 @@
#define AUDPP_CMD_COMMON_CFG_UPDATE 0x8000
#define AUDPP_CMD_COMMON_CFG_DONT_UPDATE 0x0000
+#define AUDPP_CMD_COPP_STREAM 0x0006
+
typedef struct {
unsigned short cmd_id;
unsigned short obj0_cfg;
@@ -580,6 +594,7 @@
* Command Structure to configure post processing params (Volume)
*/
+#define AUDPP_CMD_VOLUME_PAN 0
#define AUDPP_CMD_CFG_OBJECT_PARAMS_VOLUME_LEN \
sizeof(audpp_cmd_cfg_object_params_volume)
@@ -645,6 +660,7 @@
pan pan_filter[4];
} __attribute__((packed)) filter_4;
+#define AUDPP_CMD_IIR_TUNING_FILTER 1
#define AUDPP_CMD_CFG_OBJECT_PARAMS_PCM_LEN \
sizeof(audpp_cmd_cfg_object_params_pcm)
@@ -666,6 +682,7 @@
* Command Structure to configure post processing parameters (equalizer)
*/
+#define AUDPP_CMD_EQUALIZER 2
#define AUDPP_CMD_CFG_OBJECT_PARAMS_EQALIZER_LEN \
sizeof(audpp_cmd_cfg_object_params_eqalizer)
@@ -787,6 +804,7 @@
* Command Structure to configure post processing parameters (ADRC)
*/
+#define AUDPP_CMD_ADRC 3
#define AUDPP_CMD_CFG_OBJECT_PARAMS_ADRC_LEN \
sizeof(audpp_cmd_cfg_object_params_adrc)
@@ -794,6 +812,7 @@
#define AUDPP_CMD_ADRC_FLAG_DIS 0x0000
#define AUDPP_CMD_ADRC_FLAG_ENA -1
+#define AUDPP_CMD_MBADRC 10
#define AUDPP_MAX_MBADRC_BANDS 5
#define AUDPP_MBADRC_EXTERNAL_BUF_SIZE 196
@@ -839,6 +858,7 @@
* Command Structure to configure post processing parameters(Spectrum Analizer)
*/
+#define AUDPP_CMD_SPECTROGRAM 4
#define AUDPP_CMD_CFG_OBJECT_PARAMS_SPECTRAM_LEN \
sizeof(audpp_cmd_cfg_object_params_spectram)
@@ -853,6 +873,7 @@
* Command Structure to configure post processing parameters (QConcert)
*/
+#define AUDPP_CMD_QCONCERT 5
#define AUDPP_CMD_CFG_OBJECT_PARAMS_QCONCERT_LEN \
sizeof(audpp_cmd_cfg_object_params_qconcert)
@@ -899,6 +920,7 @@
* Command Structure to configure post processing parameters (Side Chain)
*/
+#define AUDPP_CMD_SIDECHAIN_TUNING_FILTER 6
#define AUDPP_CMD_CFG_OBJECT_PARAMS_SIDECHAIN_LEN \
sizeof(audpp_cmd_cfg_object_params_sidechain)
@@ -923,6 +945,7 @@
* Command Structure to configure post processing parameters (QAFX)
*/
+#define AUDPP_CMD_QAFX 8
#define AUDPP_CMD_CFG_OBJECT_PARAMS_QAFX_LEN \
sizeof(audpp_cmd_cfg_object_params_qafx)
@@ -1046,6 +1069,8 @@
audpp_cmd_cfg_object_params_common common;
unsigned short v[SRS_PARAMS_MAX_L];
} __packed;
+#define AUDPP_CMD_SAMPLING_FREQUENCY 7
+#define AUDPP_CMD_QRUMBLE 9
#endif /* QDSP5AUDPPCMDI_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
index 0ba8261..fef4c35 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
@@ -2,29 +2,29 @@
#define QDSP5AUDPPMSG_H
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
-
- Q D S P 5 A U D I O P O S T P R O C E S S I N G M S G
-
-GENERAL DESCRIPTION
- Messages sent by AUDPPTASK to ARM
-
-REFERENCES
- None
-
-EXTERNALIZED FUNCTIONS
- None
-
-Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved.
-
-This software is licensed under the terms of the GNU General Public
-License version 2, as published by the Free Software Foundation, and
-may be copied, distributed, and modified under those terms.
-
-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.
-
+*
+* Q D S P 5 A U D I O P O S T P R O C E S S I N G M S G
+*
+* GENERAL DESCRIPTION
+* Messages sent by AUDPPTASK to ARM
+*
+* REFERENCES
+* None
+*
+* EXTERNALIZED FUNCTIONS
+* None
+*
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. All rights reserved.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
@@ -318,4 +318,5 @@
#define ADSP_MESSAGE_ID 0xFFFF
+#define AUDPP_MSG_FEAT_QUERY_DM_DONE 0x000b
#endif /* QDSP5AUDPPMSG_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h
index 234c4ac..5c7c5dc 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,9 +25,49 @@
#define MSM_ADSP_ENC_MODE_TUNNEL 24
#define MSM_ADSP_ENC_MODE_NON_TUNNEL 25
+/* event callback routine prototype*/
+typedef void (*audpreproc_event_func)(void *private, unsigned id, void *msg);
+
+struct audpreproc_event_callback {
+ audpreproc_event_func fn;
+ void *private;
+};
+
+/*holds audrec information*/
+struct audrec_session_info {
+ int session_id;
+ int sampling_freq;
+};
+
/* Exported common api's from audpreproc layer */
int audpreproc_aenc_alloc(unsigned enc_type, const char **module_name,
unsigned *queue_id);
void audpreproc_aenc_free(int enc_id);
+int audpreproc_enable(int enc_id, audpreproc_event_func func, void *private);
+void audpreproc_disable(int enc_id, void *private);
+
+int audpreproc_unregister_event_callback(struct audpreproc_event_callback *ecb);
+
+int audpreproc_register_event_callback(struct audpreproc_event_callback *ecb);
+
+int audpreproc_update_audrec_info(struct audrec_session_info
+ *audrec_session_info);
+int get_audrec_session_info(struct audrec_session_info *info);
+
+int audpreproc_dsp_set_agc(audpreproc_cmd_cfg_agc_params *agc,
+ unsigned len);
+int audpreproc_dsp_set_ns(audpreproc_cmd_cfg_ns_params *ns,
+ unsigned len);
+int audpreproc_dsp_set_iir(audpreproc_cmd_cfg_iir_tuning_filter_params *iir,
+ unsigned len);
+
+int audpreproc_send_preproccmdqueue(void *cmd, unsigned len);
+typedef void (*audrec_event_func)(void *private, unsigned id, uint16_t *msg);
+int audrectask_enable(unsigned enc_type, audrec_event_func func, void *private);
+void audrectask_disable(unsigned enc_type, void *private);
+
+int audrectask_send_cmdqueue(void *cmd, unsigned len);
+int audrectask_send_bitstreamqueue(void *cmd, unsigned len);
+
#endif /* QDSP5AUDPREPROC_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h
index 8efc916..a38d224 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h
@@ -2,30 +2,30 @@
#define QDSP5AUDPREPROCCMDI_H
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
-
- A U D I O P R E P R O C E S S I N G I N T E R N A L C O M M A N D S
-
-GENERAL DESCRIPTION
- This file contains defintions of format blocks of commands
- that are accepted by AUDPREPROC Task
-
-REFERENCES
- None
-
-EXTERNALIZED FUNCTIONS
- None
-
-Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved.
-
-This software is licensed under the terms of the GNU General Public
-License version 2, as published by the Free Software Foundation, and
-may be copied, distributed, and modified under those terms.
-
-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.
-
+*
+* A U D I O P R E P R O C E S S I N G I N T E R N A L C O M M A N D S
+*
+* GENERAL DESCRIPTION
+* This file contains defintions of format blocks of commands
+* that are accepted by AUDPREPROC Task
+*
+* REFERENCES
+* None
+*
+* EXTERNALIZED FUNCTIONS
+* None
+*
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. All rights reserved.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
@@ -84,29 +84,29 @@
typedef struct {
unsigned short cmd_id;
unsigned short tx_agc_param_mask;
- unsigned short tx_agc_enable_flag;
- unsigned short static_gain;
- signed short adaptive_gain_flag;
- unsigned short expander_th;
- unsigned short expander_slope;
- unsigned short compressor_th;
- unsigned short compressor_slope;
- unsigned short param_mask;
- unsigned short aig_attackk;
- unsigned short aig_leak_down;
- unsigned short aig_leak_up;
- unsigned short aig_max;
- unsigned short aig_min;
- unsigned short aig_releasek;
- unsigned short aig_leakrate_fast;
- unsigned short aig_leakrate_slow;
- unsigned short attackk_msw;
- unsigned short attackk_lsw;
- unsigned short delay;
- unsigned short releasek_msw;
- unsigned short releasek_lsw;
- unsigned short rms_tav;
-} __attribute__((packed)) audpreproc_cmd_cfg_agc_params;
+ signed short tx_agc_enable_flag;
+ unsigned short comp_rlink_static_gain;
+ signed short comp_rlink_aig_flag;
+ unsigned short expander_rlink_th;
+ unsigned short expander_rlink_slope;
+ unsigned short compressor_rlink_th;
+ unsigned short compressor_rlink_slope;
+ unsigned short tx_adc_agc_param_mask;
+ unsigned short comp_rlink_aig_attackk;
+ unsigned short comp_rlink_aig_leak_down;
+ unsigned short comp_rlink_aig_leak_up;
+ unsigned short comp_rlink_aig_max;
+ unsigned short comp_rlink_aig_min;
+ unsigned short comp_rlink_aig_releasek;
+ unsigned short comp_rlink_aig_leakrate_fast;
+ unsigned short comp_rlink_aig_leakrate_slow;
+ unsigned short comp_rlink_attackk_msw;
+ unsigned short comp_rlink_attackk_lsw;
+ unsigned short comp_rlink_delay;
+ unsigned short comp_rlink_releasek_msw;
+ unsigned short comp_rlink_releasek_lsw;
+ unsigned short comp_rlink_rms_tav;
+} __packed audpreproc_cmd_cfg_agc_params;
/*
@@ -253,4 +253,16 @@
unsigned short channel_selected3;
} __attribute__((packed))audpreproc_cmd_cfg_iir_tuning_filter_params;
+#define AUDPREPROC_CMD_FEAT_QUERY_PARAMS 0x0004
+
+struct rtc_audpreproc_read_data {
+ unsigned short cmd_id;
+ unsigned short stream_id;
+ unsigned short feature_id;
+ unsigned short extbufsizemsw;
+ unsigned short extbufsizelsw;
+ unsigned short extpart;
+ unsigned short extbufstartmsw;
+ unsigned short extbufstartlsw;
+} __packed ;
#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h
index 0696066..d299995 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h
@@ -2,30 +2,30 @@
#define QDSP5AUDPREPROCMSG_H
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
-
- A U D I O P R E P R O C E S S I N G M E S S A G E S
-
-GENERAL DESCRIPTION
- This file contains defintions of format blocks of messages
- that are rcvd by AUDPREPROC Task
-
-REFERENCES
- None
-
-EXTERNALIZED FUNCTIONS
- None
-
-Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved.
-
-This software is licensed under the terms of the GNU General Public
-License version 2, as published by the Free Software Foundation, and
-may be copied, distributed, and modified under those terms.
-
-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.
-
+*
+* A U D I O P R E P R O C E S S I N G M E S S A G E S
+*
+* GENERAL DESCRIPTION
+* This file contains defintions of format blocks of messages
+* that are rcvd by AUDPREPROC Task
+*
+* REFERENCES
+* None
+*
+* EXTERNALIZED FUNCTIONS
+* None
+*
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. All rights reserved.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
@@ -82,4 +82,5 @@
unsigned short err_index;
} __attribute__((packed)) audpreproc_msg_error_msg_id;
+#define AUDPREPROC_MSG_FEAT_QUERY_DM_DONE 0x0003
#endif
diff --git a/arch/arm/mach-msm/qdsp5/Makefile b/arch/arm/mach-msm/qdsp5/Makefile
index 89648fe..f4fe052 100644
--- a/arch/arm/mach-msm/qdsp5/Makefile
+++ b/arch/arm/mach-msm/qdsp5/Makefile
@@ -14,7 +14,7 @@
obj-y += audio_out.o audio_mp3.o audmgr.o audpp.o audrec.o audpreproc.o
obj-y += audio_evrc.o audio_qcelp.o audio_amrnb.o audio_aac.o audio_amrnb_in.o
obj-y += audio_wma.o audio_voicememo.o audio_pcm.o audio_amrwb.o audio_wmapro.o
-obj-y += snd.o snd_adie.o
+obj-y += snd.o snd_cad.o snd_adie.o audio_acdb.o
obj-$(CONFIG_ARCH_MSM7X27A) += audio_fm.o
obj-$(CONFIG_ARCH_MSM7X27A) += audio_mvs.o
obj-$(CONFIG_ARCH_MSM7X27A) += audio_lpa.o audio_ac3.o
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac.c b/arch/arm/mach-msm/qdsp5/audio_aac.c
index 15e0590..01e529f 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac.c
@@ -41,6 +41,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac_in.c b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
index 99e10a4..4a35939 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
@@ -109,7 +109,6 @@
int out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
/* configuration to use on next enable */
@@ -150,6 +149,8 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
struct ion_handle *output_buff_handle;
+
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -273,6 +274,31 @@
return temp;
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
/* must be called with audio->lock held */
static int audaac_in_enable(struct audio_aac_in *audio)
{
@@ -293,16 +319,24 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
+
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -328,36 +362,17 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
audmgr_disable(&audio->audmgr);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
-
static void audaac_in_get_dsp_frames(struct audio_aac_in *audio)
{
struct audio_frame *frame;
@@ -596,11 +611,7 @@
}
}
-struct msm_adsp_ops audpre_aac_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
-struct msm_adsp_ops audrec_aac_adsp_ops = {
+static struct msm_adsp_ops audrec_aac_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1241,12 +1252,9 @@
audaac_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
@@ -1342,16 +1350,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_aac_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1493,8 +1491,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_ac3.c b/arch/arm/mach-msm/qdsp5/audio_ac3.c
index ee085c5..c0e2059 100644
--- a/arch/arm/mach-msm/qdsp5/audio_ac3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_ac3.c
@@ -44,6 +44,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
new file mode 100644
index 0000000..16f23f4
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -0,0 +1,2646 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/android_pmem.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/msm_audio.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/memory_alloc.h>
+#include <linux/mfd/marimba.h>
+#include <mach/dal.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/socinfo.h>
+#include <mach/qdsp5/qdsp5audpp.h>
+#include <mach/qdsp5/qdsp5audpreproc.h>
+#include <mach/qdsp5/qdsp5audppcmdi.h>
+#include <mach/qdsp5/qdsp5audpreproccmdi.h>
+#include <mach/qdsp5/qdsp5audpreprocmsg.h>
+#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/audio_acdbi.h>
+#include <mach/qdsp5/acdb_commands.h>
+#include <mach/qdsp5/audio_acdb_def.h>
+#include <mach/debug_mm.h>
+#include <mach/msm_memtypes.h>
+
+#include "audmgr.h"
+
+/* this is the ACDB device ID */
+#define DALDEVICEID_ACDB 0x02000069
+#define ACDB_PORT_NAME "DAL00"
+#define ACDB_CPU SMD_APPS_MODEM
+#define ACDB_BUF_SIZE 4096
+#define FLUENCE_BUF_SIZE 498
+
+#define ACDB_VALUES_NOT_FILLED 0
+#define ACDB_VALUES_FILLED 1
+#define MAX_RETRY 10
+
+#define COMMON_OBJ_ID 6
+
+/*below macro is used to align the session info received from
+Devctl driver with the state mentioned as not to alter the
+Existing code*/
+#define AUDREC_OFFSET 2
+/* rpc table index */
+enum {
+ ACDB_DAL_IOCTL = DALDEVICE_FIRST_DEVICE_API_IDX
+};
+
+enum {
+ CAL_DATA_READY = 0x1,
+ AUDPP_READY = 0x2,
+ AUDREC_READY = 0x4,
+};
+
+struct acdb_data {
+ void *handle;
+
+ u32 phys_addr;
+ u8 *virt_addr;
+
+ struct task_struct *cb_thread_task;
+ struct device_info_callback dev_cb;
+
+ u32 acdb_state;
+ struct audpp_event_callback audpp_cb;
+ struct audpreproc_event_callback audpreproc_cb;
+ struct dev_evt_msg *device_info;
+
+ audpp_cmd_cfg_object_params_pcm *pp_iir;
+ audpp_cmd_cfg_object_params_mbadrc *pp_mbadrc;
+ audpreproc_cmd_cfg_agc_params *preproc_agc;
+ audpreproc_cmd_cfg_iir_tuning_filter_params *preproc_iir;
+ audpreproc_cmd_cfg_ns_params *preproc_ns;
+ struct acdb_mbadrc_block mbadrc_block;
+
+ wait_queue_head_t wait;
+ struct mutex acdb_mutex;
+ u32 device_cb_compl;
+ u32 audpp_cb_compl;
+ u32 preproc_cb_compl;
+ u8 preproc_stream_id;
+ u8 audrec_applied;
+ u32 multiple_sessions;
+ u32 cur_tx_session;
+ struct acdb_result acdb_result;
+
+ spinlock_t dsp_lock;
+ int dec_id;
+ audpp_cmd_cfg_object_params_eqalizer eq;
+ struct audrec_session_info session_info;
+ /*pmem info*/
+ int pmem_fd;
+ unsigned long paddr;
+ unsigned long kvaddr;
+ unsigned long pmem_len;
+ struct file *file;
+ /* pmem for get acdb blk */
+ unsigned long get_blk_paddr;
+ u8 *get_blk_kvaddr;
+ void *map_v_get_blk;
+};
+
+static struct acdb_data acdb_data;
+
+struct acdb_cache_node {
+ u32 node_status;
+ s32 stream_id;
+ u32 phys_addr_acdb_values;
+ void *map_v_addr;
+ u8 *virt_addr_acdb_values;
+ struct dev_evt_msg device_info;
+};
+
+struct acdb_cache_node acdb_cache_rx;
+
+/*for TX devices acdb values are applied based on AUDREC session and
+the depth of the tx cache is define by number of AUDREC sessions supported*/
+struct acdb_cache_node acdb_cache_tx;
+
+/*Audrec session info includes Attributes Sampling frequency and enc_id */
+struct audrec_session_info session_info;
+#ifdef CONFIG_DEBUG_FS
+
+#define RTC_MAX_TIMEOUT 500 /* 500 ms */
+#define PMEM_RTC_ACDB_QUERY_MEM 4096
+#define EXTRACT_HIGH_WORD(x) ((x & 0xFFFF0000)>>16)
+#define EXTRACT_LOW_WORD(x) (0x0000FFFF & x)
+#define ACDB_RTC_TX 0xF1
+#define ACDB_RTC_RX 0x1F
+
+
+static u32 acdb_audpp_entry[][4] = {
+
+ {
+ ABID_AUDIO_RTC_VOLUME_PAN_RX,\
+ IID_AUDIO_RTC_VOLUME_PAN_PARAMETERS,\
+ AUDPP_CMD_VOLUME_PAN,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_IIR_RX,\
+ IID_AUDIO_IIR_COEFF,\
+ AUDPP_CMD_IIR_TUNING_FILTER,
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_RTC_EQUALIZER_PARAMETERS,\
+ IID_AUDIO_RTC_EQUALIZER_PARAMETERS,\
+ AUDPP_CMD_EQUALIZER,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_RTC_SPA,\
+ IID_AUDIO_RTC_SPA_PARAMETERS,\
+ AUDPP_CMD_SPECTROGRAM,
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_STF_RX,\
+ IID_AUDIO_IIR_COEFF,\
+ AUDPP_CMD_SIDECHAIN_TUNING_FILTER,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_MBADRC_RX,\
+ IID_AUDIO_RTC_MBADRC_PARAMETERS,\
+ AUDPP_CMD_MBADRC,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_AGC_TX,\
+ IID_AUDIO_AGC_PARAMETERS,\
+ AUDPREPROC_CMD_CFG_AGC_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_AGC_TX,\
+ IID_AUDIO_RTC_AGC_PARAMETERS,\
+ AUDPREPROC_CMD_CFG_AGC_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_NS_TX,\
+ IID_NS_PARAMETERS,\
+ AUDPREPROC_CMD_CFG_NS_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_IIR_TX,\
+ IID_AUDIO_RTC_TX_IIR_COEFF,\
+ AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_IIR_TX,\
+ IID_AUDIO_IIR_COEFF,\
+ AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS,\
+ ACDB_RTC_TX
+ }
+ /*Any new entries should be added here*/
+};
+
+static struct dentry *get_set_abid_dentry;
+static struct dentry *get_set_abid_data_dentry;
+
+struct rtc_acdb_pmem {
+ u8 *viraddr;
+ int32_t phys;
+ void *map_v_rtc;
+};
+
+struct rtc_acdb_data {
+ u32 acdb_id;
+ u32 cmd_id;
+ u32 set_abid;
+ u32 set_iid;
+ u32 abid;
+ u32 err;
+ bool valid_abid;
+ u32 tx_rx_ctl;
+ struct rtc_acdb_pmem rtc_read;
+ struct rtc_acdb_pmem rtc_write;
+ wait_queue_head_t wait;
+};
+
+struct get_abid {
+ u32 cmd_id;
+ u32 acdb_id;
+ u32 set_abid;
+ u32 set_iid;
+};
+
+struct acdb_block_mbadrc_rtc {
+ u16 enable;
+ u16 num_bands;
+ u16 down_samp_level;
+ u16 adrc_delay;
+ u16 ext_buf_size;
+ u16 ext_partition;
+ u16 ext_buf_msw;
+ u16 ext_buf_lsw;
+ struct adrc_config adrc_band[AUDPP_MAX_MBADRC_BANDS];
+ signed int ext_buff[196];
+} __packed;
+
+enum {
+ ACDB_RTC_SUCCESS,
+ ACDB_RTC_ERR_INVALID_DEVICE,
+ ACDB_RTC_ERR_DEVICE_INACTIVE,
+ ACDB_RTC_ERR_INVALID_ABID,
+ ACDB_RTC_DSP_FAILURE,
+ ACDB_RTC_DSP_FEATURE_NOT_AVAILABLE,
+ ACDB_RTC_ERR_INVALID_LEN,
+ ACDB_RTC_ERR_UNKNOWN_FAILURE,
+ ACDB_RTC_PENDING_RESPONSE,
+ ACDB_RTC_INIT_FAILURE,
+};
+
+static struct rtc_acdb_data rtc_acdb;
+
+static int rtc_getsetabid_dbg_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ MM_DBG("GET-SET ABID Open debug intf %s\n",\
+ (char *) file->private_data);
+ return 0;
+}
+
+static bool get_feature_id(u32 set_abid, u32 iid, unsigned short *feature_id)
+{
+ bool ret_value = false;
+ int i = 0;
+
+ for (; i < (sizeof(acdb_audpp_entry) / sizeof(acdb_audpp_entry[0]));\
+ i++) {
+ if (acdb_audpp_entry[i][0] == set_abid &&
+ acdb_audpp_entry[i][1] == iid) {
+ *feature_id = acdb_audpp_entry[i][2];
+ rtc_acdb.tx_rx_ctl = acdb_audpp_entry[i][3];
+ ret_value = true;
+ break;
+ }
+ }
+ return ret_value;
+}
+static ssize_t rtc_getsetabid_dbg_write(struct file *filp,
+ const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ struct get_abid write_abid;
+ unsigned short feat_id = 0;
+ rtc_acdb.valid_abid = false;
+
+ if (copy_from_user(&write_abid, \
+ (void *)ubuf, sizeof(struct get_abid))) {
+ MM_ERR("ACDB DATA WRITE - INVALID READ LEN\n");
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_LEN;
+ return cnt;
+ }
+ MM_DBG("SET ABID : Cmd ID: %d Device:%d ABID:%d IID : %d cnt: %d\n",\
+ write_abid.cmd_id, write_abid.acdb_id,\
+ write_abid.set_abid, write_abid.set_iid, cnt);
+ if (write_abid.acdb_id > ACDB_ID_MAX ||
+ write_abid.acdb_id < ACDB_ID_HANDSET_SPKR){
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_DEVICE;
+ return cnt;
+ }
+
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_ABID;
+ rtc_acdb.abid = write_abid.set_abid;
+ if (get_feature_id(write_abid.set_abid, \
+ write_abid.set_iid, &feat_id)) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ rtc_acdb.cmd_id = write_abid.cmd_id;
+ rtc_acdb.acdb_id = write_abid.acdb_id;
+ rtc_acdb.set_abid = feat_id;
+ rtc_acdb.valid_abid = true;
+ rtc_acdb.set_iid = write_abid.set_iid;
+ }
+ return cnt;
+}
+static ssize_t rtc_getsetabid_dbg_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ static char buffer[1024];
+ int n = 0;
+ u32 msg = rtc_acdb.err;
+ memcpy(buffer, &rtc_acdb.cmd_id, sizeof(struct get_abid));
+ memcpy(buffer+16, &msg, 4);
+ n = 20;
+ MM_INFO("SET ABID : Cmd ID: %x Device:%x ABID:%x IID : %x Err: %d\n",\
+ rtc_acdb.cmd_id, rtc_acdb.acdb_id, rtc_acdb.set_abid,\
+ rtc_acdb.set_iid, rtc_acdb.err);
+ return simple_read_from_buffer(buf, count, ppos, buffer, n);
+}
+
+static int rtc_getsetabid_data_dbg_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ MM_INFO("GET-SET ABID DATA Open debug intf %s\n",
+ (char *) file->private_data);
+ return 0;
+}
+
+void acdb_rtc_set_err(u32 err_code)
+{
+ if (rtc_acdb.err == ACDB_RTC_PENDING_RESPONSE) {
+ if (err_code == 0xFFFF) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ MM_INFO("RTC READ SUCCESS---\n");
+ } else if (err_code == 0) {
+ rtc_acdb.err = ACDB_RTC_DSP_FAILURE;
+ MM_INFO("RTC READ FAIL---\n");
+ } else if (err_code == 1) {
+ rtc_acdb.err = ACDB_RTC_DSP_FEATURE_NOT_AVAILABLE;
+ MM_INFO("RTC READ FEAT UNAVAILABLE---\n");
+ } else {
+ rtc_acdb.err = ACDB_RTC_DSP_FAILURE;
+ MM_INFO("RTC Err CODE---\n");
+ }
+ } else {
+ rtc_acdb.err = ACDB_RTC_DSP_FAILURE;
+ MM_ERR("RTC Err code Invalid State\n");
+ }
+ wake_up(&rtc_acdb.wait);
+}
+
+static ssize_t rtc_getsetabid_data_dbg_read(struct file *file,
+ char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ static char buffer[PMEM_RTC_ACDB_QUERY_MEM];
+ int rc, n = 0;
+ int counter = 0;
+ struct rtc_acdb_pmem *rtc_read = &rtc_acdb.rtc_read;
+ memset(&buffer, 0, PMEM_RTC_ACDB_QUERY_MEM);
+
+ if (rtc_acdb.valid_abid != true) {
+ MM_ERR("ACDB DATA READ ---INVALID ABID\n");
+ n = 0;
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_ABID;
+ } else {
+ if (PMEM_RTC_ACDB_QUERY_MEM < count) {
+ MM_ERR("ACDB DATA READ ---"\
+ "INVALID READ LEN %x\n", count);
+ n = 0;
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_LEN;
+ } else {
+ rtc_acdb.err = ACDB_RTC_PENDING_RESPONSE;
+ if (rtc_read->viraddr != NULL) {
+ memset(rtc_read->viraddr,
+ 0, PMEM_RTC_ACDB_QUERY_MEM);
+ }
+ if (rtc_acdb.tx_rx_ctl == ACDB_RTC_RX) {
+ struct rtc_audpp_read_data rtc_read_cmd;
+ rtc_read_cmd.cmd_id =
+ AUDPP_CMD_PP_FEAT_QUERY_PARAMS;
+ rtc_read_cmd.obj_id =
+ AUDPP_CMD_COPP_STREAM;
+ rtc_read_cmd.feature_id = rtc_acdb.set_abid;
+ rtc_read_cmd.extbufsizemsw =
+ EXTRACT_HIGH_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_read_cmd.extbufsizelsw =
+ EXTRACT_LOW_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_read_cmd.extpart = 0x0000;
+ rtc_read_cmd.extbufstartmsw =
+ EXTRACT_HIGH_WORD(rtc_read->phys);
+ rtc_read_cmd.extbufstartlsw =
+ EXTRACT_LOW_WORD(rtc_read->phys);
+ rc = audpp_send_queue2(&rtc_read_cmd,
+ sizeof(rtc_read_cmd));
+ } else if (rtc_acdb.tx_rx_ctl == ACDB_RTC_TX) {
+ struct rtc_audpreproc_read_data rtc_audpreproc;
+ rtc_audpreproc.cmd_id =
+ AUDPREPROC_CMD_FEAT_QUERY_PARAMS;
+ rtc_audpreproc.feature_id = rtc_acdb.set_abid;
+ /*AUDREC1 is used for pcm recording */
+ rtc_audpreproc.stream_id = 1;
+ rtc_audpreproc.extbufsizemsw =
+ EXTRACT_HIGH_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_audpreproc.extbufsizelsw =
+ EXTRACT_LOW_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_audpreproc.extpart = 0x0000;
+ rtc_audpreproc.extbufstartmsw =
+ EXTRACT_HIGH_WORD(rtc_read->phys);
+ rtc_audpreproc.extbufstartlsw =
+ EXTRACT_LOW_WORD(rtc_read->phys);
+ rc = audpreproc_send_preproccmdqueue(
+ &rtc_audpreproc,\
+ sizeof(rtc_audpreproc));
+ MM_INFO("ACDB READ Command RC --->%x,"\
+ "stream_id %x\n", rc,
+ acdb_data.preproc_stream_id);
+ }
+ rc = wait_event_timeout(rtc_acdb.wait,
+ (rtc_acdb.err !=
+ ACDB_RTC_PENDING_RESPONSE),
+ msecs_to_jiffies(RTC_MAX_TIMEOUT));
+ MM_INFO("ACDB READ ACK Count = %x Err = %x\n",
+ count, rtc_acdb.err);
+ {
+ if (rtc_acdb.err == ACDB_RTC_SUCCESS
+ && rtc_read->viraddr != NULL) {
+ memcpy(buffer, rtc_read->viraddr, count);
+ n = count;
+ while (counter < count) {
+ MM_DBG("%x", \
+ rtc_read->viraddr[counter]);
+ counter++;
+ }
+ }
+ }
+ }
+ }
+ return simple_read_from_buffer(buf, count, ppos, buffer, n);
+}
+
+static bool acdb_set_tx_rtc(const char *ubuf, size_t writecount)
+{
+ audpreproc_cmd_cfg_iir_tuning_filter_params *preproc_iir;
+ audpreproc_cmd_cfg_agc_params *preproc_agc;
+ audpreproc_cmd_cfg_ns_params *preproc_ns;
+ s32 result = 0;
+ bool retval = false;
+ unsigned short iircmdsize =
+ sizeof(audpreproc_cmd_cfg_iir_tuning_filter_params);
+ unsigned short iircmdid = AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
+
+ rtc_acdb.err = ACDB_RTC_ERR_UNKNOWN_FAILURE;
+
+ switch (rtc_acdb.set_abid) {
+
+ case AUDPREPROC_CMD_CFG_AGC_PARAMS:
+ {
+ preproc_agc = kmalloc(sizeof(\
+ audpreproc_cmd_cfg_agc_params),\
+ GFP_KERNEL);
+ if ((sizeof(audpreproc_cmd_cfg_agc_params) -\
+ (sizeof(unsigned short)))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "AGC TX writecount > DSP struct\n");
+ } else {
+ if (preproc_agc != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)preproc_agc;
+ offset = offsetof(\
+ audpreproc_cmd_cfg_agc_params,\
+ tx_agc_param_mask);
+ offset_addr = (unsigned short *)(base + offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ preproc_agc->cmd_id =
+ AUDPREPROC_CMD_CFG_AGC_PARAMS;
+
+ result = audpreproc_dsp_set_agc(
+ preproc_agc,
+ sizeof(\
+ audpreproc_cmd_cfg_agc_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "send AGC data to "\
+ "preproc)\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "GC Tx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "AGC TX kalloc Failed LEN\n");
+ }
+ }
+ if (preproc_agc != NULL)
+ kfree(preproc_agc);
+ break;
+ }
+ case AUDPREPROC_CMD_CFG_NS_PARAMS:
+ {
+
+ preproc_ns = kmalloc(sizeof(\
+ audpreproc_cmd_cfg_ns_params),\
+ GFP_KERNEL);
+ if ((sizeof(audpreproc_cmd_cfg_ns_params) -\
+ (sizeof(unsigned short)))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "NS TX writecount > DSP struct\n");
+ } else {
+ if (preproc_ns != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)preproc_ns;
+ offset = offsetof(\
+ audpreproc_cmd_cfg_ns_params,\
+ ec_mode_new);
+ offset_addr = (unsigned short *)(base + offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ preproc_ns->cmd_id =
+ AUDPREPROC_CMD_CFG_NS_PARAMS;
+ result = audpreproc_dsp_set_ns(
+ preproc_ns,
+ sizeof(\
+ audpreproc_cmd_cfg_ns_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send "\
+ "NS data to preproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---NS Tx "\
+ "copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --NS TX "\
+ "kalloc Failed LEN\n");
+ }
+ }
+ if (preproc_ns != NULL)
+ kfree(preproc_ns);
+ break;
+ }
+ case AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS:
+ {
+
+ preproc_iir = kmalloc(sizeof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params),\
+ GFP_KERNEL);
+ if ((sizeof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params)-\
+ (sizeof(unsigned short)))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --IIR TX writecount "\
+ "> DSP struct\n");
+ } else {
+ if (preproc_iir != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)preproc_iir;
+ offset = offsetof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params,\
+ active_flag);
+ offset_addr = (unsigned short *)(base + \
+ offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ preproc_iir->cmd_id = iircmdid;
+ result = audpreproc_dsp_set_iir(\
+ preproc_iir,
+ iircmdsize);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send "\
+ "IIR data to preproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---IIR Tx "\
+ "copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --IIR TX kalloc "\
+ "Failed LEN\n");
+ }
+ }
+ if (preproc_iir != NULL)
+ kfree(preproc_iir);
+ break;
+ }
+ }
+ return retval;
+}
+
+static bool acdb_set_rx_rtc(const char *ubuf, size_t writecount)
+{
+
+ audpp_cmd_cfg_object_params_volume *volpan_config;
+ audpp_cmd_cfg_object_params_mbadrc *mbadrc_config;
+ struct acdb_block_mbadrc_rtc *acdb_mbadrc_rtc;
+ audpp_cmd_cfg_object_params_eqalizer *eq_config;
+ audpp_cmd_cfg_object_params_pcm *iir_config;
+ struct rtc_acdb_pmem *rtc_write = &rtc_acdb.rtc_write;
+ s32 result = 0;
+ bool retval = false;
+
+ switch (rtc_acdb.set_abid) {
+ case AUDPP_CMD_VOLUME_PAN:
+ {
+ volpan_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_volume),\
+ GFP_KERNEL);
+ if ((sizeof(audpp_cmd_cfg_object_params_volume) -\
+ sizeof(audpp_cmd_cfg_object_params_common))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE -- "\
+ "VolPan writecount > DSP struct\n");
+ } else {
+ if (volpan_config != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)volpan_config;
+ offset = offsetof(\
+ audpp_cmd_cfg_object_params_volume,\
+ volume);
+ offset_addr = (unsigned short *)(base+offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ MM_ERR("ACDB RX WRITE DATA: "\
+ "AUDPP_CMD_VOLUME_PAN\n");
+ result = audpp_set_volume_and_pan(
+ COMMON_OBJ_ID,
+ volpan_config->volume,
+ volpan_config->pan);
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "send VOLPAN data to"
+ " postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "Vol Pan kalloc Failed LEN\n");
+ }
+ }
+ if (volpan_config != NULL)
+ kfree(volpan_config);
+ break;
+ }
+
+ case AUDPP_CMD_IIR_TUNING_FILTER:
+ {
+ iir_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_pcm),\
+ GFP_KERNEL);
+ if ((sizeof(audpp_cmd_cfg_object_params_pcm) -\
+ sizeof(audpp_cmd_cfg_object_params_common))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "IIR RX writecount > DSP struct\n");
+ } else {
+ if (iir_config != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)iir_config;
+ offset = offsetof(\
+ audpp_cmd_cfg_object_params_pcm,\
+ active_flag);
+ offset_addr = (unsigned short *)(base+offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ MM_ERR("ACDB RX WRITE DATA:"\
+ "AUDPP_CMD_IIR_TUNING_FILTER\n");
+ result = audpp_dsp_set_rx_iir(
+ COMMON_OBJ_ID,
+ iir_config->active_flag,\
+ iir_config);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send"\
+ "IIR data to"\
+ "postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "IIR Rx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "acdb_iir_block kalloc Failed LEN\n");
+ }
+ }
+ if (iir_config != NULL)
+ kfree(iir_config);
+ break;
+ }
+ case AUDPP_CMD_EQUALIZER:
+ {
+ eq_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_eqalizer),\
+ GFP_KERNEL);
+ if ((sizeof(audpp_cmd_cfg_object_params_eqalizer) -\
+ sizeof(audpp_cmd_cfg_object_params_common))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "EQ RX writecount > DSP struct\n");
+ } else {
+ if (eq_config != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)eq_config;
+ offset = offsetof(\
+ audpp_cmd_cfg_object_params_eqalizer,\
+ eq_flag);
+ offset_addr = (unsigned short *)(base+offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ MM_ERR("ACDB RX WRITE"\
+ "DATA:AUDPP_CMD_EQUALIZER\n");
+ result = audpp_dsp_set_eq(
+ COMMON_OBJ_ID,
+ eq_config->eq_flag,\
+ eq_config);
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "send EQ data to postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "EQ Rx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "EQ kalloc Failed LEN\n");
+ }
+ }
+ if (eq_config != NULL)
+ kfree(eq_config);
+ break;
+ }
+
+ case AUDPP_CMD_MBADRC:
+ {
+ acdb_mbadrc_rtc = kmalloc(sizeof(struct \
+ acdb_block_mbadrc_rtc),\
+ GFP_KERNEL);
+ mbadrc_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_mbadrc),\
+ GFP_KERNEL);
+ if (mbadrc_config != NULL && acdb_mbadrc_rtc != NULL) {
+ if ((copy_from_user(acdb_mbadrc_rtc,\
+ (void *)ubuf,
+ sizeof(struct acdb_block_mbadrc_rtc)))
+ == 0x00) {
+
+ memset(mbadrc_config, 0,
+ sizeof(\
+ audpp_cmd_cfg_object_params_mbadrc));
+
+ mbadrc_config->enable =
+ acdb_mbadrc_rtc->enable;
+ mbadrc_config->num_bands =
+ acdb_mbadrc_rtc->num_bands;
+ mbadrc_config->down_samp_level =
+ acdb_mbadrc_rtc->down_samp_level;
+ mbadrc_config->adrc_delay =
+ acdb_mbadrc_rtc->adrc_delay;
+ memcpy(mbadrc_config->adrc_band,\
+ acdb_mbadrc_rtc->adrc_band,\
+ AUDPP_MAX_MBADRC_BANDS *\
+ sizeof(struct adrc_config));
+ if (mbadrc_config->num_bands > 1) {
+ mbadrc_config->ext_buf_size =
+ (97 * 2) + (33 * 2 * \
+ (mbadrc_config->num_bands - 2));
+ }
+ mbadrc_config->ext_partition = 0;
+ mbadrc_config->ext_buf_lsw =
+ (u16) EXTRACT_LOW_WORD(\
+ rtc_write->phys);
+ mbadrc_config->ext_buf_msw =
+ (u16) EXTRACT_HIGH_WORD(\
+ rtc_write->phys);
+ memcpy(rtc_write->viraddr,
+ acdb_mbadrc_rtc->ext_buff,
+ (196*sizeof(signed int)));
+ result = audpp_dsp_set_mbadrc(
+ COMMON_OBJ_ID,
+ mbadrc_config->enable,
+ mbadrc_config);
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "Send MBADRC data "\
+ "to postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "MBADRC Rx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --MBADRC kalloc Failed LEN\n");
+ }
+ if (mbadrc_config != NULL)
+ kfree(mbadrc_config);
+ if (acdb_mbadrc_rtc != NULL)
+ kfree(acdb_mbadrc_rtc);
+ break;
+ }
+ }
+ return retval;
+}
+static ssize_t rtc_getsetabid_data_dbg_write(struct file *filp,
+ const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ if (rtc_acdb.valid_abid != true) {
+ MM_INFO("ACDB DATA READ ---INVALID ABID\n");
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_ABID;
+ } else {
+ if (rtc_acdb.tx_rx_ctl == ACDB_RTC_RX) {
+ if (acdb_set_rx_rtc(ubuf, cnt)) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ } else {
+ rtc_acdb.err = ACDB_RTC_ERR_UNKNOWN_FAILURE;
+ cnt = 0;
+ }
+ } else if (rtc_acdb.tx_rx_ctl == ACDB_RTC_TX) {
+ if (acdb_set_tx_rtc(ubuf, cnt)) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ } else {
+ rtc_acdb.err = ACDB_RTC_ERR_UNKNOWN_FAILURE;
+ cnt = 0;
+ }
+ }
+ }
+ return cnt;
+}
+
+
+static const struct file_operations rtc_acdb_data_debug_fops = {
+ .open = rtc_getsetabid_data_dbg_open,
+ .write = rtc_getsetabid_data_dbg_write,
+ .read = rtc_getsetabid_data_dbg_read
+};
+
+static const struct file_operations rtc_acdb_debug_fops = {
+ .open = rtc_getsetabid_dbg_open,
+ .write = rtc_getsetabid_dbg_write,
+ .read = rtc_getsetabid_dbg_read
+};
+
+static void rtc_acdb_deinit(void)
+{
+ struct rtc_acdb_pmem *rtc_read = &rtc_acdb.rtc_read;
+ struct rtc_acdb_pmem *rtc_write = &rtc_acdb.rtc_write;
+ if (get_set_abid_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_dentry);
+ }
+
+ if (get_set_abid_data_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_data_dentry);
+ }
+ rtc_acdb.abid = 0;
+ rtc_acdb.acdb_id = 0;
+ rtc_acdb.cmd_id = 0;
+ rtc_acdb.err = 1;
+ rtc_acdb.set_abid = 0;
+ rtc_acdb.set_iid = 0;
+ rtc_acdb.tx_rx_ctl = 0;
+ rtc_acdb.valid_abid = false;
+
+ if (rtc_read->viraddr != NULL || ((void *)rtc_read->phys) != NULL) {
+ iounmap(rtc_read->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_read->phys);
+ }
+ if (rtc_write->viraddr != NULL || ((void *)rtc_write->phys) != NULL) {
+ iounmap(rtc_write->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_write->phys);
+ }
+}
+
+static bool rtc_acdb_init(void)
+{
+ struct rtc_acdb_pmem *rtc_read = &rtc_acdb.rtc_read;
+ struct rtc_acdb_pmem *rtc_write = &rtc_acdb.rtc_write;
+ s32 result = 0;
+ char name[sizeof "get_set_abid"+1];
+ char name1[sizeof "get_set_abid_data"+1];
+ rtc_acdb.abid = 0;
+ rtc_acdb.acdb_id = 0;
+ rtc_acdb.cmd_id = 0;
+ rtc_acdb.err = 1;
+ rtc_acdb.set_abid = 0;
+ rtc_acdb.set_iid = 0;
+ rtc_acdb.valid_abid = false;
+ rtc_acdb.tx_rx_ctl = 0;
+
+ snprintf(name, sizeof name, "get_set_abid");
+ get_set_abid_dentry = debugfs_create_file(name,
+ S_IFREG | S_IRUGO | S_IWUGO,
+ NULL, NULL, &rtc_acdb_debug_fops);
+ if (IS_ERR(get_set_abid_dentry)) {
+ MM_ERR("SET GET ABID debugfs_create_file failed\n");
+ return false;
+ }
+
+ snprintf(name1, sizeof name1, "get_set_abid_data");
+ get_set_abid_data_dentry = debugfs_create_file(name1,
+ S_IFREG | S_IRUGO | S_IWUGO,
+ NULL, NULL,
+ &rtc_acdb_data_debug_fops);
+ if (IS_ERR(get_set_abid_data_dentry)) {
+ MM_ERR("SET GET ABID DATA"\
+ " debugfs_create_file failed\n");
+ return false;
+ }
+
+ rtc_read->phys = allocate_contiguous_ebi_nomap(PMEM_RTC_ACDB_QUERY_MEM,
+ SZ_4K);
+
+ if (!rtc_read->phys) {
+ MM_ERR("ACDB Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_read->map_v_rtc = ioremap(rtc_read->phys,
+ PMEM_RTC_ACDB_QUERY_MEM);
+
+ if (IS_ERR(rtc_read->map_v_rtc)) {
+ MM_ERR("ACDB Could not map physical address\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_read->viraddr = rtc_read->map_v_rtc;
+ memset(rtc_read->viraddr, 0, PMEM_RTC_ACDB_QUERY_MEM);
+
+ rtc_write->phys = allocate_contiguous_ebi_nomap(PMEM_RTC_ACDB_QUERY_MEM,
+ SZ_4K);
+
+ if (!rtc_write->phys) {
+ MM_ERR("ACDB Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_write->map_v_rtc = ioremap(rtc_write->phys,
+ PMEM_RTC_ACDB_QUERY_MEM);
+
+ if (IS_ERR(rtc_write->map_v_rtc)) {
+ MM_ERR("ACDB Could not map physical address\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_write->viraddr = rtc_write->map_v_rtc;
+ memset(rtc_write->viraddr, 0, PMEM_RTC_ACDB_QUERY_MEM);
+ init_waitqueue_head(&rtc_acdb.wait);
+ return true;
+error:
+ MM_DBG("INIT RTC FAILED REMOVING RTC DEBUG FS\n");
+ if (get_set_abid_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_dentry);
+ }
+
+ if (get_set_abid_data_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_data_dentry);
+ }
+ if (rtc_read->viraddr != NULL || ((void *)rtc_read->phys) != NULL) {
+ iounmap(rtc_read->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_read->phys);
+ }
+ if (rtc_write->viraddr != NULL || ((void *)rtc_write->phys) != NULL) {
+ iounmap(rtc_write->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_write->phys);
+ }
+ return false;
+}
+#else
+void acdb_rtc_set_err(u32 err_code)
+{
+ return 0
+}
+#endif /*CONFIG_DEBUG_FS*/
+static s32 acdb_set_calibration_blk(unsigned long arg)
+{
+ struct acdb_cmd_device acdb_cmd;
+ s32 result = 0;
+
+ MM_DBG("acdb_set_calibration_blk\n");
+ if (copy_from_user(&acdb_cmd, (struct acdb_cmd_device *)arg,
+ sizeof(acdb_cmd))) {
+ MM_ERR("Failed copy command struct from user in"\
+ "acdb_set_calibration_blk\n");
+ return -EFAULT;
+ }
+ acdb_cmd.phys_buf = (u32 *)acdb_data.paddr;
+
+ MM_DBG("acdb_cmd.phys_buf %x\n", (u32)acdb_cmd.phys_buf);
+
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_data.acdb_result,
+ sizeof(acdb_data.acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device Set RPC failure"\
+ " result = %d\n", result);
+ return -EINVAL;
+ } else {
+ MM_ERR("ACDB=> Device Set RPC success\n");
+ if (acdb_data.acdb_result.result == ACDB_RES_SUCCESS)
+ MM_DBG("ACDB_SET_DEVICE Success\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_FAILURE)
+ MM_ERR("ACDB_SET_DEVICE Failure\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_BADPARM)
+ MM_ERR("ACDB_SET_DEVICE BadParams\n");
+ else
+ MM_ERR("Unknown error\n");
+ }
+ return result;
+}
+
+static s32 acdb_get_calibration_blk(unsigned long arg)
+{
+ s32 result = 0;
+ struct acdb_cmd_device acdb_cmd;
+
+ MM_DBG("acdb_get_calibration_blk\n");
+
+ if (copy_from_user(&acdb_cmd, (struct acdb_cmd_device *)arg,
+ sizeof(acdb_cmd))) {
+ MM_ERR("Failed copy command struct from user in"\
+ "acdb_get_calibration_blk\n");
+ return -EFAULT;
+ }
+ acdb_cmd.phys_buf = (u32 *)acdb_data.paddr;
+ MM_ERR("acdb_cmd.phys_buf %x\n", (u32)acdb_cmd.phys_buf);
+
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_data.acdb_result,
+ sizeof(acdb_data.acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device Get RPC failure"\
+ " result = %d\n", result);
+ return -EINVAL;
+ } else {
+ MM_ERR("ACDB=> Device Get RPC Success\n");
+ if (acdb_data.acdb_result.result == ACDB_RES_SUCCESS)
+ MM_DBG("ACDB_GET_DEVICE Success\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_FAILURE)
+ MM_ERR("ACDB_GET_DEVICE Failure\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_BADPARM)
+ MM_ERR("ACDB_GET_DEVICE BadParams\n");
+ else
+ MM_ERR("Unknown error\n");
+ }
+ return result;
+}
+
+static int audio_acdb_open(struct inode *inode, struct file *file)
+{
+ MM_DBG("%s\n", __func__);
+ return 0;
+}
+static int audio_acdb_release(struct inode *inode, struct file *file)
+{
+ MM_DBG("%s\n", __func__);
+ return 0;
+}
+
+static long audio_acdb_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int rc = 0;
+ unsigned long flags = 0;
+ struct msm_audio_pmem_info info;
+
+ MM_DBG("%s\n", __func__);
+
+ switch (cmd) {
+ case AUDIO_SET_EQ:
+ MM_DBG("IOCTL SET_EQ_CONFIG\n");
+ if (copy_from_user(&acdb_data.eq.num_bands, (void *) arg,
+ sizeof(acdb_data.eq) -
+ (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2))) {
+ rc = -EFAULT;
+ break;
+ }
+ spin_lock_irqsave(&acdb_data.dsp_lock, flags);
+ rc = audpp_dsp_set_eq(COMMON_OBJ_ID, 1,
+ &acdb_data.eq);
+ if (rc < 0)
+ MM_ERR("AUDPP returned err =%d\n", rc);
+ spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
+ break;
+ case AUDIO_REGISTER_PMEM:
+ MM_DBG("AUDIO_REGISTER_PMEM\n");
+ if (copy_from_user(&info, (void *) arg, sizeof(info))) {
+ MM_ERR("Cannot copy from user\n");
+ return -EFAULT;
+ }
+ rc = get_pmem_file(info.fd, &acdb_data.paddr,
+ &acdb_data.kvaddr,
+ &acdb_data.pmem_len,
+ &acdb_data.file);
+ if (rc == 0)
+ acdb_data.pmem_fd = info.fd;
+ break;
+ case AUDIO_DEREGISTER_PMEM:
+ if (acdb_data.pmem_fd)
+ put_pmem_file(acdb_data.file);
+ break;
+ case AUDIO_SET_ACDB_BLK:
+ MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
+ rc = acdb_set_calibration_blk(arg);
+ break;
+ case AUDIO_GET_ACDB_BLK:
+ MM_DBG("IOiCTL AUDIO_GET_ACDB_BLK\n");
+ rc = acdb_get_calibration_blk(arg);
+ break;
+ default:
+ MM_DBG("Unknown IOCTL%d\n", cmd);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+static const struct file_operations acdb_fops = {
+ .owner = THIS_MODULE,
+ .open = audio_acdb_open,
+ .release = audio_acdb_release,
+ .llseek = no_llseek,
+ .unlocked_ioctl = audio_acdb_ioctl
+};
+
+struct miscdevice acdb_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_acdb",
+ .fops = &acdb_fops,
+};
+
+static s32 acdb_get_calibration(void)
+{
+ struct acdb_cmd_get_device_table acdb_cmd;
+ s32 result = 0;
+ u32 iterations = 0;
+
+ MM_DBG("acdb state = %d\n", acdb_data.acdb_state);
+
+ acdb_cmd.command_id = ACDB_GET_DEVICE_TABLE;
+ acdb_cmd.device_id = acdb_data.device_info->acdb_id;
+ acdb_cmd.network_id = 0x0108B153;
+ acdb_cmd.sample_rate_id = acdb_data.device_info->sample_rate;
+ acdb_cmd.total_bytes = ACDB_BUF_SIZE;
+ acdb_cmd.phys_buf = (u32 *)acdb_data.phys_addr;
+ MM_DBG("device_id = %d, sampling_freq = %d\n",
+ acdb_cmd.device_id, acdb_cmd.sample_rate_id);
+
+ do {
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_data.acdb_result,
+ sizeof(acdb_data.acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device table RPC failure"\
+ " result = %d\n", result);
+ goto error;
+ }
+ /*following check is introduced to handle boot up race
+ condition between AUDCAL SW peers running on apps
+ and modem (ACDB_RES_BADSTATE indicates modem AUDCAL SW is
+ not in initialized sate) we need to retry to get ACDB
+ values*/
+ if (acdb_data.acdb_result.result == ACDB_RES_BADSTATE) {
+ msleep(500);
+ iterations++;
+ } else if (acdb_data.acdb_result.result == ACDB_RES_SUCCESS) {
+ MM_DBG("Modem query for acdb values is successful"\
+ " (iterations = %d)\n", iterations);
+ acdb_data.acdb_state |= CAL_DATA_READY;
+ return result;
+ } else {
+ MM_ERR("ACDB=> modem failed to fill acdb values,"\
+ " reuslt = %d, (iterations = %d)\n",
+ acdb_data.acdb_result.result,
+ iterations);
+ goto error;
+ }
+ } while (iterations < MAX_RETRY);
+ MM_ERR("ACDB=> AUDCAL SW on modem is not in intiailized state (%d)\n",
+ acdb_data.acdb_result.result);
+error:
+ result = -EINVAL;
+ return result;
+}
+
+s32 acdb_get_calibration_data(struct acdb_get_block *get_block)
+{
+ s32 result = -EINVAL;
+ struct acdb_cmd_device acdb_cmd;
+ struct acdb_result acdb_result;
+
+ MM_DBG("acdb_get_calibration_data\n");
+
+ acdb_cmd.command_id = ACDB_GET_DEVICE;
+ acdb_cmd.network_id = 0x0108B153;
+ acdb_cmd.device_id = get_block->acdb_id;
+ acdb_cmd.sample_rate_id = get_block->sample_rate_id;
+ acdb_cmd.interface_id = get_block->interface_id;
+ acdb_cmd.algorithm_block_id = get_block->algorithm_block_id;
+ acdb_cmd.total_bytes = get_block->total_bytes;
+ acdb_cmd.phys_buf = (u32 *)acdb_data.get_blk_paddr;
+
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_result,
+ sizeof(acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device Get RPC failure"\
+ " result = %d\n", result);
+ goto err_state;
+ } else {
+ MM_DBG("ACDB=> Device Get RPC Success\n");
+ if (acdb_result.result == ACDB_RES_SUCCESS) {
+ MM_DBG("ACDB_GET_DEVICE Success\n");
+ result = 0;
+ memcpy(get_block->buf_ptr, acdb_data.get_blk_kvaddr,
+ get_block->total_bytes);
+ } else if (acdb_result.result == ACDB_RES_FAILURE)
+ MM_ERR("ACDB_GET_DEVICE Failure\n");
+ else if (acdb_result.result == ACDB_RES_BADPARM)
+ MM_ERR("ACDB_GET_DEVICE BadParams\n");
+ else
+ MM_ERR("Unknown error\n");
+ }
+err_state:
+ return result;
+}
+EXPORT_SYMBOL(acdb_get_calibration_data);
+
+static u8 check_device_info_already_present(
+ struct dev_evt_msg device_info,
+ struct acdb_cache_node *acdb_cache_free_node)
+{
+ if ((device_info.sample_rate ==
+ acdb_cache_free_node->device_info.\
+ sample_rate) &&
+ (device_info.acdb_id ==
+ acdb_cache_free_node->device_info.acdb_id)) {
+ MM_DBG("acdb values are already present\n");
+ /*if acdb state is not set for CAL_DATA_READY and node status
+ is filled, acdb state should be updated with CAL_DATA_READY
+ state*/
+ acdb_data.acdb_state |= CAL_DATA_READY;
+ return 1; /*node is present but status as filled*/
+ }
+ MM_DBG("copying device info into node\n");
+ /*as device information is not present in cache copy
+ the current device information into the node*/
+ memcpy(&acdb_cache_free_node->device_info,
+ &device_info, sizeof(device_info));
+ return 0; /*cant find the node*/
+}
+
+static struct acdb_iir_block *get_audpp_irr_block(void)
+{
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_IIR_RX) {
+ if (prs_hdr->iid == IID_AUDIO_IIR_COEFF)
+ return (struct acdb_iir_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+
+static s32 acdb_fill_audpp_iir(void)
+{
+ struct acdb_iir_block *acdb_iir;
+ s32 i = 0;
+
+ acdb_iir = get_audpp_irr_block();
+ if (acdb_iir == NULL) {
+ MM_ERR("unable to find audpp iir block returning\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.pp_iir, 0, sizeof(*acdb_data.pp_iir));
+
+ acdb_data.pp_iir->active_flag = acdb_iir->enable_flag;
+ acdb_data.pp_iir->num_bands = acdb_iir->stage_count;
+ for (; i < acdb_iir->stage_count; i++) {
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b0_filter_lsw =
+ acdb_iir->stages[i].b0_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b0_filter_msw =
+ acdb_iir->stages[i].b0_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b1_filter_lsw =
+ acdb_iir->stages[i].b1_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b1_filter_msw =
+ acdb_iir->stages[i].b1_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b2_filter_lsw =
+ acdb_iir->stages[i].b2_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b2_filter_msw =
+ acdb_iir->stages[i].b2_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a0_filter_lsw =
+ acdb_iir->stages_a[i].a1_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a0_filter_msw =
+ acdb_iir->stages_a[i].a1_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a1_filter_lsw =
+ acdb_iir->stages_a[i].a2_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a1_filter_msw =
+ acdb_iir->stages_a[i].a2_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ shift_factor_filter[i].shift_factor_0 =
+ acdb_iir->shift_factor[i];
+ acdb_data.pp_iir->params_filter.filter_4_params.pan_filter[i].
+ pan_filter_0 = acdb_iir->pan[i];
+ }
+ return 0;
+}
+
+static void extract_mbadrc(u32 *phy_addr, struct header *prs_hdr, u32 *index)
+{
+ if (prs_hdr->iid == IID_MBADRC_EXT_BUFF) {
+ MM_DBG("Got IID = IID_MBADRC_EXT_BUFF\n");
+ *phy_addr = acdb_data.phys_addr + *index +
+ sizeof(struct header);
+ memcpy(acdb_data.mbadrc_block.ext_buf,
+ (acdb_data.virt_addr + *index +
+ sizeof(struct header)), 196*2);
+ MM_DBG("phy_addr = %x\n", *phy_addr);
+ *index += prs_hdr->data_len + sizeof(struct header);
+ } else if (prs_hdr->iid == IID_MBADRC_BAND_CONFIG) {
+ MM_DBG("Got IID == IID_MBADRC_BAND_CONFIG\n");
+ memcpy(acdb_data.mbadrc_block.band_config, (acdb_data.virt_addr
+ + *index + sizeof(struct header)),
+ sizeof(struct mbadrc_band_config_type) *
+ acdb_data.mbadrc_block.parameters.\
+ mbadrc_num_bands);
+ *index += prs_hdr->data_len + sizeof(struct header);
+ } else if (prs_hdr->iid == IID_MBADRC_PARAMETERS) {
+ struct mbadrc_parameter *tmp;
+ tmp = (struct mbadrc_parameter *)(acdb_data.virt_addr + *index
+ + sizeof(struct header));
+ MM_DBG("Got IID == IID_MBADRC_PARAMETERS");
+ acdb_data.mbadrc_block.parameters.mbadrc_enable =
+ tmp->mbadrc_enable;
+ acdb_data.mbadrc_block.parameters.mbadrc_num_bands =
+ tmp->mbadrc_num_bands;
+ acdb_data.mbadrc_block.parameters.mbadrc_down_sample_level =
+ tmp->mbadrc_down_sample_level;
+ acdb_data.mbadrc_block.parameters.mbadrc_delay =
+ tmp->mbadrc_delay;
+ *index += prs_hdr->data_len + sizeof(struct header);
+ }
+}
+
+static void get_audpp_mbadrc_block(u32 *phy_addr)
+{
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_MBADRC_RX) {
+ if ((prs_hdr->iid == IID_MBADRC_EXT_BUFF)
+ || (prs_hdr->iid ==
+ IID_MBADRC_BAND_CONFIG)
+ || (prs_hdr->iid ==
+ IID_MBADRC_PARAMETERS)) {
+ extract_mbadrc(phy_addr, prs_hdr,
+ &index);
+ }
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+static s32 acdb_fill_audpp_mbadrc(void)
+{
+ u32 mbadrc_phys_addr = -1;
+ get_audpp_mbadrc_block(&mbadrc_phys_addr);
+ if (IS_ERR_VALUE(mbadrc_phys_addr)) {
+ MM_ERR("failed to get mbadrc block\n");
+ return -EINVAL;
+ }
+
+ memset(acdb_data.pp_mbadrc, 0, sizeof(*acdb_data.pp_mbadrc));
+
+ acdb_data.pp_mbadrc->enable = acdb_data.mbadrc_block.\
+ parameters.mbadrc_enable;
+ acdb_data.pp_mbadrc->num_bands =
+ acdb_data.mbadrc_block.\
+ parameters.mbadrc_num_bands;
+ acdb_data.pp_mbadrc->down_samp_level =
+ acdb_data.mbadrc_block.parameters.\
+ mbadrc_down_sample_level;
+ acdb_data.pp_mbadrc->adrc_delay =
+ acdb_data.mbadrc_block.parameters.\
+ mbadrc_delay;
+
+ if (acdb_data.mbadrc_block.parameters.mbadrc_num_bands > 1)
+ acdb_data.pp_mbadrc->ext_buf_size = (97 * 2) +
+ (33 * 2 * (acdb_data.mbadrc_block.parameters.\
+ mbadrc_num_bands - 2));
+
+ acdb_data.pp_mbadrc->ext_partition = 0;
+ acdb_data.pp_mbadrc->ext_buf_lsw = (u16)(mbadrc_phys_addr\
+ & 0xFFFF);
+ acdb_data.pp_mbadrc->ext_buf_msw = (u16)((mbadrc_phys_addr\
+ & 0xFFFF0000) >> 16);
+ memcpy(acdb_data.pp_mbadrc->adrc_band, acdb_data.mbadrc_block.\
+ band_config,
+ sizeof(struct mbadrc_band_config_type) *
+ acdb_data.mbadrc_block.parameters.mbadrc_num_bands);
+ return 0;
+}
+
+static s32 acdb_calibrate_audpp(void)
+{
+ s32 result = 0;
+
+ result = acdb_fill_audpp_iir();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpp_dsp_set_rx_iir(COMMON_OBJ_ID,
+ acdb_data.pp_iir->active_flag,
+ acdb_data.pp_iir);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send IIR data to postproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("AUDPP is calibrated with IIR parameters");
+ }
+ result = acdb_fill_audpp_mbadrc();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpp_dsp_set_mbadrc(COMMON_OBJ_ID,
+ acdb_data.pp_mbadrc->enable,
+ acdb_data.pp_mbadrc);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send MBADRC data to"\
+ " postproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("AUDPP is calibrated with MBADRC parameters");
+ }
+done:
+ return result;
+}
+
+static struct acdb_agc_block *get_audpreproc_agc_block(void)
+{
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_AGC_TX) {
+ if (prs_hdr->iid == IID_AUDIO_AGC_PARAMETERS) {
+ MM_DBG("GOT ABID_AUDIO_AGC_TX\n");
+ return (struct acdb_agc_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ }
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+static s32 acdb_fill_audpreproc_agc(void)
+{
+ struct acdb_agc_block *acdb_agc;
+
+ acdb_agc = get_audpreproc_agc_block();
+ if (!acdb_agc) {
+ MM_DBG("unable to find preproc agc parameters winding up\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.preproc_agc, 0, sizeof(*acdb_data.preproc_agc));
+ acdb_data.preproc_agc->cmd_id = AUDPREPROC_CMD_CFG_AGC_PARAMS;
+ /* 0xFE00 to configure all parameters */
+ acdb_data.preproc_agc->tx_agc_param_mask = 0xFFFF;
+ if (acdb_agc->enable_status)
+ acdb_data.preproc_agc->tx_agc_enable_flag =
+ AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA;
+ else
+ acdb_data.preproc_agc->tx_agc_enable_flag =
+ AUDPREPROC_CMD_TX_AGC_ENA_FLAG_DIS;
+
+ acdb_data.preproc_agc->comp_rlink_static_gain =
+ acdb_agc->comp_rlink_static_gain;
+ acdb_data.preproc_agc->comp_rlink_aig_flag =
+ acdb_agc->comp_rlink_aig_flag;
+ acdb_data.preproc_agc->expander_rlink_th =
+ acdb_agc->exp_rlink_threshold;
+ acdb_data.preproc_agc->expander_rlink_slope =
+ acdb_agc->exp_rlink_slope;
+ acdb_data.preproc_agc->compressor_rlink_th =
+ acdb_agc->comp_rlink_threshold;
+ acdb_data.preproc_agc->compressor_rlink_slope =
+ acdb_agc->comp_rlink_slope;
+
+ /* 0xFFF0 to configure all parameters */
+ acdb_data.preproc_agc->tx_adc_agc_param_mask = 0xFFFF;
+
+ acdb_data.preproc_agc->comp_rlink_aig_attackk =
+ acdb_agc->comp_rlink_aig_attack_k;
+ acdb_data.preproc_agc->comp_rlink_aig_leak_down =
+ acdb_agc->comp_rlink_aig_leak_down;
+ acdb_data.preproc_agc->comp_rlink_aig_leak_up =
+ acdb_agc->comp_rlink_aig_leak_up;
+ acdb_data.preproc_agc->comp_rlink_aig_max =
+ acdb_agc->comp_rlink_aig_max;
+ acdb_data.preproc_agc->comp_rlink_aig_min =
+ acdb_agc->comp_rlink_aig_min;
+ acdb_data.preproc_agc->comp_rlink_aig_releasek =
+ acdb_agc->comp_rlink_aig_release_k;
+ acdb_data.preproc_agc->comp_rlink_aig_leakrate_fast =
+ acdb_agc->comp_rlink_aig_sm_leak_rate_fast;
+ acdb_data.preproc_agc->comp_rlink_aig_leakrate_slow =
+ acdb_agc->comp_rlink_aig_sm_leak_rate_slow;
+ acdb_data.preproc_agc->comp_rlink_attackk_msw =
+ acdb_agc->comp_rlink_attack_k_msw;
+ acdb_data.preproc_agc->comp_rlink_attackk_lsw =
+ acdb_agc->comp_rlink_attack_k_lsw;
+ acdb_data.preproc_agc->comp_rlink_delay =
+ acdb_agc->comp_rlink_delay;
+ acdb_data.preproc_agc->comp_rlink_releasek_msw =
+ acdb_agc->comp_rlink_release_k_msw;
+ acdb_data.preproc_agc->comp_rlink_releasek_lsw =
+ acdb_agc->comp_rlink_release_k_lsw;
+ acdb_data.preproc_agc->comp_rlink_rms_tav =
+ acdb_agc->comp_rlink_rms_trav;
+ return 0;
+}
+
+static struct acdb_iir_block *get_audpreproc_irr_block(void)
+{
+
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_IIR_TX) {
+ if (prs_hdr->iid == IID_AUDIO_IIR_COEFF)
+ return (struct acdb_iir_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+
+static s32 acdb_fill_audpreproc_iir(void)
+{
+ struct acdb_iir_block *acdb_iir;
+
+
+ acdb_iir = get_audpreproc_irr_block();
+ if (!acdb_iir) {
+ MM_DBG("unable to find preproc iir parameters winding up\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.preproc_iir, 0, sizeof(*acdb_data.preproc_iir));
+
+ acdb_data.preproc_iir->cmd_id =
+ AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
+ acdb_data.preproc_iir->active_flag = acdb_iir->enable_flag;
+ acdb_data.preproc_iir->num_bands = acdb_iir->stage_count;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter0_lsw =
+ acdb_iir->stages[0].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter0_msw =
+ acdb_iir->stages[0].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter0_lsw =
+ acdb_iir->stages[0].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter0_msw =
+ acdb_iir->stages[0].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter0_lsw =
+ acdb_iir->stages[0].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter0_msw =
+ acdb_iir->stages[0].b2_hi;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter1_lsw =
+ acdb_iir->stages[1].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter1_msw =
+ acdb_iir->stages[1].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter1_lsw =
+ acdb_iir->stages[1].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter1_msw =
+ acdb_iir->stages[1].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter1_lsw =
+ acdb_iir->stages[1].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter1_msw =
+ acdb_iir->stages[1].b2_hi;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter2_lsw =
+ acdb_iir->stages[2].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter2_msw =
+ acdb_iir->stages[2].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter2_lsw =
+ acdb_iir->stages[2].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter2_msw =
+ acdb_iir->stages[2].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter2_lsw =
+ acdb_iir->stages[2].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter2_msw =
+ acdb_iir->stages[2].b2_hi;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter3_lsw =
+ acdb_iir->stages[3].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter3_msw =
+ acdb_iir->stages[3].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter3_lsw =
+ acdb_iir->stages[3].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter3_msw =
+ acdb_iir->stages[3].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter3_lsw =
+ acdb_iir->stages[3].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter3_msw =
+ acdb_iir->stages[3].b2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter0_lsw =
+ acdb_iir->stages_a[0].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter0_msw =
+ acdb_iir->stages_a[0].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter0_lsw =
+ acdb_iir->stages_a[0].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter0_msw =
+ acdb_iir->stages_a[0].a2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter1_lsw =
+ acdb_iir->stages_a[1].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter1_msw =
+ acdb_iir->stages_a[1].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter1_lsw =
+ acdb_iir->stages_a[1].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter1_msw =
+ acdb_iir->stages_a[1].a2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter2_lsw =
+ acdb_iir->stages_a[2].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter2_msw =
+ acdb_iir->stages_a[2].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter2_lsw =
+ acdb_iir->stages_a[2].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter2_msw =
+ acdb_iir->stages_a[2].a2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter3_lsw =
+ acdb_iir->stages_a[3].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter3_msw =
+ acdb_iir->stages_a[3].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter3_lsw =
+ acdb_iir->stages_a[3].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter3_msw =
+ acdb_iir->stages_a[3].a2_hi;
+
+ acdb_data.preproc_iir->shift_factor_filter0 =
+ acdb_iir->shift_factor[0];
+ acdb_data.preproc_iir->shift_factor_filter1 =
+ acdb_iir->shift_factor[1];
+ acdb_data.preproc_iir->shift_factor_filter2 =
+ acdb_iir->shift_factor[2];
+ acdb_data.preproc_iir->shift_factor_filter3 =
+ acdb_iir->shift_factor[3];
+
+ acdb_data.preproc_iir->channel_selected0 =
+ acdb_iir->pan[0];
+ acdb_data.preproc_iir->channel_selected1 =
+ acdb_iir->pan[1];
+ acdb_data.preproc_iir->channel_selected2 =
+ acdb_iir->pan[2];
+ acdb_data.preproc_iir->channel_selected3 =
+ acdb_iir->pan[3];
+ return 0;
+}
+
+static struct acdb_ns_tx_block *get_audpreproc_ns_block(void)
+{
+
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_NS_TX) {
+ if (prs_hdr->iid == IID_NS_PARAMETERS)
+ return (struct acdb_ns_tx_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+static s32 acdb_fill_audpreproc_ns(void)
+{
+ struct acdb_ns_tx_block *acdb_ns;
+ /* TO DO: do we enable_status_filled */
+ acdb_ns = get_audpreproc_ns_block();
+ if (!acdb_ns) {
+ MM_DBG("unable to find preproc ns parameters winding up\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.preproc_ns, 0, sizeof(*acdb_data.preproc_ns));
+ acdb_data.preproc_ns->cmd_id = AUDPREPROC_CMD_CFG_NS_PARAMS;
+
+ acdb_data.preproc_ns->ec_mode_new = acdb_ns->ec_mode_new;
+ acdb_data.preproc_ns->dens_gamma_n = acdb_ns->dens_gamma_n;
+ acdb_data.preproc_ns->dens_nfe_block_size =
+ acdb_ns->dens_nfe_block_size;
+ acdb_data.preproc_ns->dens_limit_ns = acdb_ns->dens_limit_ns;
+ acdb_data.preproc_ns->dens_limit_ns_d = acdb_ns->dens_limit_ns_d;
+ acdb_data.preproc_ns->wb_gamma_e = acdb_ns->wb_gamma_e;
+ acdb_data.preproc_ns->wb_gamma_n = acdb_ns->wb_gamma_n;
+
+ return 0;
+}
+
+s32 acdb_calibrate_audpreproc(void)
+{
+ s32 result = 0;
+
+ result = acdb_fill_audpreproc_agc();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpreproc_dsp_set_agc(acdb_data.preproc_agc, sizeof(
+ audpreproc_cmd_cfg_agc_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send AGC data to preproc)\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("AUDPREC is calibrated with AGC parameters");
+ }
+ result = acdb_fill_audpreproc_iir();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpreproc_dsp_set_iir(acdb_data.preproc_iir,
+ sizeof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send IIR data to preproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("audpreproc is calibrated with iir parameters");
+ }
+
+ result = acdb_fill_audpreproc_ns();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpreproc_dsp_set_ns(acdb_data.preproc_ns,
+ sizeof(\
+ audpreproc_cmd_cfg_ns_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send NS data to preproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("audpreproc is calibrated with NS parameters");
+ }
+done:
+ return result;
+}
+
+static s32 acdb_send_calibration(void)
+{
+ s32 result = 0;
+
+ if (acdb_data.device_info->dev_type.rx_device) {
+ result = acdb_calibrate_audpp();
+ if (result)
+ goto done;
+ } else if (acdb_data.device_info->dev_type.tx_device) {
+ result = acdb_calibrate_audpreproc();
+ if (result)
+ goto done;
+ acdb_data.audrec_applied |= AUDREC_READY;
+ MM_DBG("acdb_data.audrec_applied = %x\n",
+ acdb_data.audrec_applied);
+ }
+done:
+ return result;
+}
+
+static u8 check_tx_acdb_values_cached(void)
+{
+ if ((acdb_data.device_info->sample_rate ==
+ acdb_cache_tx.device_info.sample_rate) &&
+ (acdb_data.device_info->acdb_id ==
+ acdb_cache_tx.device_info.acdb_id) &&
+ (acdb_cache_tx.node_status ==
+ ACDB_VALUES_FILLED))
+ return 0;
+ else
+ return 1;
+}
+
+static void handle_tx_device_ready_callback(void)
+{
+ u8 acdb_value_apply = 0;
+ u8 result = 0;
+
+ /*check wheather AUDREC enabled before device call backs*/
+ if ((acdb_data.acdb_state & AUDREC_READY) &&
+ !(acdb_data.audrec_applied & AUDREC_READY)) {
+ MM_DBG("AUDREC already enabled apply acdb values\n");
+ acdb_value_apply |= AUDREC_READY;
+ }
+ if (acdb_value_apply) {
+ if (session_info.sampling_freq)
+ acdb_data.device_info->sample_rate =
+ session_info.sampling_freq;
+ result = check_tx_acdb_values_cached();
+ if (result) {
+ result = acdb_get_calibration();
+ if (result < 0) {
+ MM_ERR("Not able to get calibration"\
+ " data continue\n");
+ return;
+ }
+ }
+ acdb_cache_tx.node_status = ACDB_VALUES_FILLED;
+ acdb_send_calibration();
+ }
+}
+
+static struct acdb_cache_node *get_acdb_values_from_cache_tx(u32 stream_id)
+{
+ MM_DBG("searching node with stream_id");
+ if ((acdb_cache_tx.stream_id == stream_id) &&
+ (acdb_cache_tx.node_status ==
+ ACDB_VALUES_NOT_FILLED)) {
+ return &acdb_cache_tx;
+ }
+ MM_DBG("Error! in finding node\n");
+ return NULL;
+}
+
+static void update_acdb_data_struct(struct acdb_cache_node *cur_node)
+{
+ if (cur_node) {
+ acdb_data.device_info = &cur_node->device_info;
+ acdb_data.virt_addr = cur_node->virt_addr_acdb_values;
+ acdb_data.phys_addr = cur_node->phys_addr_acdb_values;
+ } else
+ MM_ERR("error in curent node\n");
+}
+
+static void send_acdb_values_for_active_devices(void)
+{
+ if (acdb_cache_rx.node_status ==
+ ACDB_VALUES_FILLED) {
+ update_acdb_data_struct(&acdb_cache_rx);
+ if (acdb_data.acdb_state & CAL_DATA_READY)
+ acdb_send_calibration();
+ }
+}
+
+static s32 initialize_rpc(void)
+{
+ s32 result = 0;
+
+ result = daldevice_attach(DALDEVICEID_ACDB, ACDB_PORT_NAME,
+ ACDB_CPU, &acdb_data.handle);
+
+ if (result) {
+ MM_ERR("ACDB=> Device Attach failed\n");
+ result = -ENODEV;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static u32 allocate_memory_acdb_cache_tx(void)
+{
+ u32 result = 0;
+ /*initialize local cache */
+ acdb_cache_tx.phys_addr_acdb_values =
+ allocate_contiguous_ebi_nomap(ACDB_BUF_SIZE,
+ SZ_4K);
+
+ if (!acdb_cache_tx.phys_addr_acdb_values) {
+ MM_ERR("ACDB=> Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ acdb_cache_tx.map_v_addr = ioremap(
+ acdb_cache_tx.phys_addr_acdb_values,
+ ACDB_BUF_SIZE);
+ if (IS_ERR(acdb_cache_tx.map_v_addr)) {
+ MM_ERR("ACDB=> Could not map physical address\n");
+ result = -ENOMEM;
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+ goto error;
+ }
+ acdb_cache_tx.virt_addr_acdb_values =
+ acdb_cache_tx.map_v_addr;
+ memset(acdb_cache_tx.virt_addr_acdb_values, 0,
+ ACDB_BUF_SIZE);
+ return result;
+error:
+ iounmap(acdb_cache_tx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+ return result;
+}
+
+static u32 allocate_memory_acdb_cache_rx(void)
+{
+ u32 result = 0;
+
+ /*initialize local cache */
+ acdb_cache_rx.phys_addr_acdb_values =
+ allocate_contiguous_ebi_nomap(
+ ACDB_BUF_SIZE, SZ_4K);
+
+ if (!acdb_cache_rx.phys_addr_acdb_values) {
+ MM_ERR("ACDB=> Can not allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ acdb_cache_rx.map_v_addr =
+ ioremap(acdb_cache_rx.phys_addr_acdb_values,
+ ACDB_BUF_SIZE);
+ if (IS_ERR(acdb_cache_rx.map_v_addr)) {
+ MM_ERR("ACDB=> Could not map physical address\n");
+ result = -ENOMEM;
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+ goto error;
+ }
+ acdb_cache_rx.virt_addr_acdb_values =
+ acdb_cache_rx.map_v_addr;
+ memset(acdb_cache_rx.virt_addr_acdb_values, 0,
+ ACDB_BUF_SIZE);
+ return result;
+error:
+ iounmap(acdb_cache_rx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+ return result;
+}
+
+static u32 allocate_memory_acdb_get_blk(void)
+{
+ u32 result = 0;
+ acdb_data.get_blk_paddr = allocate_contiguous_ebi_nomap(
+ ACDB_BUF_SIZE, SZ_4K);
+ if (!acdb_data.get_blk_paddr) {
+ MM_ERR("ACDB=> Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ acdb_data.map_v_get_blk = ioremap(acdb_data.get_blk_paddr,
+ ACDB_BUF_SIZE);
+ if (IS_ERR(acdb_data.map_v_get_blk)) {
+ MM_ERR("ACDB=> Could not map physical address\n");
+ result = -ENOMEM;
+ free_contiguous_memory_by_paddr(
+ acdb_data.get_blk_paddr);
+ goto error;
+ }
+ acdb_data.get_blk_kvaddr = acdb_data.map_v_get_blk;
+ memset(acdb_data.get_blk_kvaddr, 0, ACDB_BUF_SIZE);
+error:
+ return result;
+}
+
+static void free_memory_acdb_cache_rx(void)
+{
+ iounmap(acdb_cache_rx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+}
+
+static void free_memory_acdb_cache_tx(void)
+{
+
+ iounmap(acdb_cache_tx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+}
+
+static void free_memory_acdb_get_blk(void)
+{
+ iounmap(acdb_data.map_v_get_blk);
+ free_contiguous_memory_by_paddr(acdb_data.get_blk_paddr);
+}
+
+static s32 initialize_memory(void)
+{
+ s32 result = 0;
+
+ result = allocate_memory_acdb_get_blk();
+ if (result < 0) {
+ MM_ERR("memory allocation for get blk failed\n");
+ goto done;
+ }
+
+ result = allocate_memory_acdb_cache_rx();
+ if (result < 0) {
+ MM_ERR("memory allocation for rx cache is failed\n");
+ free_memory_acdb_get_blk();
+ goto done;
+ }
+ result = allocate_memory_acdb_cache_tx();
+ if (result < 0) {
+ MM_ERR("memory allocation for tx cache is failed\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ goto done;
+ }
+ acdb_data.pp_iir = kmalloc(sizeof(*acdb_data.pp_iir),
+ GFP_KERNEL);
+ if (acdb_data.pp_iir == NULL) {
+ MM_ERR("ACDB=> Could not allocate postproc iir memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.pp_mbadrc = kmalloc(sizeof(*acdb_data.pp_mbadrc), GFP_KERNEL);
+ if (acdb_data.pp_mbadrc == NULL) {
+ MM_ERR("ACDB=> Could not allocate postproc mbadrc memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.preproc_agc = kmalloc(sizeof(*acdb_data.preproc_agc),
+ GFP_KERNEL);
+ if (acdb_data.preproc_agc == NULL) {
+ MM_ERR("ACDB=> Could not allocate preproc agc memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.preproc_iir = kmalloc(sizeof(*acdb_data.preproc_iir),
+ GFP_KERNEL);
+ if (acdb_data.preproc_iir == NULL) {
+ MM_ERR("ACDB=> Could not allocate preproc iir memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ kfree(acdb_data.preproc_agc);
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.preproc_ns = kmalloc(sizeof(*acdb_data.preproc_ns),
+ GFP_KERNEL);
+ if (acdb_data.preproc_ns == NULL) {
+ MM_ERR("ACDB=> Could not allocate preproc ns memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ kfree(acdb_data.preproc_agc);
+ kfree(acdb_data.preproc_iir);
+ result = -ENOMEM;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static u8 check_device_change(struct dev_evt_msg device_info)
+{
+ if (!acdb_data.device_info) {
+ MM_ERR("not pointing to previous valid device detail\n");
+ return 1; /*device info will not be pointing to*/
+ /* valid device when acdb driver comes up*/
+ }
+ if ((device_info.sample_rate ==
+ acdb_data.device_info->sample_rate) &&
+ (device_info.acdb_id == acdb_data.device_info->acdb_id)) {
+ return 0;
+ }
+ return 1;
+}
+
+static void device_cb(struct dev_evt_msg *evt, void *private)
+{
+ struct cad_device_info_type dev_type;
+ struct acdb_cache_node *acdb_cache_free_node = NULL;
+ u32 session_id = 0;
+ u8 ret = 0;
+ u8 device_change = 0;
+
+ /*if session value is zero it indicates that device call back is for
+ voice call we will drop the request as acdb values for voice call is
+ not applied from acdb driver*/
+ if (!evt->session_info) {
+ MM_DBG("no active sessions and call back is for"\
+ " voice call\n");
+ goto done;
+ }
+
+ if ((evt->dev_type.rx_device) &&
+ (evt->acdb_id == PSEUDO_ACDB_ID)) {
+ MM_INFO("device cb is for rx device with pseudo acdb id\n");
+ goto done;
+ }
+ dev_type = evt->dev_type;
+ MM_DBG("sample_rate = %d\n", evt->sample_rate);
+ MM_DBG("acdb_id = %d\n", evt->acdb_id);
+ MM_DBG("sessions = %d\n", evt->session_info);
+ MM_DBG("acdb_state = %x\n", acdb_data.acdb_state);
+ mutex_lock(&acdb_data.acdb_mutex);
+ device_change = check_device_change(*evt);
+ if (!device_change) {
+ if (dev_type.tx_device) {
+ if (!(acdb_data.acdb_state & AUDREC_READY))
+ acdb_data.audrec_applied &= ~AUDREC_READY;
+
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+ goto update_cache;
+ }
+ } else
+ /* state is updated to query the modem for values */
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+
+update_cache:
+ if (dev_type.tx_device) {
+ /*Only one recording session possible*/
+ session_id = 0;
+ acdb_cache_free_node = &acdb_cache_tx;
+ ret = check_device_info_already_present(
+ *evt,
+ acdb_cache_free_node);
+ acdb_cache_free_node->stream_id = session_id;
+ acdb_data.cur_tx_session = session_id;
+ } else {
+ acdb_cache_free_node = &acdb_cache_rx;
+ ret = check_device_info_already_present(*evt,
+ acdb_cache_free_node);
+ if (ret == 1) {
+ MM_DBG("got device ready call back for another "\
+ "audplay task sessions on same COPP\n");
+ /*stream_id is used to keep track of number of active*/
+ /*sessions active on this device*/
+ acdb_cache_free_node->stream_id++;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ goto done;
+ }
+ acdb_cache_free_node->stream_id++;
+ }
+ update_acdb_data_struct(acdb_cache_free_node);
+ acdb_data.device_cb_compl = 1;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ wake_up(&acdb_data.wait);
+done:
+ return;
+}
+
+static s32 register_device_cb(void)
+{
+ s32 result = 0;
+ acdb_data.dev_cb.func = device_cb;
+ acdb_data.dev_cb.private = (void *)&acdb_data;
+
+ result = audmgr_register_device_info_callback(&acdb_data.dev_cb);
+
+ if (result) {
+ MM_ERR("ACDB=> Could not register device callback\n");
+ result = -ENODEV;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static void audpp_cb(void *private, u32 id, u16 *msg)
+{
+ MM_DBG("\n");
+ if (id != AUDPP_MSG_CFG_MSG)
+ goto done;
+
+ if (msg[0] == AUDPP_MSG_ENA_DIS) {
+ if (--acdb_cache_rx.stream_id <= 0) {
+ acdb_data.acdb_state &= ~AUDPP_READY;
+ acdb_cache_rx.stream_id = 0;
+ MM_DBG("AUDPP_MSG_ENA_DIS\n");
+ }
+ goto done;
+ }
+
+ acdb_data.acdb_state |= AUDPP_READY;
+ acdb_data.audpp_cb_compl = 1;
+ wake_up(&acdb_data.wait);
+done:
+ return;
+}
+
+static s8 handle_audpreproc_cb(void)
+{
+ struct acdb_cache_node *acdb_cached_values;
+ s8 result = 0;
+ u8 stream_id = acdb_data.preproc_stream_id;
+ acdb_data.preproc_cb_compl = 0;
+ acdb_cached_values = get_acdb_values_from_cache_tx(stream_id);
+ if (acdb_cached_values == NULL) {
+ MM_DBG("ERROR: to get chached acdb values\n");
+ return -EPERM;
+ }
+ update_acdb_data_struct(acdb_cached_values);
+
+ if (session_info.sampling_freq)
+ acdb_data.device_info->sample_rate =
+ session_info.sampling_freq;
+
+ if (!(acdb_data.acdb_state & CAL_DATA_READY)) {
+ result = check_tx_acdb_values_cached();
+ if (result) {
+ result = acdb_get_calibration();
+ if (result < 0) {
+ MM_ERR("failed to get calibration data\n");
+ return result;
+ }
+ }
+ acdb_cached_values->node_status = ACDB_VALUES_FILLED;
+ }
+ return result;
+}
+
+static void audpreproc_cb(void *private, u32 id, void *event_data)
+{
+ u8 result = 0;
+ uint16_t *msg = event_data;
+ int stream_id = 0; /* Only single tunnel mode recording supported */
+ if (id != AUDPREPROC_MSG_CMD_CFG_DONE_MSG)
+ goto done;
+
+ acdb_data.preproc_stream_id = stream_id;
+ get_audrec_session_info(&session_info);
+ MM_DBG("status_flag = %x\n", msg[0]);
+ if (msg[0] == AUDPREPROC_MSG_STATUS_FLAG_DIS) {
+ acdb_data.acdb_state &= ~AUDREC_READY;
+ acdb_cache_tx.node_status =\
+ ACDB_VALUES_NOT_FILLED;
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+ goto done;
+ }
+ /*Following check is added to make sure that device info
+ is updated. audpre proc layer enabled without device
+ callback at this scenario we should not access
+ device information
+ */
+ if (acdb_data.device_info &&
+ session_info.sampling_freq) {
+ acdb_data.device_info->sample_rate =
+ session_info.sampling_freq;
+ result = check_tx_acdb_values_cached();
+ if (!result) {
+ MM_INFO("acdb values for the stream is" \
+ " querried from modem");
+ acdb_data.acdb_state |= CAL_DATA_READY;
+ } else {
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+ }
+ }
+ acdb_data.acdb_state |= AUDREC_READY;
+
+ acdb_data.preproc_cb_compl = 1;
+ MM_DBG("acdb_data.acdb_state = %x\n", acdb_data.acdb_state);
+ wake_up(&acdb_data.wait);
+done:
+ return;
+}
+
+static s32 register_audpp_cb(void)
+{
+ s32 result = 0;
+
+ acdb_data.audpp_cb.fn = audpp_cb;
+ acdb_data.audpp_cb.private = NULL;
+ result = audpp_register_event_callback(&acdb_data.audpp_cb);
+ if (result) {
+ MM_ERR("ACDB=> Could not register audpp callback\n");
+ result = -ENODEV;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static s32 register_audpreproc_cb(void)
+{
+ s32 result = 0;
+
+ acdb_data.audpreproc_cb.fn = audpreproc_cb;
+ acdb_data.audpreproc_cb.private = NULL;
+ result = audpreproc_register_event_callback(&acdb_data.audpreproc_cb);
+ if (result) {
+ MM_ERR("ACDB=> Could not register audpreproc callback\n");
+ result = -ENODEV;
+ goto done;
+ }
+
+done:
+ return result;
+}
+
+static s32 acdb_initialize_data(void)
+{
+ s32 result = 0;
+
+ mutex_init(&acdb_data.acdb_mutex);
+
+ result = initialize_rpc();
+ if (result)
+ goto err;
+
+ result = initialize_memory();
+ if (result)
+ goto err1;
+
+ result = register_device_cb();
+ if (result)
+ goto err2;
+
+ result = register_audpp_cb();
+ if (result)
+ goto err3;
+
+ result = register_audpreproc_cb();
+ if (result)
+ goto err4;
+
+
+ return result;
+
+err4:
+ result = audpreproc_unregister_event_callback(&acdb_data.audpreproc_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpreproc callback\n");
+err3:
+ result = audpp_unregister_event_callback(&acdb_data.audpp_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpp callback\n");
+err2:
+ result = audmgr_deregister_device_info_callback(&acdb_data.dev_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister device callback\n");
+err1:
+ daldevice_detach(acdb_data.handle);
+ acdb_data.handle = NULL;
+err:
+ return result;
+}
+
+static s32 acdb_calibrate_device(void *data)
+{
+ s32 result = 0;
+
+ /* initialize driver */
+ result = acdb_initialize_data();
+ if (result)
+ goto done;
+
+ while (!kthread_should_stop()) {
+ MM_DBG("Waiting for call back events\n");
+ wait_event_interruptible(acdb_data.wait,
+ (acdb_data.device_cb_compl
+ | acdb_data.audpp_cb_compl
+ | acdb_data.preproc_cb_compl));
+ mutex_lock(&acdb_data.acdb_mutex);
+ if (acdb_data.device_cb_compl) {
+ acdb_data.device_cb_compl = 0;
+ if (!(acdb_data.acdb_state & CAL_DATA_READY)) {
+ if (acdb_data.device_info->dev_type.rx_device) {
+ /*we need to get calibration values
+ only for RX device as resampler
+ moved to start of the pre - proc chain
+ tx calibration value will be based on
+ sampling frequency what audrec is
+ configured, calibration values for tx
+ device are fetch in audpreproc
+ callback*/
+ result = acdb_get_calibration();
+ if (result < 0) {
+ mutex_unlock(
+ &acdb_data.acdb_mutex);
+ MM_ERR("Not able to get "\
+ "calibration "\
+ "data continue\n");
+ continue;
+ }
+ }
+ }
+ MM_DBG("acdb state = %d\n",
+ acdb_data.acdb_state);
+ if (acdb_data.device_info->dev_type.tx_device)
+ handle_tx_device_ready_callback();
+ else {
+ acdb_cache_rx.node_status =\
+ ACDB_VALUES_FILLED;
+ if (acdb_data.acdb_state &
+ AUDPP_READY) {
+ MM_DBG("AUDPP already enabled "\
+ "apply acdb values\n");
+ goto apply;
+ }
+ }
+ }
+
+ if (!(acdb_data.audpp_cb_compl ||
+ acdb_data.preproc_cb_compl)) {
+ MM_DBG("need to wait for either AUDPP / AUDPREPROC "\
+ "Event\n");
+ mutex_unlock(&acdb_data.acdb_mutex);
+ continue;
+ } else {
+ MM_DBG("got audpp / preproc call back\n");
+ if (acdb_data.audpp_cb_compl) {
+ send_acdb_values_for_active_devices();
+ acdb_data.audpp_cb_compl = 0;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ continue;
+ } else {
+ result = handle_audpreproc_cb();
+ if (result < 0) {
+ mutex_unlock(&acdb_data.acdb_mutex);
+ continue;
+ }
+ }
+ }
+apply:
+ if (acdb_data.acdb_state & CAL_DATA_READY)
+ result = acdb_send_calibration();
+
+ mutex_unlock(&acdb_data.acdb_mutex);
+ }
+done:
+ return 0;
+}
+
+static int __init acdb_init(void)
+{
+
+ s32 result = 0;
+
+ memset(&acdb_data, 0, sizeof(acdb_data));
+ spin_lock_init(&acdb_data.dsp_lock);
+ acdb_data.cb_thread_task = kthread_run(acdb_calibrate_device,
+ NULL, "acdb_cb_thread");
+
+ if (IS_ERR(acdb_data.cb_thread_task)) {
+ MM_ERR("ACDB=> Could not register cb thread\n");
+ result = -ENODEV;
+ goto err;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ /*This is RTC specific INIT used only with debugfs*/
+ if (!rtc_acdb_init())
+ MM_ERR("RTC ACDB=>INIT Failure\n");
+
+#endif
+ init_waitqueue_head(&acdb_data.wait);
+
+ return misc_register(&acdb_misc);
+err:
+ return result;
+}
+
+static void __exit acdb_exit(void)
+{
+ s32 result = 0;
+
+ result = audmgr_deregister_device_info_callback(&acdb_data.dev_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister device callback\n");
+
+ result = audpp_unregister_event_callback(&acdb_data.audpp_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpp callback\n");
+
+ result = audpreproc_unregister_event_callback(&acdb_data.\
+ audpreproc_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpreproc callback\n");
+
+ result = kthread_stop(acdb_data.cb_thread_task);
+ if (result)
+ MM_ERR("ACDB=> Could not stop kthread\n");
+
+ free_memory_acdb_get_blk();
+
+ iounmap(acdb_cache_tx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+ iounmap(acdb_cache_rx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+ kfree(acdb_data.device_info);
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ kfree(acdb_data.preproc_agc);
+ kfree(acdb_data.preproc_iir);
+ kfree(acdb_data.preproc_ns);
+ mutex_destroy(&acdb_data.acdb_mutex);
+ memset(&acdb_data, 0, sizeof(acdb_data));
+ #ifdef CONFIG_DEBUG_FS
+ rtc_acdb_deinit();
+ #endif
+}
+
+late_initcall(acdb_init);
+module_exit(acdb_exit);
+
+MODULE_DESCRIPTION("MSM 8x25 Audio ACDB driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 45fa045..7e6c9ce 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -51,6 +51,7 @@
#include <mach/qdsp5/qdsp5audppmsg.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
#include <mach/debug_mm.h>
#include <mach/msm_memtypes.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
index 39578c1..05ad373 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
@@ -114,8 +114,6 @@
uint32_t out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
-
/* configuration to use on next enable */
uint32_t samp_rate;
@@ -154,6 +152,7 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -232,6 +231,30 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
/* must be called with audio->lock held */
static int audamrnb_in_enable(struct audio_amrnb_in *audio)
{
@@ -252,16 +275,23 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
+
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -286,35 +316,17 @@
audio->running == 0, 1*HZ);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio)
{
struct audio_frame *frame;
@@ -555,10 +567,6 @@
}
}
-struct msm_adsp_ops audpre_amrnb_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
struct msm_adsp_ops audrec_amrnb_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1201,12 +1209,8 @@
audamrnb_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
-
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
(audio->out_data)) {
@@ -1304,15 +1308,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_amrnb_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1414,8 +1409,6 @@
dma_free_coherent(NULL, dma_size, audio->data, audio->phys);
evt_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrwb.c b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
index 66b9354..f18aca7 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc.c b/arch/arm/mach-msm/qdsp5/audio_evrc.c
index 1d4148a..7aeadac 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc.c
@@ -43,6 +43,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
index e955c4b..3310743 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
@@ -111,7 +111,6 @@
int out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
/* configuration to use on next enable */
@@ -154,6 +153,8 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
struct ion_handle *output_buff_handle;
+
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -232,6 +233,32 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
+
/* must be called with audio->lock held */
static int audevrc_in_enable(struct audio_evrc_in *audio)
{
@@ -252,16 +279,24 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
+
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -288,35 +323,17 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
audmgr_disable(&audio->audmgr);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
static void audevrc_in_get_dsp_frames(struct audio_evrc_in *audio)
{
struct audio_frame *frame;
@@ -557,10 +574,6 @@
}
}
-static struct msm_adsp_ops audpre_evrc_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
static struct msm_adsp_ops audrec_evrc_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1186,12 +1199,8 @@
audevrc_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
-
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
(audio->out_data)) {
@@ -1282,16 +1291,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_evrc_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1429,8 +1428,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index fe7b270..6cbb981a3 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index 427dc8f..167de9c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.c
@@ -42,6 +42,7 @@
#include <mach/msm_memtypes.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index 0c8034c..6f3bf91 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -41,6 +41,7 @@
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/htc_pwrsink.h>
#include <mach/debug_mm.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm.c b/arch/arm/mach-msm/qdsp5/audio_pcm.c
index 880de09..3a92e0c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 716dbd2..4dcbc7b 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -75,7 +75,6 @@
struct mutex read_lock;
wait_queue_head_t wait;
- struct msm_adsp_module *audpre;
struct msm_adsp_module *audrec;
const char *module_name;
unsigned queue_ids;
@@ -105,6 +104,7 @@
int enabled;
int running;
int stopped; /* set when stopped, cleared on flush */
+ struct audrec_session_info session_info; /*audrec session info*/
/* audpre settings */
int tx_agc_enable;
@@ -176,6 +176,32 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
+
/* must be called with audio->lock held */
static int audpcm_in_enable(struct audio_in *audio)
{
@@ -195,14 +221,15 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
- MM_ERR("msm_adsp_enable(audpre) failed\n");
+ if (audpreproc_enable(audio->enc_id, &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
return -ENODEV;
}
+
if (msm_adsp_enable(audio->audrec)) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
}
@@ -210,6 +237,12 @@
audio->enabled = 1;
audpcm_in_dsp_enable(audio, 1);
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
+
return 0;
}
@@ -225,34 +258,15 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
+ /*reset the sampling frequency information at audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
audmgr_disable(&audio->audmgr);
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_INFO("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
struct audio_frame {
uint16_t count_low;
uint16_t count_high;
@@ -360,18 +374,10 @@
}
}
-static struct msm_adsp_ops audpre_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
static struct msm_adsp_ops audrec_adsp_ops = {
.event = audrec_dsp_event,
};
-
-#define audio_send_queue_pre(audio, cmd, len) \
- msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
-
#define audio_send_queue_recbs(audio, cmd, len) \
msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
cmd, len)
@@ -399,7 +405,7 @@
audio->tx_agc_cfg.tx_agc_enable_flag =
AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA;
/* cmd.param_mask = 0xFFF0 from sample code */
- audio->tx_agc_cfg.param_mask =
+ audio->tx_agc_cfg.tx_agc_param_mask =
(1 << AUDPREPROC_CMD_PARAM_MASK_RMS_TAY) |
(1 << AUDPREPROC_CMD_PARAM_MASK_RELEASEK) |
(1 << AUDPREPROC_CMD_PARAM_MASK_DELAY) |
@@ -420,7 +426,7 @@
}
cmd = audio->tx_agc_cfg;
- return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
+ return audpreproc_dsp_set_agc(&cmd, sizeof(cmd));
}
static int audio_enable_tx_agc(struct audio_in *audio, int enable)
@@ -466,7 +472,7 @@
}
cmd = audio->ns_cfg;
- return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
+ return audpreproc_dsp_set_ns(&cmd, sizeof(cmd));
}
static int audio_enable_ns(struct audio_in *audio, int enable)
@@ -495,7 +501,7 @@
cmd = audio->iir_cfg;
- return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
+ return audpreproc_dsp_set_iir(&cmd, sizeof(cmd));
}
static int audio_enable_iir(struct audio_in *audio, int enable)
@@ -762,9 +768,7 @@
audpcm_in_flush(audio);
audpreproc_aenc_free(audio->enc_id);
msm_adsp_put(audio->audrec);
- msm_adsp_put(audio->audpre);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if (audio->data) {
ion_unmap_kernel(audio->client, audio->output_buff_handle);
@@ -824,14 +828,6 @@
goto done;
}
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
@@ -899,7 +895,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
return rc;
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp.c b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
index dc257cd..e1a6299 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
@@ -44,6 +44,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index 99a169d..57ae772 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -112,7 +112,6 @@
int out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
/* configuration to use on next enable */
@@ -155,6 +154,8 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
struct ion_handle *output_buff_handle;
+
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -233,6 +234,32 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
+
/* must be called with audio->lock held */
static int audqcelp_in_enable(struct audio_qcelp_in *audio)
{
@@ -253,16 +280,23 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -288,35 +322,17 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
static void audqcelp_in_get_dsp_frames(struct audio_qcelp_in *audio)
{
struct audio_frame *frame;
@@ -557,10 +573,6 @@
}
}
-static struct msm_adsp_ops audpre_qcelp_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
static struct msm_adsp_ops audrec_qcelp_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1187,12 +1199,8 @@
audqcelp_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
-
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
@@ -1285,16 +1293,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_qcelp_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1434,8 +1432,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_wma.c b/arch/arm/mach-msm/qdsp5/audio_wma.c
index e28e704..276c9d4 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wma.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_wmapro.c b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
index 87afcf0..b881c59 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
@@ -45,6 +45,7 @@
#include <mach/msm_adsp.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audmgr.c b/arch/arm/mach-msm/qdsp5/audmgr.c
index 231a28c..666323b 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr.c
+++ b/arch/arm/mach-msm/qdsp5/audmgr.c
@@ -3,7 +3,7 @@
* interface to "audmgr" service on the baseband cpu
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -35,6 +35,10 @@
#define STATE_ENABLED 3
#define STATE_DISABLING 4
#define STATE_ERROR 5
+#define MAX_DEVICE_INFO_CALLBACK 1
+#define SESSION_VOICE 0
+#define SESSION_PLAYBACK 1
+#define SESSION_RECORDING 2
/* store information used across complete audmgr sessions */
struct audmgr_global {
@@ -42,6 +46,9 @@
struct msm_rpc_endpoint *ept;
struct task_struct *task;
uint32_t rpc_version;
+ int cad;
+ struct device_info_callback *device_cb[MAX_DEVICE_INFO_CALLBACK];
+
};
static DEFINE_MUTEX(audmgr_lock);
@@ -49,6 +56,59 @@
.lock = &audmgr_lock,
};
+static void audmgr_rpc_connect(struct audmgr_global *amg)
+{
+ amg->cad = 0;
+ amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
+ AUDMGR_VERS_COMP_VER3,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ MM_DBG("connect failed with current VERS"\
+ "= %x, trying again with Cad API\n",
+ AUDMGR_VERS_COMP_VER3);
+ amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
+ AUDMGR_VERS_COMP_VER4,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
+ AUDMGR_VERS_COMP_VER2,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ MM_ERR("connect failed with current VERS" \
+ "= %x, trying again with another API\n",
+ AUDMGR_VERS_COMP_VER2);
+ amg->ept = msm_rpc_connect_compatible(
+ AUDMGR_PROG,
+ AUDMGR_VERS_COMP,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ MM_ERR("connect failed with current" \
+ "VERS=%x, trying again with" \
+ "another API\n",
+ AUDMGR_VERS_COMP);
+ amg->ept = msm_rpc_connect(AUDMGR_PROG,
+ AUDMGR_VERS,
+ MSM_RPC_UNINTERRUPTIBLE);
+ amg->rpc_version = AUDMGR_VERS;
+ } else
+ amg->rpc_version = AUDMGR_VERS_COMP;
+ } else
+ amg->rpc_version = AUDMGR_VERS_COMP_VER2;
+ } else {
+ amg->rpc_version = AUDMGR_VERS_COMP_VER4;
+ amg->cad = 1;
+ }
+ } else
+ amg->rpc_version = AUDMGR_VERS_COMP_VER3;
+
+ if (IS_ERR(amg->ept)) {
+ amg->ept = NULL;
+ MM_ERR("failed to connect to audmgr svc\n");
+ }
+
+ return;
+}
+
static void rpc_ack(struct msm_rpc_endpoint *ept, uint32_t xid)
{
uint32_t rep[6];
@@ -64,34 +124,45 @@
}
static void process_audmgr_callback(struct audmgr_global *amg,
- struct rpc_audmgr_cb_func_ptr *args,
- int len)
+ void *args, int len)
{
struct audmgr *am;
+ int i = 0;
+ struct rpc_audmgr_cb_device_info *temp;
- /* Allow only if complete arguments recevied */
- if (len < (sizeof(struct rpc_audmgr_cb_func_ptr)))
+ /* Allow only if complete arguments recevied*/
+ if (len < MIN_RPC_DATA_LENGTH)
return;
/* Allow only if valid argument */
- if (be32_to_cpu(args->set_to_one) != 1)
+ if (be32_to_cpu(((struct rpc_audmgr_cb_common *)args)->set_to_one) != 1)
return;
- am = (struct audmgr *) be32_to_cpu(args->client_data);
-
- if (!am)
- return;
-
- switch (be32_to_cpu(args->status)) {
+ switch (be32_to_cpu(((struct rpc_audmgr_cb_common *)args)->status)) {
case RPC_AUDMGR_STATUS_READY:
- am->handle = be32_to_cpu(args->u.handle);
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
+ am->handle = be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->u.handle);
MM_INFO("rpc READY handle=0x%08x\n", am->handle);
break;
case RPC_AUDMGR_STATUS_CODEC_CONFIG: {
- uint32_t volume;
- volume = be32_to_cpu(args->u.volume);
- MM_INFO("rpc CODEC_CONFIG volume=0x%08x\n", volume);
- am->state = STATE_ENABLED;
+ MM_INFO("rpc CODEC_CONFIG\n");
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
+ if (am->state != STATE_ENABLED)
+ am->state = STATE_ENABLED;
+ while ((amg->device_cb[i] != NULL) &&
+ (i < MAX_DEVICE_INFO_CALLBACK) &&
+ (amg->cad)) {
+ amg->device_cb[i]->func(&(am->evt),
+ amg->device_cb[i]->private);
+ i++;
+ }
wake_up(&am->wait);
break;
}
@@ -109,14 +180,51 @@
break;
case RPC_AUDMGR_STATUS_DISABLED:
MM_ERR("DISABLED\n");
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
am->state = STATE_DISABLED;
wake_up(&am->wait);
break;
case RPC_AUDMGR_STATUS_ERROR:
MM_ERR("ERROR?\n");
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
am->state = STATE_ERROR;
wake_up(&am->wait);
break;
+ case RPC_AUDMGR_STATUS_DEVICE_INFO:
+ MM_INFO("rpc DEVICE_INFO\n");
+ if (!amg->cad)
+ break;
+ temp = (struct rpc_audmgr_cb_device_info *)args;
+ am = (struct audmgr *) be32_to_cpu(temp->client_data);
+ if (!am)
+ return;
+ if (am->evt.session_info == SESSION_PLAYBACK) {
+ am->evt.dev_type.rx_device =
+ be32_to_cpu(temp->d.rx_device);
+ am->evt.dev_type.tx_device = 0;
+ am->evt.acdb_id = am->evt.dev_type.rx_device;
+ } else if (am->evt.session_info == SESSION_RECORDING) {
+ am->evt.dev_type.rx_device = 0;
+ am->evt.dev_type.tx_device =
+ be32_to_cpu(temp->d.tx_device);
+ am->evt.acdb_id = am->evt.dev_type.tx_device;
+ }
+ am->evt.dev_type.ear_mute =
+ be32_to_cpu(temp->d.ear_mute);
+ am->evt.dev_type.mic_mute =
+ be32_to_cpu(temp->d.mic_mute);
+ am->evt.dev_type.volume =
+ be32_to_cpu(temp->d.volume);
+ break;
+ case RPC_AUDMGR_STATUS_DEVICE_CONFIG:
+ MM_ERR("rpc DEVICE_CONFIG\n");
+ break;
default:
break;
}
@@ -201,6 +309,36 @@
return 0;
}
+static unsigned convert_samp_index(unsigned index)
+{
+ switch (index) {
+ case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
+ case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
+ case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
+ case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
+ case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
+ case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
+ case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
+ case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
+ case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
+ default: return 11025;
+ }
+}
+
+static void get_current_session_info(struct audmgr *am,
+ struct audmgr_config *cfg)
+{
+ if (cfg->def_method == RPC_AUD_DEF_METHOD_PLAYBACK ||
+ (cfg->def_method == RPC_AUD_DEF_METHOD_HOST_PCM && cfg->rx_rate)) {
+ am->evt.session_info = SESSION_PLAYBACK; /* playback */
+ am->evt.sample_rate = convert_samp_index(cfg->rx_rate);
+ } else if (cfg->def_method == RPC_AUD_DEF_METHOD_RECORD) {
+ am->evt.session_info = SESSION_RECORDING; /* recording */
+ am->evt.sample_rate = convert_samp_index(cfg->tx_rate);
+ } else
+ am->evt.session_info = SESSION_VOICE;
+}
+
struct audmgr_enable_msg {
struct rpc_request_hdr hdr;
struct rpc_audmgr_enable_client_args args;
@@ -223,39 +361,7 @@
/* connect to audmgr end point and polling thread only once */
if (amg->ept == NULL) {
- amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
- AUDMGR_VERS_COMP_VER3,
- MSM_RPC_UNINTERRUPTIBLE);
- if (IS_ERR(amg->ept)) {
- MM_ERR("connect failed with current VERS \
- = %x, trying again with another API\n",
- AUDMGR_VERS_COMP_VER3);
- amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
- AUDMGR_VERS_COMP_VER2,
- MSM_RPC_UNINTERRUPTIBLE);
- if (IS_ERR(amg->ept)) {
- MM_ERR("connect failed with current VERS \
- = %x, trying again with another API\n",
- AUDMGR_VERS_COMP_VER2);
- amg->ept = msm_rpc_connect_compatible(
- AUDMGR_PROG,
- AUDMGR_VERS_COMP,
- MSM_RPC_UNINTERRUPTIBLE);
- if (IS_ERR(amg->ept)) {
- MM_ERR("connect failed with current \
- VERS=%x, trying again with another \
- API\n", AUDMGR_VERS_COMP);
- amg->ept = msm_rpc_connect(AUDMGR_PROG,
- AUDMGR_VERS,
- MSM_RPC_UNINTERRUPTIBLE);
- amg->rpc_version = AUDMGR_VERS;
- } else
- amg->rpc_version = AUDMGR_VERS_COMP;
- } else
- amg->rpc_version = AUDMGR_VERS_COMP_VER2;
- } else
- amg->rpc_version = AUDMGR_VERS_COMP_VER3;
-
+ audmgr_rpc_connect(amg);
if (IS_ERR(amg->ept)) {
rc = PTR_ERR(amg->ept);
amg->ept = NULL;
@@ -312,6 +418,7 @@
msg.args.cb_func = cpu_to_be32(0x11111111);
msg.args.client_data = cpu_to_be32((int)am);
+ get_current_session_info(am, cfg);
msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, amg->rpc_version,
AUDMGR_ENABLE_CLIENT);
@@ -326,6 +433,7 @@
if (am->state == STATE_ENABLED)
return 0;
+ am->evt.session_info = -1;
MM_ERR("unexpected state %d while enabling?!\n", am->state);
return -ENODEV;
}
@@ -341,6 +449,7 @@
return 0;
MM_INFO("session 0x%08x\n", (int) am);
+ am->evt.session_info = -1;
msg.handle = cpu_to_be32(am->handle);
msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, amg->rpc_version,
AUDMGR_DISABLE_CLIENT);
@@ -363,3 +472,33 @@
return -ENODEV;
}
EXPORT_SYMBOL(audmgr_disable);
+
+int audmgr_register_device_info_callback(struct device_info_callback *dcb)
+{
+ struct audmgr_global *amg = &the_audmgr_state;
+ int i;
+
+ for (i = 0; i < MAX_DEVICE_INFO_CALLBACK; i++) {
+ if (NULL == amg->device_cb[i]) {
+ amg->device_cb[i] = dcb;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audmgr_register_device_info_callback);
+
+int audmgr_deregister_device_info_callback(struct device_info_callback *dcb)
+{
+ struct audmgr_global *amg = &the_audmgr_state;
+ int i;
+
+ for (i = 0; i < MAX_DEVICE_INFO_CALLBACK; i++) {
+ if (dcb == amg->device_cb[i]) {
+ amg->device_cb[i] = NULL;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audmgr_deregister_device_info_callback);
diff --git a/arch/arm/mach-msm/qdsp5/audmgr.h b/arch/arm/mach-msm/qdsp5/audmgr.h
index 3d8c560..15dd954 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr.h
+++ b/arch/arm/mach-msm/qdsp5/audmgr.h
@@ -125,6 +125,9 @@
RPC_AUDMGR_STATUS_VOLUME_CHANGE,
RPC_AUDMGR_STATUS_DISABLED,
RPC_AUDMGR_STATUS_ERROR,
+ RPC_AUDMGR_STATUS_DEVICE_CONFIG,
+ RPC_AUDMGR_STATUS_DEVICE_INFO
+
};
struct rpc_audmgr_enable_client_args {
@@ -148,6 +151,7 @@
#define AUDMGR_GET_RX_SAMPLE_RATE 8
#define AUDMGR_GET_TX_SAMPLE_RATE 9
#define AUDMGR_SET_DEVICE_MODE 10
+#define MIN_RPC_DATA_LENGTH 16
#define AUDMGR_PROG_VERS "rs30000013:0x7feccbff"
#define AUDMGR_PROG 0x30000013
@@ -155,8 +159,17 @@
#define AUDMGR_VERS_COMP 0x00010001
#define AUDMGR_VERS_COMP_VER2 0x00020001
#define AUDMGR_VERS_COMP_VER3 0x00030001
+#define AUDMGR_VERS_COMP_VER4 0x00040001
-struct rpc_audmgr_cb_func_ptr {
+struct cad_device_info_type {
+ uint32_t rx_device;
+ uint32_t tx_device;
+ uint32_t ear_mute;
+ uint32_t mic_mute;
+ uint32_t volume;
+};
+
+struct rpc_audmgr_cb_common {
uint32_t cb_id; /* cb_func */
uint32_t status; /* Audmgr status */
uint32_t set_to_one; /* Pointer status (1 = valid, 0 = invalid) */
@@ -165,6 +178,10 @@
disc = AUDMGR_STATUS_CODEC_CONFIG => data = volume
disc = AUDMGR_STATUS_DISABLED => data =status_disabled
disc = AUDMGR_STATUS_VOLUME_CHANGE => data = volume_change */
+};
+
+struct rpc_audmgr_cb_ready {
+ struct rpc_audmgr_cb_common c_data;
union {
uint32_t handle;
uint32_t volume;
@@ -174,18 +191,35 @@
uint32_t client_data;
};
+struct rpc_audmgr_cb_device_info {
+ struct rpc_audmgr_cb_common c_data;
+ struct cad_device_info_type d;
+ uint32_t client_data;
+};
+
#define AUDMGR_CB_FUNC_PTR 1
#define AUDMGR_OPR_LSTNR_CB_FUNC_PTR 2
#define AUDMGR_CODEC_LSTR_FUNC_PTR 3
-#define AUDMGR_CB_PROG_VERS "rs31000013:0xf8e3e2d9"
-#define AUDMGR_CB_PROG 0x31000013
-#define AUDMGR_CB_VERS 0xf8e3e2d9
+struct dev_evt_msg {
+ struct cad_device_info_type dev_type;
+ uint32_t acdb_id;
+ int session_info;
+ uint32_t sample_rate;
+};
+
+typedef void (*device_info_func)(struct dev_evt_msg *evt_msg, void *private);
+
+struct device_info_callback {
+ device_info_func func;
+ void *private;
+};
struct audmgr {
wait_queue_head_t wait;
uint32_t handle;
int state;
+ struct dev_evt_msg evt;
};
struct audmgr_config {
@@ -196,86 +230,11 @@
uint32_t snd_method;
};
+int audmgr_register_device_info_callback(struct device_info_callback *dcb);
+int audmgr_deregister_device_info_callback(struct device_info_callback *dcb);
+
int audmgr_open(struct audmgr *am);
int audmgr_close(struct audmgr *am);
int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg);
int audmgr_disable(struct audmgr *am);
-
-typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
-typedef void (*audrec_event_func)(void *private, unsigned id, uint16_t *msg);
-
-/* worst case delay of 1sec for response */
-#define MSM_AUD_DECODER_WAIT_MS 1000
-#define MSM_AUD_MODE_TUNNEL 0x00000100
-#define MSM_AUD_MODE_NONTUNNEL 0x00000200
-#define MSM_AUD_DECODER_MASK 0x0000FFFF
-#define MSM_AUD_OP_MASK 0xFFFF0000
-
-/*Playback mode*/
-#define NON_TUNNEL_MODE_PLAYBACK 1
-#define TUNNEL_MODE_PLAYBACK 0
-
-enum msm_aud_decoder_state {
- MSM_AUD_DECODER_STATE_NONE = 0,
- MSM_AUD_DECODER_STATE_FAILURE = 1,
- MSM_AUD_DECODER_STATE_SUCCESS = 2,
- MSM_AUD_DECODER_STATE_CLOSE = 3,
-};
-
-int audpp_adec_alloc(unsigned dec_attrb, const char **module_name,
- unsigned *queueid);
-void audpp_adec_free(int decid);
-
-struct audpp_event_callback {
- audpp_event_func fn;
- void *private;
-};
-
-int audpp_register_event_callback(struct audpp_event_callback *eh);
-int audpp_unregister_event_callback(struct audpp_event_callback *eh);
-int is_audpp_enable(void);
-
-int audpp_enable(int id, audpp_event_func func, void *private);
-void audpp_disable(int id, void *private);
-
-int audpp_send_queue1(void *cmd, unsigned len);
-int audpp_send_queue2(void *cmd, unsigned len);
-int audpp_send_queue3(void *cmd, unsigned len);
-
-int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
-int audpp_pause(unsigned id, int pause);
-int audpp_flush(unsigned id);
-void audpp_avsync(int id, unsigned rate);
-unsigned audpp_avsync_sample_count(int id);
-unsigned audpp_avsync_byte_count(int id);
-int audpp_dsp_set_mbadrc(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_mbadrc *mbadrc);
-int audpp_dsp_set_eq(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_eqalizer *eq);
-int audpp_dsp_set_rx_iir(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_pcm *iir);
-
-int audpp_dsp_set_rx_srs_trumedia_g
- (struct audpp_cmd_cfg_object_params_srstm_g *srstm);
-int audpp_dsp_set_rx_srs_trumedia_w
- (struct audpp_cmd_cfg_object_params_srstm_w *srstm);
-int audpp_dsp_set_rx_srs_trumedia_c
- (struct audpp_cmd_cfg_object_params_srstm_c *srstm);
-int audpp_dsp_set_rx_srs_trumedia_h
- (struct audpp_cmd_cfg_object_params_srstm_h *srstm);
-int audpp_dsp_set_rx_srs_trumedia_p
- (struct audpp_cmd_cfg_object_params_srstm_p *srstm);
-int audpp_dsp_set_rx_srs_trumedia_l
- (struct audpp_cmd_cfg_object_params_srstm_l *srstm);
-
-int audpp_dsp_set_vol_pan(unsigned id,
- audpp_cmd_cfg_object_params_volume *vol_pan);
-int audpp_dsp_set_qconcert_plus(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_qconcert *qconcert_plus);
-int audrectask_enable(unsigned enc_type, audrec_event_func func, void *private);
-void audrectask_disable(unsigned enc_type, void *private);
-
-int audrectask_send_cmdqueue(void *cmd, unsigned len);
-int audrectask_send_bitstreamqueue(void *cmd, unsigned len);
-
#endif
diff --git a/arch/arm/mach-msm/qdsp5/audmgr_new.h b/arch/arm/mach-msm/qdsp5/audmgr_new.h
index 2453022..20e27f1 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr_new.h
+++ b/arch/arm/mach-msm/qdsp5/audmgr_new.h
@@ -1,6 +1,6 @@
/* arch/arm/mach-msm/qdsp5/audmgr.h
*
- * Copyright 2008 (c) Code Aurora Forum. All rights reserved.
+ * Copyright 2008,2012 (c) Code Aurora Forum. All rights reserved.
* Copyright (C) 2008 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
@@ -194,21 +194,4 @@
int audmgr_close(struct audmgr *am);
int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg);
int audmgr_disable(struct audmgr *am);
-
-typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
-
-int audpp_enable(int id, audpp_event_func func, void *private);
-void audpp_disable(int id, void *private);
-
-int audpp_send_queue1(void *cmd, unsigned len);
-int audpp_send_queue2(void *cmd, unsigned len);
-int audpp_send_queue3(void *cmd, unsigned len);
-
-int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
-int audpp_pause(unsigned id, int pause);
-int audpp_flush(unsigned id);
-void audpp_avsync(int id, unsigned rate);
-unsigned audpp_avsync_sample_count(int id);
-unsigned audpp_avsync_byte_count(int id);
-
#endif
diff --git a/arch/arm/mach-msm/qdsp5/audpp.c b/arch/arm/mach-msm/qdsp5/audpp.c
index 1616ad0..b4ead5c 100644
--- a/arch/arm/mach-msm/qdsp5/audpp.c
+++ b/arch/arm/mach-msm/qdsp5/audpp.c
@@ -34,6 +34,8 @@
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
+#include <mach/qdsp5v2/audio_acdbi.h>
#include <mach/debug_mm.h>
#include "evlog.h"
@@ -85,19 +87,7 @@
#define AUDPP_CMD_IIR_FLAG_DIS 0x0000
#define AUDPP_CMD_IIR_FLAG_ENA -1
-#define AUDPP_CMD_VOLUME_PAN 0
-#define AUDPP_CMD_IIR_TUNING_FILTER 1
-#define AUDPP_CMD_EQUALIZER 2
-#define AUDPP_CMD_ADRC 3
-#define AUDPP_CMD_SPECTROGRAM 4
-#define AUDPP_CMD_QCONCERT 5
-#define AUDPP_CMD_SIDECHAIN_TUNING_FILTER 6
-#define AUDPP_CMD_SAMPLING_FREQUENCY 7
-#define AUDPP_CMD_QAFX 8
-#define AUDPP_CMD_QRUMBLE 9
-#define AUDPP_CMD_MBADRC 10
-
-#define MAX_EVENT_CALLBACK_CLIENTS 1
+#define MAX_EVENT_CALLBACK_CLIENTS 2
#define AUDPP_CONCURRENCY_DEFAULT 6 /* All non tunnel mode */
#define AUDPP_MAX_DECODER_CNT 5
@@ -335,6 +325,11 @@
case ADSP_MESSAGE_ID:
MM_DBG("Received ADSP event: module enable/disable(audpptask)");
break;
+ case AUDPP_MSG_FEAT_QUERY_DM_DONE:
+ MM_INFO(" RTC ACK --> %x %x %x\n", msg[0],\
+ msg[1], msg[2]);
+ acdb_rtc_set_err(msg[2]);
+ break;
default:
MM_ERR("unhandled msg id %x\n", id);
}
diff --git a/arch/arm/mach-msm/qdsp5/audpreproc.c b/arch/arm/mach-msm/qdsp5/audpreproc.c
index 230429f..92e54f8 100644
--- a/arch/arm/mach-msm/qdsp5/audpreproc.c
+++ b/arch/arm/mach-msm/qdsp5/audpreproc.c
@@ -1,7 +1,7 @@
/*
* Common code to deal with the AUDPREPROC dsp task (audio preprocessing)
*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* Based on the audpp layer in arch/arm/mach-msm/qdsp5/audpp.c
*
@@ -23,6 +23,8 @@
#include <mach/debug_mm.h>
#include <mach/qdsp5/qdsp5audpreproc.h>
#include <mach/qdsp5/qdsp5audreccmdi.h>
+#include <mach/qdsp5v2/audio_acdbi.h>
+
static DEFINE_MUTEX(audpreproc_lock);
@@ -56,6 +58,9 @@
(1<<AUDREC_CMD_TYPE_0_INDEX_QCELP))
#endif
+#define MAX_ENC_COUNT 2
+#define MAX_EVENT_CALLBACK_CLIENTS 2
+
struct msm_adspenc_database {
unsigned num_enc;
struct msm_adspenc_info *enc_info_list;
@@ -90,15 +95,237 @@
struct audpreproc_state {
struct msm_adsp_module *mod;
+ audpreproc_event_func func[MAX_ENC_COUNT];
+ void *private[MAX_ENC_COUNT];
struct mutex *lock;
unsigned open_count;
unsigned enc_inuse;
+ struct audpreproc_event_callback *cb_tbl[MAX_EVENT_CALLBACK_CLIENTS];
};
+static struct audrec_session_info session_info;
+
static struct audpreproc_state the_audpreproc_state = {
.lock = &audpreproc_lock,
};
+/* DSP preproc event handler */
+static void audpreproc_dsp_event(void *data, unsigned id, size_t len,
+ void (*getevent)(void *ptr, size_t len))
+{
+ struct audpreproc_state *audpreproc = data;
+ uint16_t msg[2];
+ MM_ERR("audpreproc_dsp_event %id", id);
+
+ getevent(msg, sizeof(msg));
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
+ if (audpreproc->func[0])
+ audpreproc->func[0](
+ audpreproc->private[0], id,
+ &msg);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ if (audpreproc->func[0])
+ audpreproc->func[0](
+ audpreproc->private[0], id,
+ &msg);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ if (audpreproc->func[0])
+ audpreproc->func[0](
+ audpreproc->private[0], id,
+ &msg);
+ break;
+ case AUDPREPROC_MSG_FEAT_QUERY_DM_DONE:
+ {
+ uint16_t msg[3];
+ getevent(msg, sizeof(msg));
+ MM_INFO("RTC ACK --> %x %x %x\n", msg[0], msg[1], msg[2]);
+ acdb_rtc_set_err(msg[2]);
+ }
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+ return;
+}
+
+static struct msm_adsp_ops adsp_ops = {
+ .event = audpreproc_dsp_event,
+};
+
+/* EXPORTED API's */
+int audpreproc_enable(int enc_id, audpreproc_event_func func, void *private)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ int res = 0;
+ uint16_t msg[2];
+ int n = 0;
+ MM_DBG("audpreproc_enable %d\n", enc_id);
+
+ if (enc_id < 0 || enc_id > (MAX_ENC_COUNT - 1))
+ return -EINVAL;
+
+ mutex_lock(audpreproc->lock);
+ if (audpreproc->func[enc_id]) {
+ res = -EBUSY;
+ goto out;
+ }
+
+ audpreproc->func[enc_id] = func;
+ audpreproc->private[enc_id] = private;
+
+ /* First client to enable preproc task */
+ if (audpreproc->open_count++ == 0) {
+ MM_DBG("Get AUDPREPROCTASK\n");
+ res = msm_adsp_get("AUDPREPROCTASK", &audpreproc->mod,
+ &adsp_ops, audpreproc);
+ if (res < 0) {
+ MM_ERR("Can not get AUDPREPROCTASK\n");
+ audpreproc->open_count = 0;
+ audpreproc->func[enc_id] = NULL;
+ audpreproc->private[enc_id] = NULL;
+ goto out;
+ }
+ if (msm_adsp_enable(audpreproc->mod)) {
+ audpreproc->open_count = 0;
+ audpreproc->func[enc_id] = NULL;
+ audpreproc->private[enc_id] = NULL;
+ msm_adsp_put(audpreproc->mod);
+ audpreproc->mod = NULL;
+ res = -ENODEV;
+ goto out;
+ }
+ }
+ msg[0] = AUDPREPROC_MSG_STATUS_FLAG_ENA;
+ /* Generate audpre enabled message for registered clients */
+ for (n = 0; n < MAX_EVENT_CALLBACK_CLIENTS; ++n) {
+ if (audpreproc->cb_tbl[n] &&
+ audpreproc->cb_tbl[n]->fn) {
+ audpreproc->cb_tbl[n]->fn( \
+ audpreproc->cb_tbl[n]->private,\
+ AUDPREPROC_MSG_CMD_CFG_DONE_MSG,
+ (void *) &msg);
+ }
+ }
+ res = 0;
+out:
+ mutex_unlock(audpreproc->lock);
+ return res;
+}
+EXPORT_SYMBOL(audpreproc_enable);
+
+
+void audpreproc_disable(int enc_id, void *private)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ uint16_t msg[2];
+ int n = 0;
+
+ if (enc_id < 0 || enc_id > (MAX_ENC_COUNT - 1))
+ return;
+
+ mutex_lock(audpreproc->lock);
+ if (!audpreproc->func[enc_id])
+ goto out;
+ if (audpreproc->private[enc_id] != private)
+ goto out;
+
+ audpreproc->func[enc_id] = NULL;
+ audpreproc->private[enc_id] = NULL;
+
+ /* Last client then disable preproc task */
+ if (--audpreproc->open_count == 0) {
+ msm_adsp_disable(audpreproc->mod);
+ MM_DBG("Put AUDPREPROCTASK\n");
+ msm_adsp_put(audpreproc->mod);
+ audpreproc->mod = NULL;
+ }
+ msg[0] = AUDPREPROC_MSG_STATUS_FLAG_DIS;
+ /* Generate audpre enabled message for registered clients */
+ for (n = 0; n < MAX_EVENT_CALLBACK_CLIENTS; ++n) {
+ if (audpreproc->cb_tbl[n] &&
+ audpreproc->cb_tbl[n]->fn) {
+ audpreproc->cb_tbl[n]->fn( \
+ audpreproc->cb_tbl[n]->private,\
+ AUDPREPROC_MSG_CMD_CFG_DONE_MSG,
+ (void *) &msg);
+ }
+ }
+out:
+ mutex_unlock(audpreproc->lock);
+ return;
+}
+EXPORT_SYMBOL(audpreproc_disable);
+
+int audpreproc_update_audrec_info(
+ struct audrec_session_info *audrec_session_info)
+{
+ if (!audrec_session_info) {
+ MM_ERR("error in audrec session info address\n");
+ return -EINVAL;
+ }
+ if (audrec_session_info->session_id < MAX_ENC_COUNT) {
+ memcpy(&session_info,
+ audrec_session_info,
+ sizeof(struct audrec_session_info));
+ return 0;
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audpreproc_update_audrec_info);
+
+int get_audrec_session_info(struct audrec_session_info *info)
+{
+ if (!info) {
+ MM_ERR("error in audrec session info address\n");
+ return -EINVAL;
+ }
+
+ if (the_audpreproc_state.open_count == 0) {
+ MM_ERR("No aud pre session active\n");
+ return -EINVAL;
+ }
+
+ memcpy(info, &session_info, sizeof(struct audrec_session_info));
+
+ return 0;
+}
+EXPORT_SYMBOL(get_audrec_session_info);
+
+int audpreproc_register_event_callback(struct audpreproc_event_callback *ecb)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ int i;
+
+ for (i = 0; i < MAX_EVENT_CALLBACK_CLIENTS; ++i) {
+ if (NULL == audpreproc->cb_tbl[i]) {
+ audpreproc->cb_tbl[i] = ecb;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audpreproc_register_event_callback);
+
+int audpreproc_unregister_event_callback(struct audpreproc_event_callback *ecb)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ int i;
+
+ for (i = 0; i < MAX_EVENT_CALLBACK_CLIENTS; ++i) {
+ if (ecb == audpreproc->cb_tbl[i]) {
+ audpreproc->cb_tbl[i] = NULL;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
/* enc_type = supported encode format *
* like pcm, aac, sbc, evrc, qcelp, amrnb etc ... *
*/
@@ -167,3 +394,37 @@
}
EXPORT_SYMBOL(audpreproc_aenc_free);
+
+int audpreproc_dsp_set_agc(
+ audpreproc_cmd_cfg_agc_params *agc_cfg,
+ unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, agc_cfg, len);
+}
+EXPORT_SYMBOL(audpreproc_dsp_set_agc);
+
+int audpreproc_dsp_set_ns(
+ audpreproc_cmd_cfg_ns_params *ns_cfg,
+ unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, ns_cfg, len);
+}
+EXPORT_SYMBOL(audpreproc_dsp_set_ns);
+
+int audpreproc_dsp_set_iir(
+ audpreproc_cmd_cfg_iir_tuning_filter_params *iir_cfg,
+ unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, iir_cfg, len);
+}
+EXPORT_SYMBOL(audpreproc_dsp_set_iir);
+
+int audpreproc_send_preproccmdqueue(void *cmd, unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, cmd, len);
+}
+EXPORT_SYMBOL(audpreproc_send_preproccmdqueue);
diff --git a/arch/arm/mach-msm/qdsp5/audrec.c b/arch/arm/mach-msm/qdsp5/audrec.c
index d5cb168..e238e32 100644
--- a/arch/arm/mach-msm/qdsp5/audrec.c
+++ b/arch/arm/mach-msm/qdsp5/audrec.c
@@ -2,7 +2,7 @@
*
* common code to deal with the AUDREC dsp task (audio recording)
*
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009,2012 Code Aurora Forum. All rights reserved.
*
* Based on the audpp layer in arch/arm/mach-msm/qdsp5/audpp.c
*
@@ -34,6 +34,7 @@
#include <mach/qdsp5/qdsp5audreccmdi.h>
#include <mach/qdsp5/qdsp5audrecmsg.h>
+#include <mach/qdsp5/qdsp5audpreproc.h>
#include "audmgr.h"
#include <mach/debug_mm.h>
diff --git a/arch/arm/mach-msm/qdsp5/snd_cad.c b/arch/arm/mach-msm/qdsp5/snd_cad.c
new file mode 100644
index 0000000..c0efa3b
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp5/snd_cad.c
@@ -0,0 +1,607 @@
+/* arch/arm/mach-msm/qdsp5/snd_cad.c
+ *
+ * interface to "snd" service on the baseband cpu
+ * This code also borrows from snd.c, which is
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2009, 2012 Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/msm_audio.h>
+#include <linux/seq_file.h>
+#include <asm/atomic.h>
+#include <asm/ioctls.h>
+#include <mach/board.h>
+#include <mach/msm_rpcrouter.h>
+#include <mach/debug_mm.h>
+#include <linux/debugfs.h>
+
+struct snd_cad_ctxt {
+ struct mutex lock;
+ int opened;
+ struct msm_rpc_endpoint *ept;
+ struct msm_cad_endpoints *cad_epts;
+};
+
+struct snd_cad_sys_ctxt {
+ struct mutex lock;
+ struct msm_rpc_endpoint *ept;
+};
+
+struct snd_curr_dev_info {
+ int rx_dev;
+ int tx_dev;
+};
+
+static struct snd_cad_sys_ctxt the_snd_cad_sys;
+
+static struct snd_cad_ctxt the_snd;
+static struct snd_curr_dev_info curr_dev;
+
+#define RPC_SND_PROG 0x30000002
+#define RPC_SND_CB_PROG 0x31000002
+
+#define RPC_SND_VERS 0x00030003
+
+#define SND_CAD_SET_DEVICE_PROC 40
+#define SND_CAD_SET_VOLUME_PROC 39
+#define MAX_SND_ACTIVE_DEVICE 2
+
+struct rpc_cad_set_device_args {
+ struct cad_devices_type device;
+ uint32_t ear_mute;
+ uint32_t mic_mute;
+
+ uint32_t cb_func;
+ uint32_t client_data;
+};
+
+struct rpc_cad_set_volume_args {
+ struct cad_devices_type device;
+ uint32_t method;
+ uint32_t volume;
+
+ uint32_t cb_func;
+ uint32_t client_data;
+};
+
+struct snd_cad_set_device_msg {
+ struct rpc_request_hdr hdr;
+ struct rpc_cad_set_device_args args;
+};
+
+struct snd_cad_set_volume_msg {
+ struct rpc_request_hdr hdr;
+ struct rpc_cad_set_volume_args args;
+};
+
+struct cad_endpoint *get_cad_endpoints(int *size);
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *dentry;
+
+static int rtc_getdevice_dbg_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ MM_INFO("debug intf %s\n", (char *) file->private_data);
+ return 0;
+}
+
+static ssize_t rtc_getdevice_dbg_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int n = 0;
+ static char *buffer;
+ static char *swap_buf;
+ const int debug_bufmax = 1024;
+ int swap_count = 0;
+ int rc = 0;
+ int dev_count = 0;
+ int dev_id = 0;
+ struct msm_cad_endpoints *msm_cad_epts = the_snd.cad_epts;
+ struct cad_endpoint *cad_epts;
+
+ buffer = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
+ if (buffer == NULL) {
+ MM_ERR("Memory allocation failed for buffer failed\n");
+ return -EFAULT;
+ }
+
+ swap_buf = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
+ if (swap_buf == NULL) {
+ MM_ERR("Memory allocation failed for swap buffer failed\n");
+ kfree(buffer);
+ return -EFAULT;
+ }
+
+ if (msm_cad_epts->num <= 0) {
+ dev_count = 0;
+ n = scnprintf(buffer, debug_bufmax, "DEV_NO:0x%x\n",
+ msm_cad_epts->num);
+ } else {
+ for (dev_id = 0; dev_id < msm_cad_epts->num; dev_id++) {
+ cad_epts = &msm_cad_epts->endpoints[dev_id];
+ if (IS_ERR(cad_epts)) {
+ MM_ERR("invalid snd endpoint for dev_id %d\n",
+ dev_id);
+ rc = PTR_ERR(cad_epts);
+ continue;
+ }
+
+ if ((cad_epts->id != curr_dev.tx_dev) &&
+ (cad_epts->id != curr_dev.rx_dev))
+ continue;
+
+ n += scnprintf(swap_buf + n, debug_bufmax - n,
+ "ACDB_ID:0x%x;CAPB:0x%x\n",
+ cad_epts->id,
+ cad_epts->capability);
+ dev_count++;
+ MM_DBG("RTC Get Device %x Capb %x Dev Count %x\n",
+ dev_id, cad_epts->capability,
+ dev_count);
+
+ }
+ }
+ swap_count = scnprintf(buffer, debug_bufmax, \
+ "DEV_NO:0x%x\n", dev_count);
+
+ memcpy(buffer+swap_count, swap_buf, n*sizeof(char));
+ n = n+swap_count;
+
+ buffer[n] = 0;
+ rc = simple_read_from_buffer(buf, count, ppos, buffer, n);
+ kfree(buffer);
+ kfree(swap_buf);
+ return rc;
+}
+
+static const struct file_operations rtc_acdb_debug_fops = {
+ .open = rtc_getdevice_dbg_open,
+ .read = rtc_getdevice_dbg_read
+};
+
+static int rtc_debugfs_create_entry(void)
+{
+ int rc = 0;
+ char name[sizeof "rtc_get_device"+1];
+
+ snprintf(name, sizeof name, "rtc_get_device");
+ dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+ NULL, NULL, &rtc_acdb_debug_fops);
+ if (IS_ERR(dentry)) {
+ MM_ERR("debugfs_create_file failed\n");
+ rc = PTR_ERR(dentry);
+ }
+ return rc;
+}
+#else
+static int rtc_debugfs_create_entry()
+{
+ return 0;
+}
+#endif
+
+static inline int check_mute(int mute)
+{
+ return (mute == SND_MUTE_MUTED ||
+ mute == SND_MUTE_UNMUTED) ? 0 : -EINVAL;
+}
+
+static int get_endpoint(struct snd_cad_ctxt *snd, unsigned long arg)
+{
+ int rc = 0, index;
+ struct msm_cad_endpoint ept;
+
+ if (copy_from_user(&ept, (void __user *)arg, sizeof(ept))) {
+ MM_ERR("cad_ioctl get endpoint: invalid read pointer\n");
+ return -EFAULT;
+ }
+
+ index = ept.id;
+ if (index < 0 || index >= snd->cad_epts->num) {
+ MM_ERR("snd_ioctl get endpoint: invalid index!\n");
+ return -EINVAL;
+ }
+
+ ept.id = snd->cad_epts->endpoints[index].id;
+ strlcpy(ept.name,
+ snd->cad_epts->endpoints[index].name,
+ sizeof(ept.name));
+
+ if (copy_to_user((void __user *)arg, &ept, sizeof(ept))) {
+ MM_ERR("snd_ioctl get endpoint: invalid write pointer\n");
+ rc = -EFAULT;
+ }
+
+ return rc;
+}
+
+static long snd_cad_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct snd_cad_set_device_msg dmsg;
+ struct snd_cad_set_volume_msg vmsg;
+
+ struct msm_cad_device_config dev;
+ struct msm_cad_volume_config vol;
+ struct snd_cad_ctxt *snd = file->private_data;
+ int rc = 0;
+
+ mutex_lock(&snd->lock);
+ switch (cmd) {
+ case SND_SET_DEVICE:
+ if (copy_from_user(&dev, (void __user *) arg, sizeof(dev))) {
+ MM_ERR("set device: invalid pointer\n");
+ rc = -EFAULT;
+ break;
+ }
+
+ dmsg.args.device.rx_device = cpu_to_be32(dev.device.rx_device);
+ dmsg.args.device.tx_device = cpu_to_be32(dev.device.tx_device);
+ dmsg.args.device.pathtype = cpu_to_be32(dev.device.pathtype);
+ dmsg.args.ear_mute = cpu_to_be32(dev.ear_mute);
+ dmsg.args.mic_mute = cpu_to_be32(dev.mic_mute);
+ if (check_mute(dev.ear_mute) < 0 ||
+ check_mute(dev.mic_mute) < 0) {
+ MM_ERR("set device: invalid mute status\n");
+ rc = -EINVAL;
+ break;
+ }
+ dmsg.args.cb_func = -1;
+ dmsg.args.client_data = 0;
+ curr_dev.tx_dev = dev.device.tx_device;
+ curr_dev.rx_dev = dev.device.rx_device;
+ MM_ERR("snd_cad_set_device %d %d %d %d\n", dev.device.rx_device,
+ dev.device.tx_device, dev.ear_mute, dev.mic_mute);
+
+ rc = msm_rpc_call(snd->ept,
+ SND_CAD_SET_DEVICE_PROC,
+ &dmsg, sizeof(dmsg), 5 * HZ);
+ break;
+
+ case SND_SET_VOLUME:
+ if (copy_from_user(&vol, (void __user *) arg, sizeof(vol))) {
+ MM_ERR("set volume: invalid pointer\n");
+ rc = -EFAULT;
+ break;
+ }
+
+ vmsg.args.device.rx_device = cpu_to_be32(dev.device.rx_device);
+ vmsg.args.device.tx_device = cpu_to_be32(dev.device.tx_device);
+ vmsg.args.method = cpu_to_be32(vol.method);
+ if (vol.method != SND_METHOD_VOICE) {
+ MM_ERR("set volume: invalid method\n");
+ rc = -EINVAL;
+ break;
+ }
+
+ vmsg.args.volume = cpu_to_be32(vol.volume);
+ vmsg.args.cb_func = -1;
+ vmsg.args.client_data = 0;
+
+ MM_ERR("snd_cad_set_volume %d %d %d %d\n", vol.device.rx_device,
+ vol.device.tx_device, vol.method, vol.volume);
+
+ rc = msm_rpc_call(snd->ept,
+ SND_CAD_SET_VOLUME_PROC,
+ &vmsg, sizeof(vmsg), 5 * HZ);
+
+ break;
+
+ case SND_GET_NUM_ENDPOINTS:
+ if (copy_to_user((void __user *)arg,
+ &snd->cad_epts->num, sizeof(unsigned))) {
+ MM_ERR("get endpoint: invalid pointer\n");
+ rc = -EFAULT;
+ }
+ break;
+
+ case SND_GET_ENDPOINT:
+ rc = get_endpoint(snd, arg);
+ break;
+
+ default:
+ MM_ERR("unknown command\n");
+ rc = -EINVAL;
+ break;
+ }
+ mutex_unlock(&snd->lock);
+
+ return rc;
+}
+
+static int snd_cad_release(struct inode *inode, struct file *file)
+{
+ struct snd_cad_ctxt *snd = file->private_data;
+ int rc;
+
+ mutex_lock(&snd->lock);
+ rc = msm_rpc_close(snd->ept);
+ if (rc < 0)
+ MM_ERR("msm_rpc_close failed\n");
+ snd->ept = NULL;
+ snd->opened = 0;
+ mutex_unlock(&snd->lock);
+ return 0;
+}
+static int snd_cad_sys_release(void)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ mutex_lock(&snd_cad_sys->lock);
+ rc = msm_rpc_close(snd_cad_sys->ept);
+ if (rc < 0)
+ MM_ERR("msm_rpc_close failed\n");
+ snd_cad_sys->ept = NULL;
+ mutex_unlock(&snd_cad_sys->lock);
+ return rc;
+}
+static int snd_cad_open(struct inode *inode, struct file *file)
+{
+ struct snd_cad_ctxt *snd = &the_snd;
+ int rc = 0;
+
+ mutex_lock(&snd->lock);
+ if (snd->opened == 0) {
+ if (snd->ept == NULL) {
+ snd->ept = msm_rpc_connect_compatible(RPC_SND_PROG,
+ RPC_SND_VERS, 0);
+ if (IS_ERR(snd->ept)) {
+ rc = PTR_ERR(snd->ept);
+ snd->ept = NULL;
+ MM_ERR("cad connect failed with VERS %x\n",
+ RPC_SND_VERS);
+ goto err;
+ }
+ }
+ file->private_data = snd;
+ snd->opened = 1;
+ } else {
+ MM_ERR("snd already opened\n");
+ rc = -EBUSY;
+ }
+
+err:
+ mutex_unlock(&snd->lock);
+ return rc;
+}
+static int snd_cad_sys_open(void)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ mutex_lock(&snd_cad_sys->lock);
+ if (snd_cad_sys->ept == NULL) {
+ snd_cad_sys->ept = msm_rpc_connect_compatible(RPC_SND_PROG,
+ RPC_SND_VERS, 0);
+ if (IS_ERR(snd_cad_sys->ept)) {
+ rc = PTR_ERR(snd_cad_sys->ept);
+ snd_cad_sys->ept = NULL;
+ MM_ERR("func %s : cad connect failed with VERS %x\n",
+ __func__, RPC_SND_VERS);
+ goto err;
+ }
+ } else
+ MM_DBG("snd already opened\n");
+err:
+ mutex_unlock(&snd_cad_sys->lock);
+ return rc;
+}
+
+static const struct file_operations snd_cad_fops = {
+ .owner = THIS_MODULE,
+ .open = snd_cad_open,
+ .release = snd_cad_release,
+ .unlocked_ioctl = snd_cad_ioctl,
+};
+
+struct miscdevice snd_cad_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_cad",
+ .fops = &snd_cad_fops,
+};
+
+static long snd_cad_vol_enable(const char *arg)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ struct snd_cad_set_volume_msg vmsg;
+ struct msm_cad_volume_config vol;
+ int rc = 0;
+
+ rc = sscanf(arg, "%d %d %d %d", &vol.device.rx_device,
+ &vol.device.tx_device, &vol.method, &vol.volume);
+ if (rc != 4) {
+ MM_ERR("Invalid arguments. Usage: <rx_device> <tx_device>" \
+ "method> <volume>\n");
+ rc = -EINVAL;
+ return rc;
+ }
+
+ vmsg.args.device.rx_device = cpu_to_be32(vol.device.rx_device);
+ vmsg.args.device.tx_device = cpu_to_be32(vol.device.tx_device);
+ vmsg.args.method = cpu_to_be32(vol.method);
+ if (vol.method != SND_METHOD_VOICE) {
+ MM_ERR("snd_cad_ioctl set volume: invalid method\n");
+ rc = -EINVAL;
+ return rc;
+ }
+
+ vmsg.args.volume = cpu_to_be32(vol.volume);
+ vmsg.args.cb_func = -1;
+ vmsg.args.client_data = 0;
+
+ MM_DBG("snd_cad_set_volume %d %d %d %d\n", vol.device.rx_device,
+ vol.device.rx_device, vol.method, vol.volume);
+
+ rc = msm_rpc_call(snd_cad_sys->ept,
+ SND_CAD_SET_VOLUME_PROC,
+ &vmsg, sizeof(vmsg), 5 * HZ);
+ return rc;
+}
+
+static long snd_cad_dev_enable(const char *arg)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ struct snd_cad_set_device_msg dmsg;
+ struct msm_cad_device_config dev;
+ int rc = 0;
+
+
+ rc = sscanf(arg, "%d %d %d %d", &dev.device.rx_device,
+ &dev.device.tx_device, &dev.ear_mute, &dev.mic_mute);
+ if (rc != 4) {
+ MM_ERR("Invalid arguments. Usage: <rx_device> <tx_device> "\
+ "<ear_mute> <mic_mute>\n");
+ rc = -EINVAL;
+ return rc;
+ }
+ dmsg.args.device.rx_device = cpu_to_be32(dev.device.rx_device);
+ dmsg.args.device.tx_device = cpu_to_be32(dev.device.tx_device);
+ dmsg.args.device.pathtype = cpu_to_be32(CAD_DEVICE_PATH_RX_TX);
+ dmsg.args.ear_mute = cpu_to_be32(dev.ear_mute);
+ dmsg.args.mic_mute = cpu_to_be32(dev.mic_mute);
+ if (check_mute(dev.ear_mute) < 0 ||
+ check_mute(dev.mic_mute) < 0) {
+ MM_ERR("snd_cad_ioctl set device: invalid mute status\n");
+ rc = -EINVAL;
+ return rc;
+ }
+ dmsg.args.cb_func = -1;
+ dmsg.args.client_data = 0;
+ curr_dev.tx_dev = dev.device.tx_device;
+ curr_dev.rx_dev = dev.device.rx_device;
+
+ MM_INFO("snd_cad_set_device %d %d %d %d\n", dev.device.rx_device,
+ dev.device.tx_device, dev.ear_mute, dev.mic_mute);
+
+ rc = msm_rpc_call(snd_cad_sys->ept,
+ SND_CAD_SET_DEVICE_PROC,
+ &dmsg, sizeof(dmsg), 5 * HZ);
+ return rc;
+}
+
+static ssize_t snd_cad_dev_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ rc = snd_cad_sys_open();
+ if (rc)
+ return rc;
+
+ mutex_lock(&snd_cad_sys->lock);
+ status = snd_cad_dev_enable(buf);
+ mutex_unlock(&snd_cad_sys->lock);
+
+ rc = snd_cad_sys_release();
+ if (rc)
+ return rc;
+
+ return status ? : size;
+}
+
+static ssize_t snd_cad_vol_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ rc = snd_cad_sys_open();
+ if (rc)
+ return rc;
+
+ mutex_lock(&snd_cad_sys->lock);
+ status = snd_cad_vol_enable(buf);
+ mutex_unlock(&snd_cad_sys->lock);
+
+ rc = snd_cad_sys_release();
+ if (rc)
+ return rc;
+
+ return status ? : size;
+}
+
+static DEVICE_ATTR(device, S_IWUSR | S_IRUGO,
+ NULL, snd_cad_dev_store);
+
+static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO,
+ NULL, snd_cad_vol_store);
+
+static int snd_cad_probe(struct platform_device *pdev)
+{
+ struct snd_cad_ctxt *snd = &the_snd;
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ mutex_init(&snd->lock);
+ mutex_init(&snd_cad_sys->lock);
+ snd_cad_sys->ept = NULL;
+ snd->cad_epts =
+ (struct msm_cad_endpoints *)pdev->dev.platform_data;
+ rc = misc_register(&snd_cad_misc);
+ if (rc)
+ return rc;
+
+ rc = device_create_file(snd_cad_misc.this_device, &dev_attr_device);
+ if (rc) {
+ misc_deregister(&snd_cad_misc);
+ return rc;
+ }
+
+ rc = device_create_file(snd_cad_misc.this_device, &dev_attr_volume);
+ if (rc) {
+ device_remove_file(snd_cad_misc.this_device,
+ &dev_attr_device);
+ misc_deregister(&snd_cad_misc);
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ rc = rtc_debugfs_create_entry();
+ if (rc) {
+ device_remove_file(snd_cad_misc.this_device,
+ &dev_attr_volume);
+ device_remove_file(snd_cad_misc.this_device,
+ &dev_attr_device);
+ misc_deregister(&snd_cad_misc);
+ }
+#endif
+ return rc;
+}
+
+static struct platform_driver snd_cad_plat_driver = {
+ .probe = snd_cad_probe,
+ .driver = {
+ .name = "msm_cad",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init snd_cad_init(void)
+{
+ return platform_driver_register(&snd_cad_plat_driver);
+}
+
+module_init(snd_cad_init);
+
+MODULE_DESCRIPTION("MSM CAD SND driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 8e0113c..b9f8bff 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -246,6 +246,7 @@
[127] = MSM_CPU_8625,
[128] = MSM_CPU_8625,
[129] = MSM_CPU_8625,
+ [137] = MSM_CPU_8625,
/* 8064 MPQ ID */
[130] = MSM_CPU_8064,
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 9240605..26e8496 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -307,6 +307,16 @@
This option enables support for LEDs connected to the PCA9633
LED driver chip accessed via the I2C bus.
+config LEDS_QPNP
+ tristate "Support for QPNP LEDs"
+ depends on SPMI && OF_SPMI
+ help
+ This driver supports the leds functionality of Qualcomm PNP PMIC. It
+ includes RGB Leds, WLED and Flash Led.
+
+ To compile this driver as a module, choose M here: the module will
+ be called leds-qpnp.
+
config LEDS_WM831X_STATUS
tristate "LED support for status LEDs on WM831x PMICs"
depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 8edd465..c688898 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -19,6 +19,7 @@
obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
obj-$(CONFIG_LEDS_PM8XXX) += leds-pm8xxx.o
+obj-$(CONFIG_LEDS_QPNP) += leds-qpnp.o
obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
new file mode 100644
index 0000000..f42fb5e
--- /dev/null
+++ b/drivers/leds/leds-qpnp.c
@@ -0,0 +1,725 @@
+
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/spmi.h>
+
+#define WLED_MOD_EN_REG(base, n) (base + 0x60 + n*0x10)
+#define WLED_IDAC_DLY_REG(base, n) (WLED_MOD_EN_REG(base, n) + 0x01)
+#define WLED_FULL_SCALE_REG(base, n) (WLED_IDAC_DLY_REG(base, n) + 0x01)
+
+/* wled control registers */
+#define WLED_BRIGHTNESS_CNTL_LSB(base, n) (base + 0x40 + 2*n)
+#define WLED_BRIGHTNESS_CNTL_MSB(base, n) (base + 0x41 + 2*n)
+#define WLED_MOD_CTRL_REG(base) (base + 0x46)
+#define WLED_SYNC_REG(base) (base + 0x47)
+#define WLED_FDBCK_CTRL_REG(base) (base + 0x48)
+#define WLED_SWITCHING_FREQ_REG(base) (base + 0x4C)
+#define WLED_OVP_CFG_REG(base) (base + 0x4D)
+#define WLED_BOOST_LIMIT_REG(base) (base + 0x4E)
+#define WLED_CURR_SINK_REG(base) (base + 0x4F)
+#define WLED_HIGH_POLE_CAP_REG(base) (base + 0x58)
+#define WLED_CURR_SINK_MASK 0xE0
+#define WLED_CURR_SINK_SHFT 0x05
+#define WLED_SWITCH_FREQ_MASK 0x02
+#define WLED_OVP_VAL_MASK 0x03
+#define WLED_OVP_VAL_BIT_SHFT 0x00
+#define WLED_BOOST_LIMIT_MASK 0x07
+#define WLED_BOOST_LIMIT_BIT_SHFT 0x00
+#define WLED_BOOST_ON 0x80
+#define WLED_BOOST_OFF 0x00
+#define WLED_EN_MASK 0x80
+#define WLED_NO_MASK 0x00
+#define WLED_CP_SELECT_MAX 0x03
+#define WLED_CP_SELECT_MASK 0x02
+#define WLED_USE_EXT_GEN_MOD_SRC 0x01
+#define WLED_CTL_DLY_STEP 200
+#define WLED_CTL_DLY_MAX 1400
+#define WLED_MAX_CURR 25
+#define WLED_MSB_MASK 0x0F
+#define WLED_MAX_CURR_MASK 0x19
+#define WLED_OP_FDBCK_MASK 0x07
+#define WLED_OP_FDBCK_BIT_SHFT 0x00
+
+#define WLED_MAX_LEVEL 255
+#define WLED_8_BIT_MASK 0xFF
+#define WLED_4_BIT_MASK 0x0F
+#define WLED_8_BIT_SHFT 0x08
+#define WLED_MAX_DUTY_CYCLE 0xFFF
+
+#define WLED_SYNC_VAL 0x07
+#define WLED_SYNC_RESET_VAL 0x00
+
+#define WLED_TRIGGER_DEFAULT "none"
+#define WLED_FLAGS_DEFAULT 0x00
+#define WLED_DEFAULT_STRINGS 0x01
+#define WLED_DEFAULT_OVP_VAL 0x02
+#define WLED_BOOST_LIM_DEFAULT 0x03
+#define WLED_CP_SEL_DEFAULT 0x00
+#define WLED_CTRL_DLY_DEFAULT 0x00
+#define WLED_SWITCH_FREQ_DEFAULT 0x02
+
+/**
+ * enum qpnp_leds - QPNP supported led ids
+ * @QPNP_ID_WLED - White led backlight
+ */
+enum qpnp_leds {
+ QPNP_ID_WLED,
+};
+
+/* current boost limit */
+enum wled_current_boost_limit {
+ WLED_CURR_LIMIT_105mA,
+ WLED_CURR_LIMIT_385mA,
+ WLED_CURR_LIMIT_525mA,
+ WLED_CURR_LIMIT_805mA,
+ WLED_CURR_LIMIT_980mA,
+ WLED_CURR_LIMIT_1260mA,
+ WLED_CURR_LIMIT_1400mA,
+ WLED_CURR_LIMIT_1680mA,
+};
+
+/* over voltage protection threshold */
+enum wled_ovp_threshold {
+ WLED_OVP_35V,
+ WLED_OVP_32V,
+ WLED_OVP_29V,
+ WLED_OVP_37V,
+};
+
+/* switch frquency */
+enum wled_switch_freq {
+ WLED_800kHz = 0,
+ WLED_960kHz,
+ WLED_1600kHz,
+ WLED_3200kHz,
+};
+
+static u8 wled_debug_regs[] = {
+ /* common registers */
+ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ /* LED1 */
+ 0x60, 0x61, 0x62, 0x63, 0x66,
+ /* LED1 */
+ 0x70, 0x71, 0x72, 0x73, 0x76,
+ /* LED1 */
+ 0x80, 0x81, 0x82, 0x83, 0x86,
+};
+
+/**
+ * wled_config_data - wled configuration data
+ * @num_strings - number of wled strings supported
+ * @ovp_val - over voltage protection threshold
+ * @boost_curr_lim - boot current limit
+ * @cp_select - high pole capacitance
+ * @ctrl_delay_us - delay in activation of led
+ * @dig_mod_gen_en - digital module generator
+ * @cs_out_en - current sink output enable
+ * @op_fdbck - selection of output as feedback for the boost
+ */
+struct wled_config_data {
+ u8 num_strings;
+ u8 ovp_val;
+ u8 boost_curr_lim;
+ u8 cp_select;
+ u8 ctrl_delay_us;
+ u8 switch_freq;
+ bool dig_mod_gen_en;
+ bool cs_out_en;
+ bool op_fdbck;
+};
+
+/**
+ * struct qpnp_led_data - internal led data structure
+ * @led_classdev - led class device
+ * @id - led index
+ * @base_reg - base register given in device tree
+ * @lock - to protect the transactions
+ * @reg - cached value of led register
+ * @max_current - maximum current supported by LED
+ * @default_on - true: default state max, false, default state 0
+ */
+struct qpnp_led_data {
+ struct led_classdev cdev;
+ struct spmi_device *spmi_dev;
+ int id;
+ u16 base;
+ u8 reg;
+ struct mutex lock;
+ struct wled_config_data *wled_cfg;
+ int max_current;
+ bool default_on;
+};
+
+static int
+qpnp_led_masked_write(struct qpnp_led_data *led, u16 addr, u8 mask, u8 val)
+{
+ int rc;
+ u8 reg;
+
+ rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ addr, ®, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read from addr=%x, rc(%d)\n", addr, rc);
+ }
+
+ reg &= ~mask;
+ reg |= val;
+
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ addr, ®, 1);
+ if (rc)
+ dev_err(&led->spmi_dev->dev,
+ "Unable to write to addr=%x, rc(%d)\n", addr, rc);
+ return rc;
+}
+
+static int qpnp_wled_set(struct qpnp_led_data *led)
+{
+ int rc, duty;
+ u8 level, val, i, num_wled_strings;
+
+ level = led->cdev.brightness;
+
+ if (level > WLED_MAX_LEVEL)
+ level = WLED_MAX_LEVEL;
+ if (level == 0) {
+ val = WLED_BOOST_OFF;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid, WLED_MOD_CTRL_REG(led->base),
+ &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED write ctrl reg failed(%d)\n", rc);
+ return rc;
+ }
+ } else {
+ val = WLED_BOOST_ON;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid, WLED_MOD_CTRL_REG(led->base),
+ &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED write ctrl reg failed(%d)\n", rc);
+ return rc;
+ }
+ }
+
+ duty = (WLED_MAX_DUTY_CYCLE * level) / WLED_MAX_LEVEL;
+
+ num_wled_strings = led->wled_cfg->num_strings;
+
+ /* program brightness control registers */
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = qpnp_led_masked_write(led,
+ WLED_BRIGHTNESS_CNTL_MSB(led->base, i), WLED_MSB_MASK,
+ (duty >> WLED_8_BIT_SHFT) & WLED_4_BIT_MASK);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED set brightness MSB failed(%d)\n", rc);
+ return rc;
+ }
+ val = duty & WLED_8_BIT_MASK;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid,
+ WLED_BRIGHTNESS_CNTL_LSB(led->base, i), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED set brightness LSB failed(%d)\n", rc);
+ return rc;
+ }
+ }
+
+ /* sync */
+ val = WLED_SYNC_VAL;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ WLED_SYNC_REG(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED set sync reg failed(%d)\n", rc);
+ return rc;
+ }
+
+ val = WLED_SYNC_RESET_VAL;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ WLED_SYNC_REG(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED reset sync reg failed(%d)\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
+static void qpnp_wled_dump_regs(struct qpnp_led_data *led)
+{
+ int i;
+ u8 val;
+
+ pr_debug("===== WLED register dump start =====\n");
+ for (i = 0; i < ARRAY_SIZE(wled_debug_regs); i++) {
+ spmi_ext_register_readl(led->spmi_dev->ctrl,
+ led->spmi_dev->sid,
+ led->base + wled_debug_regs[i],
+ &val, sizeof(val));
+ pr_debug("0x%x = 0x%x\n", led->base + wled_debug_regs[i], val);
+ }
+ pr_debug("===== WLED register dump end =====\n");
+}
+
+static void qpnp_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ int rc;
+ struct qpnp_led_data *led;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ if (value < LED_OFF || value > led->cdev.max_brightness) {
+ dev_err(led->cdev.dev, "Invalid brightness value\n");
+ return;
+ }
+
+ mutex_lock(&led->lock);
+ led->cdev.brightness = value;
+
+ switch (led->id) {
+ case QPNP_ID_WLED:
+ rc = qpnp_wled_set(led);
+ if (rc < 0)
+ dev_err(led->cdev.dev,
+ "WLED set brightness failed (%d)\n", rc);
+ break;
+ default:
+ dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+ break;
+ }
+ mutex_unlock(&led->lock);
+}
+
+static int __devinit qpnp_led_set_max_brightness(struct qpnp_led_data *led)
+{
+ switch (led->id) {
+ case QPNP_ID_WLED:
+ led->cdev.max_brightness = WLED_MAX_LEVEL;
+ break;
+ default:
+ dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum led_brightness qpnp_led_get(struct led_classdev *led_cdev)
+{
+ struct qpnp_led_data *led;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ return led->cdev.brightness;
+}
+
+static int __devinit qpnp_wled_init(struct qpnp_led_data *led)
+{
+ int rc, i;
+ u8 num_wled_strings;
+
+ num_wled_strings = led->wled_cfg->num_strings;
+
+ /* verify ranges */
+ if (led->wled_cfg->ovp_val > WLED_OVP_37V) {
+ dev_err(&led->spmi_dev->dev, "Invalid ovp value\n");
+ return -EINVAL;
+ }
+
+ if (led->wled_cfg->boost_curr_lim > WLED_CURR_LIMIT_1680mA) {
+ dev_err(&led->spmi_dev->dev, "Invalid boost current limit\n");
+ return -EINVAL;
+ }
+
+ if (led->wled_cfg->cp_select > WLED_CP_SELECT_MAX) {
+ dev_err(&led->spmi_dev->dev, "Invalid pole capacitance\n");
+ return -EINVAL;
+ }
+
+ if ((led->max_current > WLED_MAX_CURR)) {
+ dev_err(&led->spmi_dev->dev, "Invalid max current\n");
+ return -EINVAL;
+ }
+
+ if ((led->wled_cfg->ctrl_delay_us % WLED_CTL_DLY_STEP) ||
+ (led->wled_cfg->ctrl_delay_us > WLED_CTL_DLY_MAX)) {
+ dev_err(&led->spmi_dev->dev, "Invalid control delay\n");
+ return -EINVAL;
+ }
+
+ /* program over voltage protection threshold */
+ rc = qpnp_led_masked_write(led, WLED_OVP_CFG_REG(led->base),
+ WLED_OVP_VAL_MASK,
+ (led->wled_cfg->ovp_val << WLED_OVP_VAL_BIT_SHFT));
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED OVP reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program current boost limit */
+ rc = qpnp_led_masked_write(led, WLED_BOOST_LIMIT_REG(led->base),
+ WLED_BOOST_LIMIT_MASK, led->wled_cfg->boost_curr_lim);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED boost limit reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program output feedback */
+ rc = qpnp_led_masked_write(led, WLED_FDBCK_CTRL_REG(led->base),
+ WLED_OP_FDBCK_MASK,
+ (led->wled_cfg->op_fdbck << WLED_OP_FDBCK_BIT_SHFT));
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED fdbck ctrl reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program switch frequency */
+ rc = qpnp_led_masked_write(led, WLED_SWITCHING_FREQ_REG(led->base),
+ WLED_SWITCH_FREQ_MASK, led->wled_cfg->switch_freq);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED switch freq reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program current sink */
+ if (led->wled_cfg->cs_out_en) {
+ rc = qpnp_led_masked_write(led, WLED_CURR_SINK_REG(led->base),
+ WLED_CURR_SINK_MASK,
+ (led->wled_cfg->num_strings << WLED_CURR_SINK_SHFT));
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED curr sink reg write failed(%d)\n", rc);
+ return rc;
+ }
+ }
+
+ /* program high pole capacitance */
+ rc = qpnp_led_masked_write(led, WLED_HIGH_POLE_CAP_REG(led->base),
+ WLED_CP_SELECT_MASK, led->wled_cfg->cp_select);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED pole cap reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program modulator, current mod src and cabc */
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = qpnp_led_masked_write(led, WLED_MOD_EN_REG(led->base, i),
+ WLED_NO_MASK, WLED_EN_MASK);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED mod enable reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ if (led->wled_cfg->dig_mod_gen_en) {
+ rc = qpnp_led_masked_write(led,
+ WLED_MOD_EN_REG(led->base, i),
+ WLED_NO_MASK, WLED_USE_EXT_GEN_MOD_SRC);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED dig mod en reg write failed(%d)\n", rc);
+ }
+ }
+
+ rc = qpnp_led_masked_write(led,
+ WLED_FULL_SCALE_REG(led->base, i), WLED_MAX_CURR_MASK,
+ led->max_current);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED max current reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ }
+
+ /* dump wled registers */
+ qpnp_wled_dump_regs(led);
+
+ return 0;
+}
+
+static int __devinit qpnp_led_initialize(struct qpnp_led_data *led)
+{
+ int rc;
+
+ switch (led->id) {
+ case QPNP_ID_WLED:
+ rc = qpnp_wled_init(led);
+ if (rc)
+ dev_err(led->cdev.dev,
+ "WLED initialize failed(%d)\n", rc);
+ break;
+ default:
+ dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+/*
+ * Handlers for alternative sources of platform_data
+ */
+static int __devinit qpnp_get_config_wled(struct qpnp_led_data *led,
+ struct device_node *node)
+{
+ u32 val;
+ int rc;
+ const char *temp_string;
+
+ led->id = QPNP_ID_WLED;
+
+ led->wled_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ sizeof(struct wled_config_data), GFP_KERNEL);
+ if (!led->wled_cfg) {
+ dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ led->cdev.default_trigger = WLED_TRIGGER_DEFAULT;
+ rc = of_property_read_string(node, "linux,default-trigger",
+ &temp_string);
+ if (!rc)
+ led->cdev.default_trigger = temp_string;
+ else if (rc != -EINVAL)
+ return rc;
+
+
+ led->cdev.flags = WLED_FLAGS_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,flags", &val);
+ if (!rc)
+ led->cdev.flags = (int) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->default_on = true;
+ rc = of_property_read_string(node, "qcom,default-state",
+ &temp_string);
+ if (!rc) {
+ if (!strncmp(temp_string, "off", sizeof("off")))
+ led->default_on = false;
+ } else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->num_strings = WLED_DEFAULT_STRINGS;
+ rc = of_property_read_u32(node, "qcom,num-strings", &val);
+ if (!rc)
+ led->wled_cfg->num_strings = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->ovp_val = WLED_DEFAULT_OVP_VAL;
+ rc = of_property_read_u32(node, "qcom,ovp-val", &val);
+ if (!rc)
+ led->wled_cfg->ovp_val = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->boost_curr_lim = WLED_BOOST_LIM_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,boost-curr-lim", &val);
+ if (!rc)
+ led->wled_cfg->boost_curr_lim = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->cp_select = WLED_CP_SEL_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,cp-sel", &val);
+ if (!rc)
+ led->wled_cfg->cp_select = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->ctrl_delay_us = WLED_CTRL_DLY_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,ctrl-delay-us", &val);
+ if (!rc)
+ led->wled_cfg->ctrl_delay_us = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->switch_freq = WLED_SWITCH_FREQ_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,switch-freq", &val);
+ if (!rc)
+ led->wled_cfg->switch_freq = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->dig_mod_gen_en =
+ of_property_read_bool(node, "qcom,dig-mod-gen-en");
+
+ led->wled_cfg->cs_out_en =
+ of_property_read_bool(node, "qcom,cs-out-en");
+
+ led->wled_cfg->op_fdbck =
+ of_property_read_bool(node, "qcom,op-fdbck");
+
+ return 0;
+}
+
+static int __devinit qpnp_leds_probe(struct spmi_device *spmi)
+{
+ struct qpnp_led_data *led;
+ struct resource *led_resource;
+ struct device_node *node;
+ int rc;
+ const char *led_label;
+
+ led = devm_kzalloc(&spmi->dev, (sizeof(struct qpnp_led_data)),
+ GFP_KERNEL);
+ if (!led) {
+ dev_err(&spmi->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ led->spmi_dev = spmi;
+
+ led_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+ if (!led_resource) {
+ dev_err(&spmi->dev, "Unable to get LED base address\n");
+ return -ENXIO;
+ }
+ led->base = led_resource->start;
+
+ dev_set_drvdata(&spmi->dev, led);
+
+ node = led->spmi_dev->dev.of_node;
+ if (node == NULL)
+ return -ENODEV;
+
+ rc = of_property_read_string(node, "qcom,label", &led_label);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Failure reading label, rc = %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_string(node, "qcom,name", &led->cdev.name);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Failure reading led name, rc = %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,max-current", &led->max_current);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Failure reading max_current, rc = %d\n", rc);
+ return rc;
+ }
+
+ led->cdev.brightness_set = qpnp_led_set;
+ led->cdev.brightness_get = qpnp_led_get;
+ led->cdev.brightness = LED_OFF;
+
+ if (strncmp(led_label, "wled", sizeof("wled")) == 0) {
+ rc = qpnp_get_config_wled(led, node);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read wled config data\n");
+ return rc;
+ }
+ } else {
+ dev_err(&led->spmi_dev->dev, "No LED matching label\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&led->lock);
+
+ rc = qpnp_led_initialize(led);
+ if (rc < 0)
+ goto fail_id_check;
+
+ rc = qpnp_led_set_max_brightness(led);
+ if (rc < 0)
+ goto fail_id_check;
+
+
+ rc = led_classdev_register(&spmi->dev, &led->cdev);
+ if (rc) {
+ dev_err(&spmi->dev, "unable to register led %d,rc=%d\n",
+ led->id, rc);
+ goto fail_id_check;
+ }
+
+ /* configure default state */
+ if (led->default_on)
+ led->cdev.brightness = led->cdev.max_brightness;
+
+ qpnp_led_set(&led->cdev, led->cdev.brightness);
+
+ return 0;
+
+fail_id_check:
+ mutex_destroy(&led->lock);
+ led_classdev_unregister(&led->cdev);
+ return rc;
+}
+
+static int __devexit qpnp_leds_remove(struct spmi_device *spmi)
+{
+ struct qpnp_led_data *led = dev_get_drvdata(&spmi->dev);
+
+ mutex_destroy(&led->lock);
+ led_classdev_unregister(&led->cdev);
+
+ return 0;
+}
+static struct of_device_id spmi_match_table[] = {
+ { .compatible = "qcom,leds-qpnp",
+ }
+};
+
+static struct spmi_driver qpnp_leds_driver = {
+ .driver = {
+ .name = "qcom,leds-qpnp",
+ .of_match_table = spmi_match_table,
+ },
+ .probe = qpnp_leds_probe,
+ .remove = __devexit_p(qpnp_leds_remove),
+};
+
+static int __init qpnp_led_init(void)
+{
+ return spmi_driver_register(&qpnp_leds_driver);
+}
+module_init(qpnp_led_init);
+
+static void __exit qpnp_led_exit(void)
+{
+ spmi_driver_unregister(&qpnp_leds_driver);
+}
+module_exit(qpnp_led_exit);
+
+MODULE_DESCRIPTION("QPNP LEDs driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("leds:leds-qpnp");
diff --git a/drivers/media/video/msm/cci/msm_cci.c b/drivers/media/video/msm/cci/msm_cci.c
index ad3cc6a..3caa580 100644
--- a/drivers/media/video/msm/cci/msm_cci.c
+++ b/drivers/media/video/msm/cci/msm_cci.c
@@ -24,11 +24,10 @@
#include "msm_cam_cci_hwreg.h"
#define V4L2_IDENT_CCI 50005
-#define CCI_I2C_QUEUE_0_SIZE 2
+#define CCI_I2C_QUEUE_0_SIZE 64
#define CCI_I2C_QUEUE_1_SIZE 16
-#undef CDBG
-#define CDBG pr_debug
+#define CCI_TIMEOUT msecs_to_jiffies(100)
static void msm_cci_set_clk_param(struct cci_device *cci_dev)
{
@@ -127,8 +126,9 @@
msm_camera_io_w(reg_val, cci_dev->base + CCI_QUEUE_START_ADDR);
CDBG("%s line %d wait_for_completion_interruptible\n",
__func__, __LINE__);
- wait_for_completion_interruptible(&cci_dev->
- cci_master_info[master].reset_complete);
+ wait_for_completion_interruptible_timeout(&cci_dev->
+ cci_master_info[master].reset_complete, CCI_TIMEOUT);
+
rc = cci_dev->cci_master_info[master].status;
if (rc < 0)
pr_err("%s failed rc %d\n", __func__, rc);
@@ -234,6 +234,9 @@
read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
mutex_lock(&cci_dev->cci_master_info[master].mutex);
CDBG("%s master %d, queue %d\n", __func__, master, queue);
+ CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+ c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+ c_ctrl->cci_info->id_map);
val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
c_ctrl->cci_info->retries << 16 |
c_ctrl->cci_info->id_map << 18;
@@ -285,9 +288,8 @@
val = 1 << ((master * 2) + queue);
msm_camera_io_w(val, cci_dev->base + CCI_QUEUE_START_ADDR);
-
- wait_for_completion_interruptible(&cci_dev->
- cci_master_info[master].reset_complete);
+ wait_for_completion_interruptible_timeout(&cci_dev->
+ cci_master_info[master].reset_complete, CCI_TIMEOUT);
read_bytes = (read_cfg->num_byte / 4) + 1;
index = 0;
@@ -328,6 +330,9 @@
cci_dev = v4l2_get_subdevdata(sd);
master = c_ctrl->cci_info->cci_i2c_master;
CDBG("%s master %d, queue %d\n", __func__, master, queue);
+ CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+ c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+ c_ctrl->cci_info->id_map);
mutex_lock(&cci_dev->cci_master_info[master].mutex);
val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
c_ctrl->cci_info->retries << 16 |
@@ -366,7 +371,7 @@
val = msm_camera_io_r(cci_dev->base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR +
master * 0x200 + queue * 0x100);
- CDBG("%s line %d size of queue %d\n", __func__, __LINE__, val);
+ CDBG("%s:%d cur word count %d\n", __func__, __LINE__, val);
CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR\n", __func__, __LINE__);
msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR +
master * 0x200 + queue * 0x100);
@@ -378,8 +383,9 @@
CDBG("%s line %d wait_for_completion_interruptible\n",
__func__, __LINE__);
- wait_for_completion_interruptible(&cci_dev->
- cci_master_info[master].reset_complete);
+ wait_for_completion_interruptible_timeout(&cci_dev->
+ cci_master_info[master].reset_complete, CCI_TIMEOUT);
+
ERROR:
mutex_unlock(&cci_dev->cci_master_info[master].mutex);
return rc;
@@ -395,7 +401,10 @@
}
static struct msm_cam_clk_info cci_clk_info[] = {
- {"cci_clk_src", 19200000},
+ {"camss_top_ahb_clk", -1},
+ {"cci_src_clk", 19200000},
+ {"cci_ahb_clk", -1},
+ {"cci_clk", -1},
};
static int32_t msm_cci_init(struct v4l2_subdev *sd)
@@ -411,7 +420,7 @@
rc = msm_cam_clk_enable(&cci_dev->pdev->dev, cci_clk_info,
cci_dev->cci_clk, ARRAY_SIZE(cci_clk_info), 1);
if (rc < 0) {
- CDBG("%s: regulator enable failed\n", __func__);
+ CDBG("%s: clk enable failed\n", __func__);
goto clk_enable_failed;
}
@@ -421,8 +430,9 @@
cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_RESET_CMD_ADDR);
msm_camera_io_w(0x1, cci_dev->base + CCI_RESET_CMD_ADDR);
- wait_for_completion_interruptible(&cci_dev->cci_master_info[MASTER_0].
- reset_complete);
+ wait_for_completion_interruptible_timeout(
+ &cci_dev->cci_master_info[MASTER_0].reset_complete,
+ CCI_TIMEOUT);
msm_cci_set_clk_param(cci_dev);
msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_IRQ_MASK_0_ADDR);
msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
@@ -535,6 +545,12 @@
cci_dev->cci_master_info[MASTER_1].reset_pending = TRUE;
msm_camera_io_w(CCI_M1_RESET_RMSK,
cci_dev->base + CCI_RESET_CMD_ADDR);
+ } else {
+ pr_err("%s unhandled irq 0x%x\n", __func__, irq);
+ cci_dev->cci_master_info[MASTER_0].status = 0;
+ complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
+ cci_dev->cci_master_info[MASTER_1].status = 0;
+ complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
}
return IRQ_HANDLED;
}
@@ -686,11 +702,6 @@
goto cci_release_mem;
}
- CDBG("%s line %d cci irq start %d end %d\n", __func__,
- __LINE__,
- new_cci_dev->irq->start,
- new_cci_dev->irq->end);
-
new_cci_dev->pdev = pdev;
msm_cci_initialize_cci_params(new_cci_dev);
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
index c79748c..b66bee0 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
@@ -47,5 +47,6 @@
#define CSID_RST_STB_ALL 0x7FFF
#define CSID_DL_INPUT_SEL_SHIFT 0x2
#define CSID_PHY_SEL_SHIFT 0x17
+#define CSID_VERSION 0x02000011
#endif
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
index 93d1fc4..2e83101 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
@@ -28,6 +28,7 @@
#define MIPI_CSIPHY_LNCK_MISC1_ADDR 0x128
#define MIPI_CSIPHY_GLBL_RESET_ADDR 0x140
#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR 0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR 0x164
#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR 0x180
#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR 0x1A0
#define MIPI_CSIPHY_INTERRUPT_MASK_VAL 0x6F
@@ -37,5 +38,6 @@
#define MIPI_CSIPHY_MODE_CONFIG_SHIFT 0x4
#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR 0x1E0
#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR 0x1E8
+#define CSIPHY_VERSION 0x0
#endif
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
index ae842b2..d37d67e 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
@@ -64,6 +64,9 @@
#define MISC_LOGIC_RST_STB 1
#define STROBED_RST_EN 0
+#define ISPIF_RST_CMD_MASK 0xFE0F1FFF
+#define ISPIF_RST_CMD_1_MASK 0xFC0F1FF9
+
#define PIX_INTF_0_OVERFLOW_IRQ 12
#define RAW_INTF_0_OVERFLOW_IRQ 25
#define RAW_INTF_1_OVERFLOW_IRQ 25
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
index 27d5a06..ca21238 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
@@ -47,5 +47,6 @@
#define CSID_RST_STB_ALL 0x7FFF
#define CSID_DL_INPUT_SEL_SHIFT 0x4
#define CSID_PHY_SEL_SHIFT 0x17
+#define CSID_VERSION 0x30000000
#endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
index 79791bd..4e640e3 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
@@ -27,15 +27,17 @@
#define MIPI_CSIPHY_LNCK_MISC1_ADDR 0x128
#define MIPI_CSIPHY_GLBL_RESET_ADDR 0x140
#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR 0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR 0x164
#define MIPI_CSIPHY_HW_VERSION_ADDR 0x188
#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR 0x18C
#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR 0x1AC
#define MIPI_CSIPHY_INTERRUPT_MASK_VAL 0x3F
-#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR 0x1B0
+#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR 0x1AC
#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR 0x1CC
-#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR 0x1D0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR 0x1CC
#define MIPI_CSIPHY_MODE_CONFIG_SHIFT 0x4
#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR 0x1EC
#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR 0x1F4
+#define CSIPHY_VERSION 0x10
#endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
index 5b13cc5..7c09c4f 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
@@ -78,6 +78,9 @@
#define MISC_LOGIC_RST_STB 1
#define STROBED_RST_EN 0
+#define ISPIF_RST_CMD_MASK 0xFE0F1FFF
+#define ISPIF_RST_CMD_1_MASK 0xFC0F1FF9
+
#define PIX_INTF_0_OVERFLOW_IRQ 12
#define RAW_INTF_0_OVERFLOW_IRQ 25
#define RAW_INTF_1_OVERFLOW_IRQ 25
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 8f6a98b..7996ed1 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -22,6 +22,8 @@
#include "msm_cam_server.h"
#define V4L2_IDENT_CSID 50002
+#define CSID_VERSION_V2 0x02000011
+#define CSID_VERSION_V3 0x30000000
#define DBG_CSID 0
@@ -160,17 +162,30 @@
return 0;
}
-static struct msm_cam_clk_info csid_clk_info[] = {
+static struct msm_cam_clk_info csid_8960_clk_info[] = {
{"csi_src_clk", 177780000},
{"csi_clk", -1},
{"csi_phy_clk", -1},
{"csi_pclk", -1},
};
-static struct camera_vreg_t csid_vreg_info[] = {
+static struct msm_cam_clk_info csid_8974_clk_info[] = {
+ {"csi_ahb_clk", -1},
+ {"csi_src_clk", 200000000},
+ {"csi_clk", -1},
+ {"csi_phy_clk", -1},
+ {"csi_pix_clk", -1},
+ {"csi_rdi_clk", -1},
+};
+
+static struct camera_vreg_t csid_8960_vreg_info[] = {
{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
};
+static struct camera_vreg_t csid_8974_vreg_info[] = {
+ {"mipi_csi_vdd", REG_LDO, 1800000, 1800000, 12000},
+};
+
static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
{
int rc = 0;
@@ -188,25 +203,54 @@
return rc;
}
- rc = msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), NULL, 0, &csid_dev->csi_vdd, 1);
- if (rc < 0) {
- pr_err("%s: regulator on failed\n", __func__);
- goto vreg_config_failed;
- }
+ if (CSID_VERSION <= CSID_VERSION_V2) {
+ rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator on failed\n", __func__);
+ goto vreg_config_failed;
+ }
- rc = msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), NULL, 0, &csid_dev->csi_vdd, 1);
- if (rc < 0) {
- pr_err("%s: regulator enable failed\n", __func__);
- goto vreg_enable_failed;
- }
+ rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto vreg_enable_failed;
+ }
- rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
- csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
- if (rc < 0) {
- pr_err("%s: regulator enable failed\n", __func__);
- goto clk_enable_failed;
+ rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+ csid_8960_clk_info, csid_dev->csid_clk,
+ ARRAY_SIZE(csid_8960_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto clk_enable_failed;
+ }
+ } else if (CSID_VERSION == CSID_VERSION_V3) {
+ rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator on failed\n", __func__);
+ goto vreg_config_failed;
+ }
+
+ rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto vreg_enable_failed;
+ }
+
+ rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+ csid_8974_clk_info, csid_dev->csid_clk,
+ ARRAY_SIZE(csid_8974_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto clk_enable_failed;
+ }
}
csid_dev->hw_version =
@@ -221,11 +265,25 @@
return rc;
clk_enable_failed:
- msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), NULL, 0, &csid_dev->csi_vdd, 0);
+ if (CSID_VERSION <= CSID_VERSION_V2) {
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ } else if (CSID_VERSION == CSID_VERSION_V3) {
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ }
vreg_enable_failed:
- msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), NULL, 0, &csid_dev->csi_vdd, 0);
+ if (CSID_VERSION <= CSID_VERSION_V2) {
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ } else if (CSID_VERSION == CSID_VERSION_V3) {
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ }
vreg_config_failed:
iounmap(csid_dev->base);
csid_dev->base = NULL;
@@ -242,14 +300,29 @@
disable_irq(csid_dev->irq->start);
- msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
- csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
+ if (csid_dev->hw_version <= CSID_VERSION_V2) {
+ msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8960_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_8960_clk_info), 0);
- msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), NULL, 0, &csid_dev->csi_vdd, 0);
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
- msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), NULL, 0, &csid_dev->csi_vdd, 0);
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ } else if (csid_dev->hw_version == CSID_VERSION_V3) {
+ msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8974_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_8974_clk_info), 0);
+
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ }
iounmap(csid_dev->base);
csid_dev->base = NULL;
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index 4e07b6a..3113295 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -78,6 +78,7 @@
csiphybase + MIPI_CSIPHY_GLBL_RESET_ADDR);
}
+ lane_mask &= 0x1f;
while (lane_mask & 0x1f) {
if (!(lane_mask & 0x1)) {
j++;
@@ -105,18 +106,23 @@
int i;
struct csiphy_device *csiphy_dev = data;
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < 8; i++) {
irq = msm_camera_io_r(
csiphy_dev->base +
MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR + 0x4*i);
msm_camera_io_w(irq,
csiphy_dev->base +
MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
- CDBG("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
+ pr_err("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
__func__, csiphy_dev->pdev->id, i, irq);
+ msm_camera_io_w(0x1, csiphy_dev->base +
+ MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+ msm_camera_io_w(0x0, csiphy_dev->base +
+ MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+ msm_camera_io_w(0x0,
+ csiphy_dev->base +
+ MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
}
- msm_camera_io_w(0x1, csiphy_dev->base + 0x164);
- msm_camera_io_w(0x0, csiphy_dev->base + 0x164);
return IRQ_HANDLED;
}
@@ -136,11 +142,17 @@
return 0;
}
-static struct msm_cam_clk_info csiphy_clk_info[] = {
+static struct msm_cam_clk_info csiphy_8960_clk_info[] = {
{"csiphy_timer_src_clk", 177780000},
{"csiphy_timer_clk", -1},
};
+static struct msm_cam_clk_info csiphy_8974_clk_info[] = {
+ {"ispif_ahb_clk", -1},
+ {"csiphy_timer_src_clk", 200000000},
+ {"csiphy_timer_clk", -1},
+};
+
static int msm_csiphy_init(struct csiphy_device *csiphy_dev)
{
int rc = 0;
@@ -165,8 +177,14 @@
return rc;
}
- rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
- csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 1);
+ if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+ rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8960_clk_info), 1);
+ else
+ rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8974_clk_info), 1);
if (rc < 0) {
pr_err("%s: csiphy clk enable failed\n", __func__);
@@ -235,8 +253,14 @@
#if DBG_CSIPHY
disable_irq(csiphy_dev->irq->start);
#endif
- msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
- csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 0);
+ if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+ msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8960_clk_info), 0);
+ else
+ msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8974_clk_info), 0);
iounmap(csiphy_dev->base);
csiphy_dev->base = NULL;
@@ -317,7 +341,6 @@
int rc = 0;
struct msm_cam_subdev_info sd_info;
- CDBG("%s: device id = %d\n", __func__, pdev->id);
new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
if (!new_csiphy_dev) {
pr_err("%s: no enough memory\n", __func__);
@@ -337,6 +360,7 @@
if (pdev->dev.of_node)
of_property_read_u32((&pdev->dev)->of_node,
"cell-index", &pdev->id);
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
new_csiphy_dev->mem = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "csiphy");
diff --git a/drivers/media/video/msm/csi/msm_csiphy.h b/drivers/media/video/msm/csi/msm_csiphy.h
index 01eacb6..4b2e68e 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.h
+++ b/drivers/media/video/msm/csi/msm_csiphy.h
@@ -30,7 +30,7 @@
struct mutex mutex;
uint32_t hw_version;
- struct clk *csiphy_clk[2];
+ struct clk *csiphy_clk[3];
uint8_t ref_count;
uint16_t lane_mask[MAX_CSIPHY];
};
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index 479fc028..ab97138 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -37,7 +37,6 @@
{
int rc = 0;
uint32_t data = (0x1 << STROBED_RST_EN);
- uint32_t data1 = (0x1 << STROBED_RST_EN);
uint16_t intfnum = 0, mask = intfmask;
while (mask != 0) {
@@ -48,49 +47,29 @@
}
switch (intfnum) {
case PIX0:
- if (vfe_intf == VFE0)
- data |= (0x1 << PIX_0_VFE_RST_STB) |
- (0x1 << PIX_0_CSID_RST_STB);
- else
- data1 |= (0x1 << PIX_0_VFE_RST_STB) |
- (0x1 << PIX_0_CSID_RST_STB);
+ data |= (0x1 << PIX_0_VFE_RST_STB) |
+ (0x1 << PIX_0_CSID_RST_STB);
ispif->pix_sof_count = 0;
break;
case RDI0:
- if (vfe_intf == VFE0)
- data |= (0x1 << RDI_0_VFE_RST_STB) |
- (0x1 << RDI_0_CSID_RST_STB);
- else
- data1 |= (0x1 << RDI_0_VFE_RST_STB) |
- (0x1 << RDI_0_CSID_RST_STB);
+ data |= (0x1 << RDI_0_VFE_RST_STB) |
+ (0x1 << RDI_0_CSID_RST_STB);
break;
case PIX1:
- if (vfe_intf == VFE0)
- data |= (0x1 << PIX_1_VFE_RST_STB) |
- (0x1 << PIX_1_CSID_RST_STB);
- else
- data1 |= (0x1 << PIX_1_VFE_RST_STB) |
- (0x1 << PIX_1_CSID_RST_STB);
+ data |= (0x1 << PIX_1_VFE_RST_STB) |
+ (0x1 << PIX_1_CSID_RST_STB);
break;
case RDI1:
- if (vfe_intf == VFE0)
- data |= (0x1 << RDI_1_VFE_RST_STB) |
- (0x1 << RDI_1_CSID_RST_STB);
- else
- data1 |= (0x1 << RDI_1_VFE_RST_STB) |
- (0x1 << RDI_1_CSID_RST_STB);
+ data |= (0x1 << RDI_1_VFE_RST_STB) |
+ (0x1 << RDI_1_CSID_RST_STB);
break;
case RDI2:
- if (vfe_intf == VFE0)
- data |= (0x1 << RDI_2_VFE_RST_STB) |
- (0x1 << RDI_2_CSID_RST_STB);
- else
- data1 |= (0x1 << RDI_2_VFE_RST_STB) |
- (0x1 << RDI_2_CSID_RST_STB);
+ data |= (0x1 << RDI_2_VFE_RST_STB) |
+ (0x1 << RDI_2_CSID_RST_STB);
break;
default:
@@ -100,43 +79,26 @@
mask >>= 1;
intfnum++;
} /*end while */
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- rc = wait_for_completion_interruptible(&ispif->reset_complete);
- if (ispif->csid_version >= CSID_VERSION_V3 && data1 > 0x1) {
- msm_camera_io_w(data1,
- ispif->base + ISPIF_RST_CMD_1_ADDR);
- rc = wait_for_completion_interruptible(&ispif->
- reset_complete);
+ if (data > 0x1) {
+ if (vfe_intf == VFE0)
+ msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
+ else
+ msm_camera_io_w(data, ispif->base +
+ ISPIF_RST_CMD_1_ADDR);
+ rc = wait_for_completion_interruptible(&ispif->reset_complete);
}
-
return rc;
}
static int msm_ispif_reset(struct ispif_device *ispif)
{
int rc = 0;
- uint32_t data = (0x1 << STROBED_RST_EN) |
- (0x1 << SW_REG_RST_STB) |
- (0x1 << MISC_LOGIC_RST_STB) |
- (0x1 << PIX_0_VFE_RST_STB) |
- (0x1 << PIX_0_CSID_RST_STB) |
- (0x1 << RDI_0_VFE_RST_STB) |
- (0x1 << RDI_0_CSID_RST_STB) |
- (0x1 << RDI_1_VFE_RST_STB) |
- (0x1 << RDI_1_CSID_RST_STB);
-
- if (ispif->csid_version >= CSID_VERSION_V2)
- data |= (0x1 << PIX_1_VFE_RST_STB) |
- (0x1 << PIX_1_CSID_RST_STB) |
- (0x1 << RDI_2_VFE_RST_STB) |
- (0x1 << RDI_2_CSID_RST_STB);
ispif->pix_sof_count = 0;
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
+ msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR);
+ if (ispif->csid_version == CSID_VERSION_V3)
+ msm_camera_io_w(ISPIF_RST_CMD_1_MASK, ispif->base +
+ ISPIF_RST_CMD_1_ADDR);
rc = wait_for_completion_interruptible(&ispif->reset_complete);
- if (ispif->csid_version >= CSID_VERSION_V3) {
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_1_ADDR);
- rc = wait_for_completion_interruptible(&ispif->reset_complete);
- }
return rc;
}
@@ -155,15 +117,15 @@
int rc = 0;
uint32_t data;
- if (ispif->ispif_clk[intftype] == NULL) {
- pr_err("%s: ispif NULL clk\n", __func__);
- return;
+ if (ispif->csid_version <= CSID_VERSION_V2) {
+ if (ispif->ispif_clk[intftype] == NULL) {
+ pr_err("%s: ispif NULL clk\n", __func__);
+ return;
+ }
+ rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
+ if (rc < 0)
+ pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
}
-
- rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
- if (rc < 0)
- pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
-
data = msm_camera_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR +
(0x200 * vfe_intf));
switch (intftype) {
@@ -566,7 +528,6 @@
struct ispif_isr_queue_cmd *qcmd = NULL;
struct ispif_device *ispif;
- CDBG("=== ispif_do_tasklet start ===\n");
ispif = (struct ispif_device *)data;
while (atomic_read(&ispif_irq_cnt)) {
@@ -606,7 +567,6 @@
spin_unlock_irqrestore(&ispif_sof_lock, flags);
kfree(qcmd);
}
- CDBG("=== ispif_do_tasklet end ===\n");
}
static void ispif_process_irq(struct ispif_device *ispif,
@@ -615,7 +575,6 @@
unsigned long flags;
struct ispif_isr_queue_cmd *qcmd;
- CDBG("ispif_process_irq\n");
qcmd = kzalloc(sizeof(struct ispif_isr_queue_cmd),
GFP_ATOMIC);
if (!qcmd) {
@@ -646,6 +605,7 @@
static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
void *data)
{
+ uint32_t status0 = 0, status1 = 0, status2 = 0;
struct ispif_device *ispif = (struct ispif_device *)data;
out->ispifIrqStatus0 = msm_camera_io_r(ispif->base +
ISPIF_IRQ_STATUS_ADDR);
@@ -660,8 +620,9 @@
msm_camera_io_w(out->ispifIrqStatus2,
ispif->base + ISPIF_IRQ_CLEAR_2_ADDR);
- CDBG("%s: irq ispif->irq: Irq_status0 = 0x%x\n", __func__,
- out->ispifIrqStatus0);
+ CDBG("%s: irq vfe0 Irq_status0 = 0x%x, 1 = 0x%x, 2 = 0x%x\n",
+ __func__, out->ispifIrqStatus0, out->ispifIrqStatus1,
+ out->ispifIrqStatus2);
if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
if (out->ispifIrqStatus0 & (0x1 << RESET_DONE_IRQ))
complete(&ispif->reset_complete);
@@ -678,6 +639,22 @@
(out->ispifIrqStatus2 & ISPIF_IRQ_STATUS_RDI2_SOF_MASK))
ispif_process_irq(ispif, out);
}
+ if (ispif->csid_version == CSID_VERSION_V3) {
+ status0 = msm_camera_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_ADDR + 0x200);
+ msm_camera_io_w(status0,
+ ispif->base + ISPIF_IRQ_CLEAR_ADDR + 0x200);
+ status1 = msm_camera_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_1_ADDR + 0x200);
+ msm_camera_io_w(status1,
+ ispif->base + ISPIF_IRQ_CLEAR_1_ADDR + 0x200);
+ status2 = msm_camera_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_2_ADDR + 0x200);
+ msm_camera_io_w(status2,
+ ispif->base + ISPIF_IRQ_CLEAR_2_ADDR + 0x200);
+ CDBG("%s: irq vfe1 Irq_status0 = 0x%x, 1 = 0x%x, 2 = 0x%x\n",
+ __func__, status0, status1, status2);
+ }
msm_camera_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
}
@@ -689,7 +666,7 @@
return IRQ_HANDLED;
}
-static struct msm_cam_clk_info ispif_clk_info[] = {
+static struct msm_cam_clk_info ispif_8960_clk_info[] = {
{"csi_pix_clk", 0},
{"csi_rdi_clk", 0},
{"csi_pix1_clk", 0},
@@ -712,14 +689,14 @@
ispif_do_tasklet, (unsigned long)ispif);
ispif->csid_version = *csid_version;
- if (ispif->csid_version >= CSID_VERSION_V2) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 1);
+ if (ispif->csid_version < CSID_VERSION_V2) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk, 2, 1);
if (rc < 0)
return rc;
- } else {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
- ispif->ispif_clk, 2, 1);
+ } else if (ispif->csid_version == CSID_VERSION_V2) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 1);
if (rc < 0)
return rc;
}
@@ -733,12 +710,13 @@
free_irq(ispif->irq->start, ispif);
tasklet_kill(&ispif->ispif_tasklet);
- if (ispif->csid_version == CSID_VERSION_V2)
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 0);
- else
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+ if (ispif->csid_version < CSID_VERSION_V2) {
+ msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
ispif->ispif_clk, 2, 0);
+ } else if (ispif->csid_version == CSID_VERSION_V2) {
+ msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
+ }
}
static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/video/msm/io/msm_camera_i2c.c
index d05f1f2..27ebac5 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c.c
@@ -84,6 +84,7 @@
cci_ctrl.cci_info = client->cci_client;
cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = ®_conf_tbl;
cci_ctrl.cfg.cci_i2c_write_cfg.data_type = data_type;
+ cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
cci_ctrl.cfg.cci_i2c_write_cfg.size = 1;
rc = v4l2_subdev_call(client->cci_client->cci_subdev,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
@@ -381,6 +382,7 @@
cci_ctrl.cci_info = client->cci_client;
cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = reg_conf_tbl;
cci_ctrl.cfg.cci_i2c_write_cfg.data_type = data_type;
+ cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
cci_ctrl.cfg.cci_i2c_write_cfg.size = size;
rc = v4l2_subdev_call(client->cci_client->cci_subdev,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index 605efff..35b3bd4 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -27,19 +27,6 @@
#define S_I2C_DBG(fmt, args...) CDBG(fmt, ##args)
#endif
-enum msm_camera_i2c_cmd_type {
- MSM_CAMERA_I2C_CMD_WRITE,
- MSM_CAMERA_I2C_CMD_POLL,
-};
-
-struct msm_camera_i2c_reg_conf {
- uint16_t reg_addr;
- uint16_t reg_data;
- enum msm_camera_i2c_data_type dt;
- enum msm_camera_i2c_cmd_type cmd_type;
- int16_t mask;
-};
-
struct msm_camera_i2c_client {
struct i2c_client *client;
struct msm_camera_cci_client *cci_client;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 0d15f75..98b2372 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1278,11 +1278,21 @@
{
int rc = -ENOMEM;
struct video_device *pvdev = NULL;
- struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
+ struct i2c_client *client = NULL;
+ struct platform_device *pdev = NULL;
D("%s\n", __func__);
/* first register the v4l2 device */
- pcam->v4l2_dev.dev = &client->dev;
+ if (pcam->sensor_sdev->flags & V4L2_SUBDEV_FL_IS_I2C) {
+ client = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->v4l2_dev.dev = &client->dev;
+ pcam->media_dev.dev = &client->dev;
+ } else {
+ pdev = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->v4l2_dev.dev = &pdev->dev;
+ pcam->media_dev.dev = &pdev->dev;
+ }
+
rc = v4l2_device_register(pcam->v4l2_dev.dev, &pcam->v4l2_dev);
if (rc < 0)
return -EINVAL;
@@ -1299,7 +1309,6 @@
strlcpy(pcam->media_dev.model, QCAMERA_NAME,
sizeof(pcam->media_dev.model));
- pcam->media_dev.dev = &client->dev;
rc = media_device_register(&pcam->media_dev);
pvdev->v4l2_dev = &pcam->v4l2_dev;
pcam->v4l2_dev.mdev = &pcam->media_dev;
@@ -1358,7 +1367,7 @@
D("%s called\n", __func__);
- if (!actuator_info)
+ if (!actuator_info || !actuator_info->board_info)
goto probe_fail;
adapter = i2c_get_adapter(actuator_info->bus_id);
@@ -1401,7 +1410,7 @@
D("%s called\n", __func__);
- if (!eeprom_info)
+ if (!eeprom_info || !eeprom_info->board_info)
goto probe_fail;
adapter = i2c_get_adapter(eeprom_info->bus_id);
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index fac1ffd..0711ca5 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -1601,12 +1601,20 @@
{
int rc = -EINVAL;
struct video_device *pvdev = NULL;
- struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
-
+ struct i2c_client *client = NULL;
+ struct platform_device *pdev = NULL;
D("%s\n", __func__);
/* first register the v4l2 device */
- pcam->mctl_node.v4l2_dev.dev = &client->dev;
+ if (pcam->sensor_sdev->flags & V4L2_SUBDEV_FL_IS_I2C) {
+ client = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->mctl_node.v4l2_dev.dev = &client->dev;
+ } else {
+ pdev = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->mctl_node.v4l2_dev.dev = &pdev->dev;
+ }
+
+ /* first register the v4l2 device */
rc = v4l2_device_register(pcam->mctl_node.v4l2_dev.dev,
&pcam->mctl_node.v4l2_dev);
if (rc < 0)
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 69584d5..6c03002 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -9,7 +9,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
#include "msm_sensor.h"
#include "msm_sensor_common.h"
#include "msm.h"
@@ -274,6 +275,7 @@
}
return rc;
}
+
int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
int update_type, int res)
{
@@ -562,10 +564,15 @@
return rc;
}
-static struct msm_cam_clk_info cam_clk_info[] = {
+static struct msm_cam_clk_info cam_8960_clk_info[] = {
{"cam_clk", MSM_SENSOR_MCLK_24HZ},
};
+static struct msm_cam_clk_info cam_8974_clk_info[] = {
+ {"cam_src_clk", 19200000},
+ {"cam_clk", -1},
+};
+
int32_t msm_sensor_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
{
struct v4l2_subdev *i2c_mux_sd =
@@ -710,7 +717,8 @@
}
static int32_t msm_sensor_init_gpio_common_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size)
{
int32_t rc = 0, i = 0;
uint32_t count = 0;
@@ -720,9 +728,14 @@
return 0;
count /= sizeof(uint32_t);
-
- if (!count)
+ if (!count) {
+ pr_err("%s gpio_common_tbl_num 0\n", __func__);
return 0;
+ } else if (count > gpio_array_size) {
+ pr_err("%s gpio common tbl size exceeds gpio array\n",
+ __func__);
+ return -EFAULT;
+ }
val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
if (!val_array) {
@@ -746,7 +759,12 @@
goto ERROR2;
}
for (i = 0; i < count; i++) {
- gconf->cam_gpio_common_tbl[i].gpio = val_array[i];
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio common tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ gconf->cam_gpio_common_tbl[i].gpio = gpio_array[val_array[i]];
CDBG("%s cam_gpio_common_tbl[%d].gpio = %d\n", __func__, i,
gconf->cam_gpio_common_tbl[i].gpio);
}
@@ -787,7 +805,8 @@
}
static int32_t msm_sensor_init_gpio_req_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size)
{
int32_t rc = 0, i = 0;
uint32_t count = 0;
@@ -797,9 +816,10 @@
return 0;
count /= sizeof(uint32_t);
-
- if (!count)
+ if (!count) {
+ pr_err("%s gpio_req_tbl_num 0\n", __func__);
return 0;
+ }
val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
if (!val_array) {
@@ -823,7 +843,12 @@
goto ERROR2;
}
for (i = 0; i < count; i++) {
- gconf->cam_gpio_req_tbl[i].gpio = val_array[i];
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio req tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
CDBG("%s cam_gpio_req_tbl[%d].gpio = %d\n", __func__, i,
gconf->cam_gpio_req_tbl[i].gpio);
}
@@ -864,7 +889,8 @@
}
static int32_t msm_sensor_init_gpio_set_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size)
{
int32_t rc = 0, i = 0;
uint32_t count = 0;
@@ -874,9 +900,10 @@
return 0;
count /= sizeof(uint32_t);
-
- if (!count)
+ if (!count) {
+ pr_err("%s gpio_set_tbl_num 0\n", __func__);
return 0;
+ }
val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
if (!val_array) {
@@ -900,7 +927,12 @@
goto ERROR2;
}
for (i = 0; i < count; i++) {
- gconf->cam_gpio_set_tbl[i].gpio = val_array[i];
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio set tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ gconf->cam_gpio_set_tbl[i].gpio = gpio_array[val_array[i]];
CDBG("%s cam_gpio_set_tbl[%d].gpio = %d\n", __func__, i,
gconf->cam_gpio_set_tbl[i].gpio);
}
@@ -941,7 +973,8 @@
}
static int32_t msm_sensor_init_gpio_tlmm_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size)
{
int32_t rc = 0, i = 0;
uint32_t count = 0;
@@ -992,7 +1025,12 @@
goto ERROR4;
}
for (i = 0; i < count; i++) {
- tlmm_cfg[i].gpio = val_array[i];
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio set tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ tlmm_cfg[i].gpio = gpio_array[val_array[i]];
CDBG("%s tlmm_cfg[%d].gpio = %d\n", __func__, i,
tlmm_cfg[i].gpio);
}
@@ -1184,12 +1222,14 @@
static int32_t msm_sensor_init_sensor_data(struct platform_device *pdev,
struct msm_sensor_ctrl_t *s_ctrl)
{
- int32_t rc = 0;
+ int32_t rc = 0, i = 0;
uint32_t val = 0;
struct device_node *of_node = pdev->dev.of_node;
struct msm_camera_sensor_platform_info *pinfo = NULL;
struct msm_camera_gpio_conf *gconf = NULL;
struct msm_camera_sensor_info *sensordata = NULL;
+ uint16_t *gpio_array = NULL;
+ uint16_t gpio_array_size = 0;
s_ctrl->sensordata = kzalloc(sizeof(struct msm_camera_sensor_info),
GFP_KERNEL);
@@ -1199,6 +1239,7 @@
}
sensordata = s_ctrl->sensordata;
+
rc = of_property_read_string(of_node, "sensor_name",
&sensordata->sensor_name);
CDBG("%s sensor_name %s, rc %d\n", __func__,
@@ -1276,36 +1317,57 @@
goto ERROR5;
}
- rc = msm_sensor_init_gpio_common_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR5;
- }
+ gpio_array_size = of_gpio_count(of_node);
+ CDBG("%s gpio count %d\n", __func__, gpio_array_size);
- rc = msm_sensor_init_gpio_req_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR6;
- }
+ if (gpio_array_size) {
+ gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
+ GFP_KERNEL);
+ if (!gpio_array) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR5;
+ }
+ for (i = 0; i < gpio_array_size; i++) {
+ gpio_array[i] = of_get_gpio(of_node, i);
+ CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+ gpio_array[i]);
+ }
- rc = msm_sensor_init_gpio_set_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR7;
- }
+ rc = msm_sensor_init_gpio_common_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR5;
+ }
- rc = msm_sensor_init_gpio_tlmm_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR8;
- }
+ rc = msm_sensor_init_gpio_req_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR6;
+ }
+ rc = msm_sensor_init_gpio_set_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR7;
+ }
+
+ rc = msm_sensor_init_gpio_tlmm_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR8;
+ }
+ }
rc = msm_sensor_init_actuator_data(of_node, sensordata);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR9;
}
+ kfree(gpio_array);
return rc;
ERROR9:
@@ -1334,6 +1396,7 @@
kfree(s_ctrl->sensordata->flash_data);
ERROR1:
kfree(s_ctrl->sensordata);
+ kfree(gpio_array);
return rc;
}
@@ -1365,7 +1428,11 @@
{
int32_t rc = 0;
struct msm_camera_sensor_info *data = s_ctrl->sensordata;
- CDBG("%s: %d\n", __func__, __LINE__);
+ struct device *dev = NULL;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE)
+ dev = &s_ctrl->pdev->dev;
+ else
+ dev = &s_ctrl->sensor_i2c_client->client->dev;
s_ctrl->reg_ptr = kzalloc(sizeof(struct regulator *)
* data->sensor_platform_info->num_vreg, GFP_KERNEL);
if (!s_ctrl->reg_ptr) {
@@ -1380,23 +1447,23 @@
goto request_gpio_failed;
}
- rc = msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
- s_ctrl->sensordata->sensor_platform_info->cam_vreg,
- s_ctrl->sensordata->sensor_platform_info->num_vreg,
- s_ctrl->vreg_seq,
- s_ctrl->num_vreg_seq,
- s_ctrl->reg_ptr, 1);
+ rc = msm_camera_config_vreg(dev,
+ s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 1);
if (rc < 0) {
pr_err("%s: regulator on failed\n", __func__);
goto config_vreg_failed;
}
- rc = msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
- s_ctrl->sensordata->sensor_platform_info->cam_vreg,
- s_ctrl->sensordata->sensor_platform_info->num_vreg,
- s_ctrl->vreg_seq,
- s_ctrl->num_vreg_seq,
- s_ctrl->reg_ptr, 1);
+ rc = msm_camera_enable_vreg(dev,
+ s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 1);
if (rc < 0) {
pr_err("%s: enable regulator failed\n", __func__);
goto enable_vreg_failed;
@@ -1408,14 +1475,23 @@
goto config_gpio_failed;
}
- if (s_ctrl->clk_rate != 0)
- cam_clk_info->clk_rate = s_ctrl->clk_rate;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_I2C_DEVICE) {
+ if (s_ctrl->clk_rate != 0)
+ cam_8960_clk_info->clk_rate = s_ctrl->clk_rate;
- rc = msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
- cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 1);
- if (rc < 0) {
- pr_err("%s: clk enable failed\n", __func__);
- goto enable_clk_failed;
+ rc = msm_cam_clk_enable(dev, cam_8960_clk_info,
+ s_ctrl->cam_clk, ARRAY_SIZE(cam_8960_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: clk enable failed\n", __func__);
+ goto enable_clk_failed;
+ }
+ } else {
+ rc = msm_cam_clk_enable(dev, cam_8974_clk_info,
+ s_ctrl->cam_clk, ARRAY_SIZE(cam_8974_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: clk enable failed\n", __func__);
+ goto enable_clk_failed;
+ }
}
if (!s_ctrl->power_seq_delay)
@@ -1433,7 +1509,7 @@
data->sensor_platform_info->i2c_conf->use_i2c_mux)
msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
- if (s_ctrl->sensor_i2c_client->cci_client) {
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
rc = msm_sensor_cci_util(s_ctrl->sensor_i2c_client,
MSM_CCI_INIT);
if (rc < 0) {
@@ -1452,7 +1528,7 @@
enable_clk_failed:
msm_camera_config_gpio_table(data, 0);
config_gpio_failed:
- msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_enable_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
s_ctrl->vreg_seq,
@@ -1460,7 +1536,7 @@
s_ctrl->reg_ptr, 0);
enable_vreg_failed:
- msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_config_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
s_ctrl->vreg_seq,
@@ -1476,8 +1552,12 @@
int32_t msm_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
{
struct msm_camera_sensor_info *data = s_ctrl->sensordata;
- CDBG("%s\n", __func__);
- if (s_ctrl->sensor_i2c_client->cci_client) {
+ struct device *dev = NULL;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE)
+ dev = &s_ctrl->pdev->dev;
+ else
+ dev = &s_ctrl->sensor_i2c_client->client->dev;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
msm_sensor_cci_util(s_ctrl->sensor_i2c_client,
MSM_CCI_RELEASE);
}
@@ -1489,16 +1569,20 @@
if (data->sensor_platform_info->ext_power_ctrl != NULL)
data->sensor_platform_info->ext_power_ctrl(0);
- msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
- cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 0);
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_I2C_DEVICE)
+ msm_cam_clk_enable(dev, cam_8960_clk_info, s_ctrl->cam_clk,
+ ARRAY_SIZE(cam_8960_clk_info), 0);
+ else
+ msm_cam_clk_enable(dev, cam_8974_clk_info, s_ctrl->cam_clk,
+ ARRAY_SIZE(cam_8974_clk_info), 0);
msm_camera_config_gpio_table(data, 0);
- msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_enable_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
s_ctrl->vreg_seq,
s_ctrl->num_vreg_seq,
s_ctrl->reg_ptr, 0);
- msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_config_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
s_ctrl->vreg_seq,
@@ -1547,6 +1631,7 @@
}
s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+ s_ctrl->sensor_device_type = MSM_SENSOR_I2C_DEVICE;
if (s_ctrl->sensor_i2c_client != NULL) {
s_ctrl->sensor_i2c_client->client = client;
if (s_ctrl->sensor_i2c_addr != 0)
@@ -1632,6 +1717,7 @@
return rc;
}
}
+ s_ctrl->sensor_device_type = MSM_SENSOR_PLATFORM_DEVICE;
s_ctrl->sensor_i2c_client->cci_client = kzalloc(sizeof(
struct msm_camera_cci_client), GFP_KERNEL);
if (!s_ctrl->sensor_i2c_client->cci_client) {
@@ -1657,7 +1743,7 @@
s_ctrl->sensor_i2c_client->cci_client->cci_i2c_master = MASTER_0;
s_ctrl->sensor_i2c_client->cci_client->sid =
s_ctrl->sensor_i2c_addr >> 1;
- s_ctrl->sensor_i2c_client->cci_client->retries = 0;
+ s_ctrl->sensor_i2c_client->cci_client->retries = 3;
s_ctrl->sensor_i2c_client->cci_client->id_map = 0;
rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 8e66251..7dd0602 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -24,6 +24,7 @@
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <mach/camera.h>
#include <media/msm_camera.h>
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.c b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
index 4c380c7..c867867 100644
--- a/drivers/media/video/msm/sensors/msm_sensor_bayer.c
+++ b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
@@ -324,7 +324,7 @@
break;
}
rc = msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
- clk_info, &s_ctrl->cam_clk,
+ clk_info, s_ctrl->cam_clk,
clk_setting.num_clk_info,
clk_setting.enable);
kfree(clk_info);
@@ -470,7 +470,7 @@
rc = msm_cam_clk_enable(
&s_ctrl->sensor_i2c_client->client->dev,
- cam_clk_info, &s_ctrl->cam_clk,
+ cam_clk_info, s_ctrl->cam_clk,
ARRAY_SIZE(cam_clk_info), 1);
if (rc < 0) {
pr_err("%s: clk enable failed\n", __func__);
@@ -523,7 +523,7 @@
break;
case CONFIG_CLK:
msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->
- dev, cam_clk_info, &s_ctrl->cam_clk,
+ dev, cam_clk_info, s_ctrl->cam_clk,
ARRAY_SIZE(cam_clk_info), 0);
break;
case ENABLE_GPIO:
@@ -594,7 +594,7 @@
break;
case CONFIG_CLK:
msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->
- dev, cam_clk_info, &s_ctrl->cam_clk,
+ dev, cam_clk_info, s_ctrl->cam_clk,
ARRAY_SIZE(cam_clk_info), 0);
break;
case ENABLE_GPIO:
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.h b/drivers/media/video/msm/sensors/msm_sensor_common.h
index 3b135e1..79fe52e 100644
--- a/drivers/media/video/msm/sensors/msm_sensor_common.h
+++ b/drivers/media/video/msm/sensors/msm_sensor_common.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <mach/camera.h>
#include <media/msm_camera.h>
#include <media/v4l2-subdev.h>
@@ -101,6 +102,11 @@
uint8_t num_conf;
};
+enum msm_sensor_device_type_t {
+ MSM_SENSOR_I2C_DEVICE,
+ MSM_SENSOR_PLATFORM_DEVICE,
+};
+
struct v4l2_subdev_info {
enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
@@ -177,6 +183,7 @@
int num_vreg_seq;
struct msm_camera_power_seq_t *power_seq;
int num_power_seq;
+ enum msm_sensor_device_type_t sensor_device_type;
struct msm_sensor_output_reg_addr_t *sensor_output_reg_addr;
struct msm_sensor_id_info_t *sensor_id_info;
@@ -201,7 +208,7 @@
struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
struct msm_sensor_fn_t *func_tbl;
struct regulator **reg_ptr;
- struct clk *cam_clk;
+ struct clk *cam_clk[2];
long clk_rate;
enum msm_sensor_state sensor_state;
/* Number of frames to delay after start / stop stream in Q10 format.
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index 16fb14d..b7b12cb 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -36,7 +36,7 @@
pr_debug("\n In %s domain: %d, Partition: %d\n",
__func__, domain_num, partition_num);
rc = ion_map_iommu(clnt, hndl, domain_num, partition_num, align,
- 0, iova, buffer_size, flags, 0);
+ 0, iova, buffer_size, UNCACHED, 0);
if (rc)
pr_err("ion_map_iommu failed(%d).domain: %d,partition: %d\n",
rc, domain_num, partition_num);
@@ -217,21 +217,11 @@
static int ion_mem_clean_invalidate(struct smem_client *clt,
struct msm_smem *mem)
{
- unsigned long ionflag;
- int rc;
- rc = ion_handle_get_flags(clt->clnt, mem->smem_priv, &ionflag);
- if (rc) {
- pr_err("Failed to get ion flags: %p, %p\n",
- clt, mem->smem_priv);
- goto fail_get_flags;
- }
- if (ionflag == CACHED) {
- pr_err("Flushing the caches\n");
- rc = msm_ion_do_cache_op(clt->clnt, mem->smem_priv, mem->kvaddr,
- mem->size, ION_IOC_CLEAN_INV_CACHES);
- }
-fail_get_flags:
- return rc;
+ /*
+ * Note: We're always mapping into iommu as uncached
+ * as a result we don't need to flush/clean anything
+ */
+ return 0;
}
int msm_smem_clean_invalidate(void *clt, struct msm_smem *mem)
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 7f83625..cae486f 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -156,11 +156,23 @@
static u32 get_frame_size_nv12(int plane,
u32 height, u32 width)
{
- int luma_stride = ALIGN(width, 32);
- int luma_slice = ALIGN(height, 32);
- int chroma_stride = ALIGN(roundup(width, 2)/2, 32);
- int chroma_slice = ALIGN(roundup(height, 2)/2, 32);
- return (luma_stride * luma_slice) + (chroma_stride * chroma_slice) * 2;
+ int size;
+ int luma_h, luma_w, luma_stride, luma_scanl, luma_size;
+ int chroma_h, chroma_w, chroma_stride, chroma_scanl, chroma_size;
+
+ luma_w = width;
+ luma_h = height;
+
+ chroma_w = luma_w;
+ chroma_h = luma_h/2;
+ NV12_IL_CALC_Y_STRIDE(luma_stride, luma_w, 32);
+ NV12_IL_CALC_Y_BUFHEIGHT(luma_scanl, luma_h, 32);
+ NV12_IL_CALC_UV_STRIDE(chroma_stride, chroma_w, 32);
+ NV12_IL_CALC_UV_BUFHEIGHT(chroma_scanl, luma_h, 32);
+ NV12_IL_CALC_BUF_SIZE(size, luma_size, luma_stride,
+ luma_scanl, chroma_size, chroma_stride, chroma_scanl, 32);
+ size = ALIGN(size, SZ_4K);
+ return size;
}
static u32 get_frame_size_nv21(int plane,
u32 height, u32 width)
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 50303d6..74f1415 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -449,7 +449,23 @@
static u32 get_frame_size_nv12(int plane, u32 height, u32 width)
{
- return ((height + 31) & (~31)) * ((width + 31) & (~31)) * 3/2;
+ int size;
+ int luma_h, luma_w, luma_stride, luma_scanl, luma_size;
+ int chroma_h, chroma_w, chroma_stride, chroma_scanl, chroma_size;
+
+ luma_w = width;
+ luma_h = height;
+
+ chroma_w = luma_w;
+ chroma_h = luma_h/2;
+ NV12_IL_CALC_Y_STRIDE(luma_stride, luma_w, 32);
+ NV12_IL_CALC_Y_BUFHEIGHT(luma_scanl, luma_h, 32);
+ NV12_IL_CALC_UV_STRIDE(chroma_stride, chroma_w, 32);
+ NV12_IL_CALC_UV_BUFHEIGHT(chroma_scanl, luma_h, 32);
+ NV12_IL_CALC_BUF_SIZE(size, luma_size, luma_stride,
+ luma_scanl, chroma_size, chroma_stride, chroma_scanl, 32);
+ size = ALIGN(size, SZ_4K);
+ return size;
}
static u32 get_frame_size_nv21(int plane, u32 height, u32 width)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 630f383..d01b1d1 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -47,6 +47,32 @@
#define SESSION_MSG_INDEX(__msg) (__msg - SESSION_MSG_START)
#define MAX_NAME_LENGTH 64
+
+#define NV12_IL_CALC_Y_STRIDE(stride, frame_width, stride_multiple) \
+ { stride = (frame_width + stride_multiple - 1) & \
+ (0xffffffff - (stride_multiple - 1)); }
+
+#define NV12_IL_CALC_Y_BUFHEIGHT(buf_height, frame_height,\
+ min_buf_height_multiple) \
+ { buf_height = (frame_height + min_buf_height_multiple - 1) & \
+ (0xffffffff - (min_buf_height_multiple - 1)); }
+
+#define NV12_IL_CALC_UV_STRIDE(stride, frame_width, stride_multiple) \
+ { stride = ((((frame_width + 1) >> 1) + stride_multiple - 1) & \
+ (0xffffffff - (stride_multiple - 1))) << 1; }
+
+#define NV12_IL_CALC_UV_BUFHEIGHT(buf_height, frame_height,\
+ min_buf_height_multiple) \
+ { buf_height = ((((frame_height + 1) >> 1) + \
+ min_buf_height_multiple - 1) & (0xffffffff - \
+ (min_buf_height_multiple - 1))); }
+
+#define NV12_IL_CALC_BUF_SIZE(buf_size, y_buf_size, y_stride, \
+ y_buf_height, uv_buf_size, uv_stride, uv_buf_height, uv_alignment) \
+ { y_buf_size = (y_stride * y_buf_height); \
+ uv_buf_size = (uv_stride * uv_buf_height) + uv_alignment; \
+ buf_size = y_buf_size + uv_buf_size; }
+
enum vidc_ports {
OUTPUT_PORT,
CAPTURE_PORT,
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 05707fd..b56f081 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -338,18 +338,26 @@
WCD9XXX_A_CHIP_VERSION) & 0x1F;
pr_info("%s : Codec version %u initialized\n",
__func__, wcd9xxx->version);
+ pr_info("idbyte_0[%08x] idbyte_1[%08x] idbyte_2[%08x] idbyte_3[%08x]\n",
+ wcd9xxx->idbyte_0, wcd9xxx->idbyte_1,
+ wcd9xxx->idbyte_2, wcd9xxx->idbyte_3);
- if (wcd9xxx->idbyte_0 == 0x2) {
+ if (wcd9xxx->idbyte_0 == 0x2 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
wcd9xxx_dev = tabla_devs;
wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
- } else if (wcd9xxx->idbyte_0 == 0x1) {
+ } else if (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
wcd9xxx_dev = tabla1x_devs;
wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
} else if (wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
wcd9xxx->idbyte_2 == 0x2 && wcd9xxx->idbyte_3 == 0x1) {
wcd9xxx_dev = taiko_devs;
wcd9xxx_dev_size = ARRAY_SIZE(taiko_devs);
- } else if (wcd9xxx->idbyte_0 == 0x0) {
+ } else if ((wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) ||
+ (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x1 && wcd9xxx->idbyte_3 == 0x1)) {
wcd9xxx_dev = sitar_devs;
wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 69d71d9..84f148f 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -230,7 +230,6 @@
[DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
u32 num_output_frames;
u32 out_frm_next_frmindex;
- u32 first_output_frame_tag;
};
struct ddl_mp2_datadumpenabletype {
u32 userdatadump_enable;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index b047505..c3d20cf 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -1801,27 +1801,11 @@
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
&output_frame->ip_frm_tag, &bottom_frame_tag);
-
- if (start_bfr_idx == 0) {
- encoder->batch_frame.first_output_frame_tag =
- output_frame->ip_frm_tag;
- DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
- __func__, output_frame->ip_frm_tag);
- if (!output_frame->ip_frm_tag) {
- DDL_MSG_ERROR("%s: first_output_frame_tag "\
- "is zero", __func__);
- }
+ if (!output_frame->ip_frm_tag) {
+ DDL_MSG_ERROR("%s: zero frame tag rcvd, index = %d",
+ __func__, index);
+ output_frame->ip_frm_tag = (u32)ddl->client_data;
}
- if (output_frame->ip_frm_tag !=
- encoder->batch_frame.first_output_frame_tag) {
- DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
- "not equal to the first_output_frame_tag[0x%x]\n",
- __func__, output_frame->ip_frm_tag,
- encoder->batch_frame.first_output_frame_tag);
- output_frame->ip_frm_tag =
- encoder->batch_frame.first_output_frame_tag;
- }
-
ddl_get_encoded_frame(output_frame,
encoder->codec.codec,
encoder->enc_frame_info.enc_frame);
@@ -1904,27 +1888,11 @@
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
&output_frame->ip_frm_tag, &bottom_frame_tag);
-
- if (start_bfr_idx == 0) {
- encoder->batch_frame.first_output_frame_tag =
- output_frame->ip_frm_tag;
- DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
- __func__, output_frame->ip_frm_tag);
- if (!output_frame->ip_frm_tag) {
- DDL_MSG_ERROR("%s: first_output_frame_tag "\
- "is zero", __func__);
- }
+ if (!output_frame->ip_frm_tag) {
+ DDL_MSG_ERROR("%s: zero frame tag rcvd, index = %d",
+ __func__, index);
+ output_frame->ip_frm_tag = (u32)ddl->client_data;
}
- if (output_frame->ip_frm_tag !=
- encoder->batch_frame.first_output_frame_tag) {
- DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
- "not equal to the first_output_frame_tag[0x%x]\n",
- __func__, output_frame->ip_frm_tag,
- encoder->batch_frame.first_output_frame_tag);
- output_frame->ip_frm_tag =
- encoder->batch_frame.first_output_frame_tag;
- }
-
ddl_get_encoded_frame(output_frame,
encoder->codec.codec,
encoder->enc_frame_info.enc_frame);
@@ -1995,8 +1963,9 @@
&output_frame->ip_frm_tag,
&bottom_frame_tag);
if (!output_frame->ip_frm_tag) {
- DDL_MSG_ERROR("%s: output frame tag is zero",
- __func__);
+ DDL_MSG_ERROR("%s: zero frame tag rcvd, index = %d",
+ __func__, index);
+ output_frame->ip_frm_tag = (u32)ddl->client_data;
}
ddl_get_encoded_frame(
output_frame,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index d1f6e07..4072b02 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -867,7 +867,6 @@
DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
sizeof(struct vidc_1080p_enc_slice_batch_in_param));
encoder->batch_frame.out_frm_next_frmindex = 0;
- encoder->batch_frame.first_output_frame_tag = 0;
bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
encoder->output_buf_req.sz = bitstream_size;
y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
diff --git a/include/linux/msm_audio.h b/include/linux/msm_audio.h
index f2a39e4..4eb8a65 100644
--- a/include/linux/msm_audio.h
+++ b/include/linux/msm_audio.h
@@ -222,6 +222,28 @@
#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *)
+enum cad_device_path_type {
+ CAD_DEVICE_PATH_RX, /*For Decoding session*/
+ CAD_DEVICE_PATH_TX, /* For Encoding session*/
+ CAD_DEVICE_PATH_RX_TX, /* For Voice call */
+ CAD_DEVICE_PATH_LB, /* For loopback (FM Analog)*/
+ CAD_DEVICE_PATH_MAX
+};
+
+struct cad_devices_type {
+ uint32_t rx_device;
+ uint32_t tx_device;
+ enum cad_device_path_type pathtype;
+};
+
+struct msm_cad_device_config {
+ struct cad_devices_type device;
+ uint32_t ear_mute;
+ uint32_t mic_mute;
+};
+
+#define CAD_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_cad_device_config *)
+
#define SND_METHOD_VOICE 0
struct msm_snd_volume_config {
@@ -232,6 +254,14 @@
#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *)
+struct msm_cad_volume_config {
+ struct cad_devices_type device;
+ uint32_t method;
+ uint32_t volume;
+};
+
+#define CAD_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_cad_volume_config *)
+
/* Returns the number of SND endpoints supported. */
#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
@@ -254,6 +284,24 @@
#define SND_AVC_CTL _IOW(SND_IOCTL_MAGIC, 6, unsigned *)
#define SND_AGC_CTL _IOW(SND_IOCTL_MAGIC, 7, unsigned *)
+/*return the number of CAD endpoints supported. */
+
+#define CAD_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
+
+struct msm_cad_endpoint {
+ int id; /* input and output */
+ char name[64]; /* output only */
+};
+
+/* Takes an index between 0 and one less than the number returned by
+ * SND_GET_NUM_ENDPOINTS, and returns the CAD index and name of a
+ * CAD endpoint. On input, the .id field contains the number of the
+ * endpoint, and on exit it contains the SND index, while .name contains
+ * the description of the endpoint.
+ */
+
+#define CAD_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_cad_endpoint *)
+
struct msm_audio_pcm_config {
uint32_t pcm_feedback; /* 0 - disable > 0 - enable */
uint32_t buffer_count; /* Number of buffers to allocate */
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 80334c4..bd97b86 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1339,7 +1339,7 @@
};
struct csi_lane_params_t {
- uint8_t csi_lane_assign;
+ uint16_t csi_lane_assign;
uint8_t csi_lane_mask;
uint8_t csi_if;
uint8_t csid_core[2];
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 32565bc..67572c3 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -2414,7 +2414,7 @@
snd_soc_write(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x50);
if (SITAR_IS_1P0(sitar_core->version))
snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1,
- 0xFF, 0x65);
+ 0xF3, 0x61);
usleep_range(1000, 1000);
} else {
pr_err("%s: Error, Invalid bandgap settings\n", __func__);
diff --git a/sound/soc/msm/msm-pcm.h b/sound/soc/msm/msm-pcm.h
index 6e1325b..867116a 100644
--- a/sound/soc/msm/msm-pcm.h
+++ b/sound/soc/msm/msm-pcm.h
@@ -27,7 +27,7 @@
#include <mach/qdsp5/qdsp5audrecmsg.h>
#include <mach/qdsp5/qdsp5audpreproccmdi.h>
#include <mach/qdsp5/qdsp5audpreprocmsg.h>
-
+#include <mach/qdsp5/qdsp5audpp.h>
#include <../arch/arm/mach-msm/qdsp5/adsp.h>
#include <../arch/arm/mach-msm/qdsp5/audmgr.h>