Merge "msm: camera: VFE 4.0 bring up changes" into msm-3.4
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index a2b7dfc..bff3732 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -3,6 +3,8 @@
Required properties :
- compatible : should be "qcom,dwc-usb3-msm"
- reg : offset and length of the register set in the memory map
+ offset and length of the TCSR register for routing USB
+ signals to either picoPHY0 or picoPHY1.
- interrupts: IRQ lines used by this controller
- interrupt-names : Required interrupt resource entries are:
"irq" : Interrupt for DWC3 core
@@ -18,7 +20,8 @@
Example MSM USB3.0 controller device node :
usb@f9200000 {
compatible = "qcom,dwc-usb3-msm";
- reg = <0xF9200000 0xFA000>;
+ reg = <0xF9200000 0xFA000>,
+ <0xFD4AB000 0x4>;
interrupts = <0 131 0 0 179 0>;
interrupt-names = "irq", "otg_irq";
SSUSB_VDDCX-supply = <&pm8841_s2>;
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
new file mode 100644
index 0000000..1f7e488
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -0,0 +1,119 @@
+/* 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.
+ */
+
+&mdss_dsi {
+
+ qcom,mdss_dsi_toshiba_720p_video {
+ compatible = "qcom,mdss-dsi-panel";
+ label = "toshiba 720p video mode dsi panel";
+ status = "disable";
+ qcom,enable-gpio = <&msmgpio 58 0>;
+ qcom,rst-gpio = <&pm8941_gpios 19 0>;
+ qcom,mdss-pan-res = <720 1280>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-porch-values = <32 12 144 3 4 9>;
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+ qcom,mdss-pan-bl-levels = <1 255>;
+ qcom,mdss-pan-dsi-mode = <0>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+ qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <1>;
+ qcom,mdss-pan-dsi-dst-format = <3>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <0>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>;
+ qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-frame-rate = <60>;
+ qcom,panel-phy-regulatorSettings = [03 01 01 00 /* Regualotor settings */
+ 20 00 01 00];
+ qcom,panel-phy-timingSettings = [69 29 1f 00 55 55
+ 19 2a 2a 03 04 00];
+ qcom,panel-phy-strengthCtrl = [77 06];
+ qcom,panel-phy-bistCtrl = [00 00 01 ff /* BIST Ctrl settings */
+ 00 00];
+ qcom,panel-phy-laneConfig = [05 c2 00 00 00 00 00 01 75 /* lane0 config */
+ 05 c2 00 00 00 00 00 01 75 /* lane1 config */
+ 05 c2 00 00 00 00 00 01 75 /* lane2 config */
+ 05 c2 00 00 00 00 00 01 75 /* lane3 config */
+ 00 c2 00 00 00 00 00 01 97]; /* Clk ln config */
+
+ qcom,panel-on-cmds = [23 01 00 00 0a 02 b0 00
+ 23 01 00 00 0a 02 b2 00
+ 23 01 00 00 0a 02 b3 0c
+ 23 01 00 00 0a 02 b4 02
+ 29 01 00 00 00 06
+ c0 40 02 7f c8 08
+ 29 01 00 00 00 10
+ c1 00 a8 00 00 00
+ 00 00 9d 08 27 00
+ 00 00 00 00
+ 29 01 00 00 00 06
+ c2 00 00 09 00 00
+ 23 01 00 00 0a 02 c3 04
+ 29 01 00 00 00 04
+ c4 4d 83 00
+ 29 01 00 00 00 0b
+ c6 12 00 08 71 00
+ 00 00 80 00 04
+ 23 01 00 00 0a 02 c7 22
+ 29 01 00 00 00 05
+ c8 4c 0c 0c 0c
+ 29 01 00 00 00 0e
+ c9 00 40 00 16 32
+ 2e 3a 43 3e 3c 45
+ 79 3f
+ 29 01 00 00 00 0e
+ ca 00 46 1a 23 21
+ 1c 25 31 2d 49 5f
+ 7f 3f
+ 29 01 00 00 00 0e
+ cb 00 4c 20 3a 42
+ 40 47 4b 42 3e 46
+ 7e 3f
+ 29 01 00 00 00 0e
+ cc 00 41 19 21 1d
+ 14 18 1f 1d 25 3f
+ 73 3f
+ 29 01 00 00 00 0e
+ cd 23 79 5a 5f 57
+ 4c 51 51 45 3f 4b
+ 7f 3f
+ 29 01 00 00 00 0e
+ ce 00 40 14 20 1a
+ 0e 0e 13 08 00 05
+ 46 1c
+ 29 01 00 00 00 04
+ d0 6a 64 01
+ 29 01 00 00 00 03 d1 77 d4
+ 23 01 00 00 0a 02 d3 33
+ 29 01 00 00 00 03 d5 0f 0f
+ 29 01 00 00 00 07
+ d8 34 64 23 25 62
+ 32
+ 29 01 00 00 00 0c
+ de 10 7b 11 0a 00
+ 00 00 00 00 00 00
+ 29 01 00 00 00 09
+ fd 04 55 53 00 70
+ ff 10 73
+ 23 01 00 00 0a 02 e2 00
+ 05 01 00 00 78 02 11 00
+ 05 01 00 00 32 02 29 00];
+ qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+ 05 01 00 00 78 02 10 00];
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index 8ae9583..779b4f2 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8974.dtsi"
+/include/ "dsi-panel-toshiba-720p-video.dtsi"
/ {
model = "Qualcomm MSM 8974 CDP";
@@ -22,6 +23,12 @@
serial@f991e000 {
status = "ok";
};
+
+ qcom,mdss_dsi@fd922800 {
+ qcom,mdss_dsi_toshiba_720p_video {
+ status = "ok";
+ };
+ };
};
&sdcc2 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index de9173c7..dbaa492 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -22,8 +22,11 @@
mdss_dsi: qcom,mdss_dsi@fd922800 {
compatible = "qcom,msm-mdss-dsi";
- reg = <0xfd922800 0x5ac>,
+ reg = <0xfd922800 0x600>,
<0xfd8c2000 0x01000>;
+ vdd-supply = <&pm8941_l22>;
+ vdd_io-supply = <&pm8941_l12>;
+ vreg-supply = <&pm8941_l2>;
};
qcom,mdss_wb_panel {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 1be0af9..dd8e80d 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -551,7 +551,8 @@
qcom,ssusb@f9200000 {
compatible = "qcom,dwc-usb3-msm";
- reg = <0xf9200000 0xfc000>;
+ reg = <0xf9200000 0xfc000>,
+ <0xfd4ab000 0x4>;
interrupts = <0 131 0 0 179 0>;
interrupt-names = "irq", "otg_irq";
SSUSB_VDDCX-supply = <&pm8841_s2>;
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 408175d..1ac8f02 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -293,6 +293,7 @@
CONFIG_STM_LIS3DH=y
CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_MSM_IPC_LOGGING=y
CONFIG_N_SMUX=y
CONFIG_N_SMUX_LOOPBACK=y
CONFIG_SMUX_CTL=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 7a4bf08..8ac8f1a 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -297,6 +297,7 @@
CONFIG_STM_LIS3DH=y
CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_MSM_IPC_LOGGING=y
CONFIG_N_SMUX=y
CONFIG_N_SMUX_LOOPBACK=y
CONFIG_SMUX_CTL=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index db94f13..b8417fe 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -147,6 +147,10 @@
CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 1097907..3c42090 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -124,6 +124,10 @@
{ 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(9), 1237500 },
{ 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(9), 1237500 },
{ 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(9), 1250000 },
+ { 1, { 1566000, HFPLL, 1, 0, 0x3A }, L2(9), 1250000 },
+ { 1, { 1620000, HFPLL, 1, 0, 0x3C }, L2(9), 1250000 },
+ { 1, { 1674000, HFPLL, 1, 0, 0x3E }, L2(9), 1250000 },
+ { 1, { 1728000, HFPLL, 1, 0, 0x40 }, L2(9), 1250000 },
{ 0, { 0 } }
};
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 4263cd6..962d8d6 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2324,6 +2324,7 @@
static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi4_pdata = {
.clk_freq = 100000,
.src_clk_rate = 24000000,
+ .keep_ahb_clk_on = 1,
};
static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi3_pdata = {
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index cde6437..34901e8 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -6237,7 +6237,7 @@
rmwreg(0x00000003, AHB_EN_REG, 0x6C000103);
writel_relaxed(0x000007F9, AHB_EN2_REG);
} else {
- rmwreg(0x44000000, AHB_EN_REG, 0x6C000103);
+ rmwreg(0x40000000, AHB_EN_REG, 0x6C000103);
writel_relaxed(0x3C7097F9, AHB_EN2_REG);
}
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e21a645..71498d5 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -497,6 +497,7 @@
#define LPASS_Q6SS_XO_CBCR 0x26000
#define LPASS_Q6_AXI_CBCR 0x11C0
#define Q6SS_AHBM_CBCR 0x22004
+#define AUDIO_WRAPPER_BR_CBCR 0x24000
#define MSS_XO_Q6_CBCR 0x108C
#define MSS_BUS_Q6_CBCR 0x10A4
#define MSS_CFG_AHB_CBCR 0x0280
@@ -634,7 +635,8 @@
#define MMSSNOC_AHB_ID 0x3
#define BIMC_ID 0x0
-#define OCMEM_ID 0x1
+#define OXILI_ID 0x1
+#define OCMEM_ID 0x2
enum {
D0_ID = 1,
@@ -653,6 +655,8 @@
DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
DEFINE_CLK_RPM_SMD(ocmemgx_clk, ocmemgx_a_clk, RPM_MEM_CLK_TYPE, OCMEM_ID,
NULL);
+DEFINE_CLK_RPM_SMD(gfx3d_clk_src, gfx3d_a_clk_src, RPM_MEM_CLK_TYPE, OXILI_ID,
+ NULL);
DEFINE_CLK_RPM_SMD_BRANCH(cxo_clk_src, cxo_a_clk_src,
RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
@@ -773,7 +777,7 @@
static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(bimc_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(ocmemgx_gfx3d_clk, &ocmemgx_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(oxili_gfx3d_clk_src, &gfx3d_clk_src.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_core_clk, &ocmemgx_clk.c, LONG_MAX);
@@ -4012,7 +4016,7 @@
static struct branch_clk oxili_gfx3d_clk = {
.cbcr_reg = OXILI_GFX3D_CBCR,
- .parent = &ocmemgx_gfx3d_clk.c,
+ .parent = &oxili_gfx3d_clk_src.c,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "oxili_gfx3d_clk",
@@ -4494,6 +4498,17 @@
},
};
+static struct branch_clk audio_wrapper_br_clk = {
+ .cbcr_reg = AUDIO_WRAPPER_BR_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_wrapper_br_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_wrapper_br_clk.c),
+ },
+};
+
static struct branch_clk mss_xo_q6_clk = {
.cbcr_reg = MSS_XO_Q6_CBCR,
.bcr_reg = MSS_Q6SS_BCR,
@@ -4702,6 +4717,7 @@
{&q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
{&q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
{&audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
+ {&audio_wrapper_br_clk.c, LPASS_BASE, 0x0022},
{&mss_bus_q6_clk.c, MSS_BASE, 0x003b},
{&mss_xo_q6_clk.c, MSS_BASE, 0x0007},
@@ -5236,7 +5252,7 @@
"msm-dai-q6.4106"),
CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
"msm-dai-q6.4106"),
-
+ CLK_LOOKUP("br_clk", audio_wrapper_br_clk.c, "fdd00000.qcom,ocmem"),
CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "pil-q6v5-mss"),
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 0331919..27de697 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1592,6 +1592,47 @@
},
};
+enum {
+ MSM8625,
+ MSM8625A,
+ MSM8625AB,
+};
+
+static int __init msm8625_cpu_id(void)
+{
+ int raw_id, cpu;
+
+ raw_id = socinfo_get_raw_id();
+ switch (raw_id) {
+ /* Part number for 1GHz part */
+ case 0x770:
+ case 0x771:
+ case 0x77C:
+ case 0x780:
+ case 0x8D0:
+ cpu = MSM8625;
+ break;
+ /* Part number for 1.2GHz part */
+ case 0x773:
+ case 0x774:
+ case 0x781:
+ case 0x8D1:
+ cpu = MSM8625A;
+ break;
+ case 0x775:
+ case 0x776:
+ case 0x77D:
+ case 0x782:
+ case 0x8D2:
+ cpu = MSM8625AB;
+ break;
+ default:
+ pr_err("Invalid Raw ID\n");
+ return -ENODEV;
+ }
+ return cpu;
+}
+
static struct resource cpr_resources[] = {
{
.start = MSM8625_INT_CPR_IRQ0,
@@ -1608,12 +1649,12 @@
* These are various Vdd levels supported by PMIC
*/
static uint32_t msm_c2_pmic_mv[] __initdata = {
- 1300, 12875 / 10, 1275, 12625 / 10, 1250,
- 12375 / 10, 1225, 12125 / 10, 1200, 11875 / 10,
- 1175, 11625 / 10, 1150, 11375 / 10, 1125,
- 11125 / 10, 1100, 10875 / 10, 1075, 10625 / 10,
- 1050, 10375 / 10, 1025, 10125 / 10, 0, 0, 0, 0,
- 0, 0, 0, 1000,
+ 1300000, 1287500, 1275000, 1262500, 1250000,
+ 1237500, 1225000, 1212500, 1200000, 1187500,
+ 1175000, 1162500, 1150000, 1137500, 1125000,
+ 1112500, 1100000, 1087500, 1075000, 1062500,
+ 1050000, 1037500, 1025000, 1012500, 0, 0, 0,
+ 0, 0, 0, 0, 1000,
};
/**
@@ -1633,10 +1674,10 @@
},
.ring_osc = 0,
.step_quot = ~0,
- .tgt_volt_offset = 1,
- .Vmax = 1200,
- .Vmin = 1000,
- .calibrated_mV = 1100,
+ .tgt_volt_offset = 0,
+ .Vmax = 1200000,
+ .Vmin = 1000000,
+ .calibrated_uV = 1100000,
},
[TURBO_MODE] = {
.ring_osc_data = {
@@ -1651,23 +1692,47 @@
},
.ring_osc = 0,
.step_quot = ~0,
- .tgt_volt_offset = 1,
- .Vmax = 1350,
- .Vmin = 1250,
- .calibrated_mV = 1300,
+ .tgt_volt_offset = 0,
+ .Vmax = 1350000,
+ .Vmin = 1150000,
+ .calibrated_uV = 1300000,
},
};
struct msm_cpr_vp_data vp_data = {
- .min_volt = 1000,
- .max_volt = 1350,
- .default_volt = 1300,
- .step_size = (12500 / 1000),
+ .min_volt = 1000000,
+ .max_volt = 1350000,
+ .default_volt = 1300000,
+ .step_size = 12500,
};
+static uint32_t
+msm_cpr_get_quot(uint32_t max_quot, uint32_t max_freq, uint32_t new_freq)
+{
+ uint32_t quot;
+
+ /* This formula is as per chip characterization data */
+ quot = max_quot - ((max_freq / 10 - new_freq / 10) * 9) + 20;
+
+ return quot;
+}
+
+static void msm_cpr_clk_enable(void)
+{
+ uint32_t reg_val;
+
+ /* Select TCXO (19.2MHz) as clock source */
+ reg_val = readl_relaxed(A11S_TEST_BUS_SEL_ADDR);
+ reg_val |= RBCPR_CLK_MUX_SEL;
+ writel_relaxed(reg_val, A11S_TEST_BUS_SEL_ADDR);
+
+ /* Get CPR out of reset */
+ writel_relaxed(0x1, RBCPR_SW_RESET_N);
+}
+
static struct msm_cpr_config msm_cpr_pdata = {
.ref_clk_khz = 19200,
- .delay_us = 10000,
+ .delay_us = 25000,
.irq_line = 0,
.cpr_mode_data = msm_cpr_mode_data,
.tgt_count_div_N = 1,
@@ -1678,8 +1743,12 @@
.dn_threshold = 2,
.up_margin = 0,
.dn_margin = 0,
- .nom_freq_limit = 1008000,
+ .max_nom_freq = 700800,
+ .max_freq = 1401600,
+ .max_quot = 0,
.vp_data = &vp_data,
+ .get_quot = msm_cpr_get_quot,
+ .clk_enable = msm_cpr_clk_enable,
};
static struct platform_device msm8625_device_cpr = {
@@ -1701,7 +1770,6 @@
{
struct cpr_info_type *cpr_info = NULL;
uint8_t ring_osc = 0;
- uint32_t reg_val;
cpr_info = kzalloc(sizeof(struct cpr_info_type), GFP_KERNEL);
if (!cpr_info) {
@@ -1728,35 +1796,32 @@
msm_cpr_mode_data[TURBO_MODE].ring_osc_data[ring_osc].gcnt = 19;
msm_cpr_mode_data[NORMAL_MODE].ring_osc_data[ring_osc].gcnt = 19;
- /* The multiplier and offset are as per PTE data */
- msm_cpr_mode_data[TURBO_MODE].ring_osc_data[ring_osc].target_count =
- cpr_info->turbo_quot * 10 + 440;
- msm_cpr_mode_data[NORMAL_MODE].ring_osc_data[ring_osc].target_count =
- cpr_info->turbo_quot / msm_cpr_pdata.tgt_count_div_N;
+ /**
+ * The scaling factor and offset are as per chip characterization data
+ * This formula is used since available fuse bits in the chip are not
+ * enough to represent the value of maximum quot
+ */
+ msm_cpr_pdata.max_quot = cpr_info->turbo_quot * 10 + 610;
/**
* Bits 4:0 of pvs_fuse provide mapping to the safe boot up voltage.
* Boot up mode is by default Turbo.
*/
- msm_cpr_mode_data[TURBO_MODE].calibrated_mV =
+ msm_cpr_mode_data[TURBO_MODE].calibrated_uV =
msm_c2_pmic_mv[cpr_info->pvs_fuse & 0x1F];
- /* TODO: Store the tgt_volt_offset values for the modes from PTE */
-
-
pr_debug("%s: cpr: ring_osc: 0x%x\n", __func__,
msm_cpr_mode_data[TURBO_MODE].ring_osc);
pr_debug("%s: cpr: turbo_quot: 0x%x\n", __func__, cpr_info->turbo_quot);
pr_debug("%s: cpr: pvs_fuse: 0x%x\n", __func__, cpr_info->pvs_fuse);
kfree(cpr_info);
- /* Select TCXO (19.2MHz) as clock source */
- reg_val = readl_relaxed(A11S_TEST_BUS_SEL_ADDR);
- reg_val |= RBCPR_CLK_MUX_SEL;
- writel_relaxed(reg_val, A11S_TEST_BUS_SEL_ADDR);
+ if (msm8625_cpu_id() == MSM8625A)
+ msm_cpr_pdata.max_freq = 1209600;
+ else if (msm8625_cpu_id() == MSM8625)
+ msm_cpr_pdata.max_freq = 1008000;
- /* Get CPR out of reset */
- writel_relaxed(0x1, RBCPR_SW_RESET_N);
+ msm_cpr_clk_enable();
platform_device_register(&msm8625_vp_device);
platform_device_register(&msm8625_device_cpr);
@@ -1828,47 +1893,6 @@
.table = msm_clock_8625_dummy,
.size = ARRAY_SIZE(msm_clock_8625_dummy),
};
-enum {
- MSM8625,
- MSM8625A,
- MSM8625AB,
-};
-
-static int __init msm8625_cpu_id(void)
-{
- int raw_id, cpu;
-
- raw_id = socinfo_get_raw_id();
- switch (raw_id) {
- /* Part number for 1GHz part */
- case 0x770:
- case 0x771:
- case 0x77C:
- case 0x780:
- case 0x8D0:
- cpu = MSM8625;
- break;
- /* Part number for 1.2GHz part */
- case 0x773:
- case 0x774:
- case 0x779:
- case 0x781:
- case 0x8D1:
- cpu = MSM8625A;
- break;
- case 0x775:
- case 0x776:
- case 0x77D:
- case 0x782:
- case 0x8D2:
- cpu = MSM8625AB;
- break;
- default:
- pr_err("Invalid Raw ID\n");
- return -ENODEV;
- }
- return cpu;
-}
int __init msm7x2x_misc_init(void)
{
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index d8f8480..3311ea1 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -515,6 +515,7 @@
int aux_dat;
int src_clk_rate;
int use_gsbi_shared_mode;
+ int keep_ahb_clk_on;
void (*msm_i2c_config_gpio)(int iface, int config_type);
};
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index f4272f3..b6c05f4 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -36,6 +36,14 @@
#define MODULE_NAME "msm-cpr"
+/**
+ * Convert the Delay time to Timer Count Register
+ * e.g if frequency is 19200 kHz and delay required is
+ * 20000us, so timer count will be 19200 * 20000 / 1000
+ */
+#define TIMER_COUNT(freq, delay) ((freq * delay) / 1000)
+#define ALL_CPR_IRQ 0x3F
+
/* Need platform device handle for suspend and resume APIs */
static struct platform_device *cpr_pdev;
@@ -45,6 +53,7 @@
int prev_mode;
uint32_t floor;
uint32_t ceiling;
+ bool max_volt_set;
void __iomem *base;
unsigned int irq;
struct mutex cpr_mutex;
@@ -157,7 +166,7 @@
static void
cpr_2pt_kv_analysis(struct msm_cpr *cpr, struct msm_cpr_mode *chip_data)
{
- int32_t tgt_volt_mV = 0, level_uV, rc;
+ int32_t level_uV = 0, rc;
uint32_t quot1, quot2;
/**
@@ -180,15 +189,10 @@
* voltage, offset is always subtracted from it.
*
*/
- if (chip_data->tgt_volt_offset > 0) {
- tgt_volt_mV = chip_data->calibrated_mV -
- (chip_data->tgt_volt_offset * cpr->vp->step_size);
- }
- pr_debug("tgt_volt_mV = %d, calibrated_mV = %d", tgt_volt_mV,
- chip_data->calibrated_mV);
+ level_uV = chip_data->Vmax -
+ (chip_data->tgt_volt_offset * cpr->vp->step_size);
+ pr_debug("tgt_volt_uV = %d\n", level_uV);
- /* level_uV = tgt_volt_mV * 1000; */
- level_uV = 1350000;
/* Call the PMIC specific routine to set the voltage */
rc = regulator_set_voltage(cpr->vreg_cx, level_uV, level_uV);
if (rc) {
@@ -202,10 +206,7 @@
return;
}
- /* Store the adjusted value of voltage */
- chip_data->calibrated_mV = 1300;
-
- /* Take first CPR measurement at a higher voltage to get QUOT1 */
+ /* First CPR measurement at a higher voltage to get QUOT1 */
/* Enable the Software mode of operation */
cpr_modify_reg(cpr, RBCPR_CTL, HW_TO_PMIC_EN_M, SW_MODE);
@@ -231,7 +232,8 @@
quot1 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
/* Take second CPR measurement at a lower voltage to get QUOT2 */
- level_uV = 1300000;
+ level_uV -= 4 * cpr->vp->step_size;
+ pr_debug("tgt_volt_uV = %d\n", level_uV);
cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
/* Call the PMIC specific routine to set the voltage */
@@ -261,7 +263,7 @@
}
quot2 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
chip_data->step_quot = (quot1 - quot2) / 4;
- pr_debug("%s: Calculated Step Quot is %d\n",
+ pr_info("%s: Calculated Step Quot is %d\n",
__func__, chip_data->step_quot);
/* Disable the cpr */
cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
@@ -279,7 +281,7 @@
void cpr_irq_clr_and_ack(struct msm_cpr *cpr, uint32_t mask)
{
/* Clear the interrupt */
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
/* Acknowledge the Recommendation */
cpr_write_reg(cpr, RBIF_CONT_ACK_CMD, 0x1);
}
@@ -287,7 +289,7 @@
static inline
void cpr_irq_clr_and_nack(struct msm_cpr *cpr, uint32_t mask)
{
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
cpr_write_reg(cpr, RBIF_CONT_NACK_CMD, 0x1);
}
@@ -307,7 +309,7 @@
static void
cpr_up_event_handler(struct msm_cpr *cpr, uint32_t new_volt)
{
- int rc, set_volt_mV;
+ int rc, set_volt_uV;
struct msm_cpr_mode *chip_data;
chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
@@ -317,26 +319,28 @@
* freq switch handler and CPR interrupt handler here
*/
/* Set New PMIC voltage */
- set_volt_mV = (new_volt < chip_data->Vmax ? new_volt
+ set_volt_uV = (new_volt < chip_data->Vmax ? new_volt
: chip_data->Vmax);
- rc = regulator_set_voltage(cpr->vreg_cx, set_volt_mV * 1000,
- set_volt_mV * 1000);
+ rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
+ set_volt_uV);
if (rc) {
- pr_err("%s: Voltage set at %dmV failed. %d\n",
- __func__, set_volt_mV, rc);
+ pr_err("%s: Voltage set at %duV failed. %d\n",
+ __func__, set_volt_uV, rc);
cpr_irq_clr_and_nack(cpr, BIT(4) | BIT(0));
return;
}
- pr_debug("%s: Voltage set at %dmV\n", __func__, set_volt_mV);
+ pr_info("(railway_voltage: %d uV)\n", set_volt_uV);
+
+ cpr->max_volt_set = (set_volt_uV == chip_data->Vmax) ? 1 : 0;
/**
* Save the new calibrated voltage to be re-used
* whenever we return to same mode after a mode switch.
*/
- chip_data->calibrated_mV = set_volt_mV;
+ chip_data->calibrated_uV = set_volt_uV;
/* Clear all the interrupts */
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
/* Disable Auto ACK for Down interrupts */
cpr_modify_reg(cpr, RBCPR_CTL, SW_AUTO_CONT_NACK_DN_EN_M, 0);
@@ -353,7 +357,7 @@
static void
cpr_dn_event_handler(struct msm_cpr *cpr, uint32_t new_volt)
{
- int rc, set_volt_mV;
+ int rc, set_volt_uV;
struct msm_cpr_mode *chip_data;
chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
@@ -363,26 +367,28 @@
* freq switch handler and CPR interrupt handler here
*/
/* Set New PMIC volt */
- set_volt_mV = (new_volt > chip_data->Vmin ? new_volt
+ set_volt_uV = (new_volt > chip_data->Vmin ? new_volt
: chip_data->Vmin);
- rc = regulator_set_voltage(cpr->vreg_cx, set_volt_mV * 1000,
- set_volt_mV * 1000);
+ rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
+ set_volt_uV);
if (rc) {
- pr_err("%s: Voltage at %dmV failed %d\n",
- __func__, set_volt_mV, rc);
+ pr_err("%s: Voltage at %duV failed %d\n",
+ __func__, set_volt_uV, rc);
cpr_irq_clr_and_nack(cpr, BIT(2) | BIT(0));
return;
}
- pr_debug("%s: Voltage set at %dmV\n", __func__, set_volt_mV);
+ pr_info("(railway_voltage: %d uV)\n", set_volt_uV);
+
+ cpr->max_volt_set = 0;
/**
* Save the new calibrated voltage to be re-used
* whenever we return to same mode after a mode switch.
*/
- chip_data->calibrated_mV = set_volt_mV;
+ chip_data->calibrated_uV = set_volt_uV;
/* Clear all the interrupts */
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
if (new_volt <= chip_data->Vmin) {
/*
@@ -416,16 +422,22 @@
chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
error_step = cpr_read_reg(cpr, RBCPR_RESULT_0) >> 2;
error_step &= 0xF;
- curr_volt = chip_data->calibrated_mV;
+ curr_volt = chip_data->calibrated_uV;
if (action == UP) {
+ /* Clear IRQ, ACK and return if Vdd already at Vmax */
+ if (cpr->max_volt_set == 1) {
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+ cpr_write_reg(cpr, RBIF_CONT_NACK_CMD, 0x1);
+ return;
+ }
+
/**
* Using up margin in the comparison helps avoid having to
* change up threshold values in chip register.
*/
if (error_step < (cpr->config->up_threshold +
cpr->config->up_margin)) {
- /* FIXME: Avoid repeated dn interrupts if we are here */
pr_debug("UP_INT error step too small to set\n");
cpr_irq_clr_and_nack(cpr, BIT(4) | BIT(0));
return;
@@ -434,6 +446,7 @@
/* Calculte new PMIC voltage */
new_volt = curr_volt + (error_step * cpr->vp->step_size);
pr_debug("UP_INT: new_volt: %d\n", new_volt);
+ pr_info("(UP Voltage recommended by CPR: %d uV)\n", new_volt);
cpr_up_event_handler(cpr, new_volt);
} else if (action == DOWN) {
@@ -443,7 +456,6 @@
*/
if (error_step < (cpr->config->dn_threshold +
cpr->config->dn_margin)) {
- /* FIXME: Avoid repeated dn interrupts if we are here */
pr_debug("DOWN_INT error_step too small to set\n");
cpr_irq_clr_and_nack(cpr, BIT(2) | BIT(0));
return;
@@ -452,6 +464,7 @@
/* Calculte new PMIC voltage */
new_volt = curr_volt - (error_step * cpr->vp->step_size);
pr_debug("DOWN_INT: new_volt: %d\n", new_volt);
+ pr_info("(DN Voltage recommended by CPR: %d uV)\n", new_volt);
cpr_dn_event_handler(cpr, new_volt);
}
}
@@ -513,6 +526,8 @@
cpr->config->dn_threshold << 28);
cpr->curr_osc = chip_data->ring_osc;
+ chip_data->ring_osc_data[cpr->curr_osc].quot =
+ cpr->config->max_quot;
/**
* Program the gate count and target values
@@ -522,7 +537,7 @@
cpr_modify_reg(cpr, RBCPR_GCNT_TARGET(cnt),
(GCNT_M | TARGET_M),
(chip_data->ring_osc_data[cnt].gcnt << 12 |
- chip_data->ring_osc_data[cnt].target_count));
+ chip_data->ring_osc_data[cnt].quot));
pr_debug("RBCPR_GCNT_TARGET(%d): = 0x%x\n", cnt,
readl_relaxed(cpr->base + RBCPR_GCNT_TARGET(cnt)));
cnt++;
@@ -536,14 +551,19 @@
* Set with an extra step since it helps as per
* characterization data.
*/
- chip_data->calibrated_mV += cpr->vp->step_size;
- tmp_uV = chip_data->calibrated_mV * 1000;
+ chip_data->calibrated_uV += cpr->vp->step_size;
+ tmp_uV = chip_data->calibrated_uV;
rc = regulator_set_voltage(cpr->vreg_cx, tmp_uV, tmp_uV);
if (rc)
pr_err("%s: Voltage set failed %d\n", __func__, rc);
- /* Program the Timer for default delay between CPR measurements */
- delay_count = 0xFFFF;
+ /*
+ * Program the Timer Register for delay between CPR measurements
+ * This is required to allow the device sufficient time for idle
+ * power collapse.
+ */
+ delay_count = TIMER_COUNT(cpr->config->ref_clk_khz,
+ cpr->config->delay_us);
cpr_write_reg(cpr, RBCPR_TIMER_INTERVAL, delay_count);
/* Enable the Timer */
@@ -554,53 +574,69 @@
SW_AUTO_CONT_ACK_EN);
}
-static void cpr_mode_config(struct msm_cpr *cpr, enum cpr_mode mode)
-{
- if (cpr->cpr_mode == mode)
- return;
-
- cpr->cpr_mode = mode;
- pr_debug("%s: Switching to %s mode\n", __func__,
- (mode == TURBO_MODE ? "TURBO" : "NORMAL"));
-
- /* Configure the new mode */
- cpr_config(cpr);
-}
-
static int
cpr_freq_transition(struct notifier_block *nb, unsigned long val,
void *data)
{
struct msm_cpr *cpr = container_of(nb, struct msm_cpr, freq_transition);
struct cpufreq_freqs *freqs = data;
+ uint32_t quot, new_freq;
switch (val) {
case CPUFREQ_PRECHANGE:
- return 0;
pr_debug("pre freq change notification to cpr\n");
- disable_irq(cpr->irq);
+ /* Disable Measurement to stop generation of CPR IRQs */
cpr_disable(cpr);
+ /* Disable routing of IRQ to App */
+ cpr_irq_set(cpr, INT_MASK & ~MID_INT, 0);
+ disable_irq(cpr->irq);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+ pr_debug("RBCPR_CTL: 0x%x\n",
+ readl_relaxed(cpr->base + RBCPR_CTL));
+ pr_debug("RBIF_IRQ_STATUS: 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_STATUS));
+ pr_debug("RBIF_IRQ_EN(0): 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line)));
+
cpr->prev_mode = cpr->cpr_mode;
break;
- case CPUFREQ_POSTCHANGE:
- return 0;
- pr_debug("post freq change notification to cpr\n");
- if (freqs->new >= cpr->config->nom_freq_limit)
- cpr_mode_config(cpr, TURBO_MODE);
- else
- cpr_mode_config(cpr, NORMAL_MODE);
+ case CPUFREQ_POSTCHANGE:
+ pr_debug("post freq change notification to cpr\n");
+ /**
+ * As per chip characterization data, use max nominal freq
+ * to calculate quot for all lower frequencies too
+ */
+ new_freq = (freqs->new > cpr->config->max_nom_freq)
+ ? freqs->new
+ : cpr->config->max_nom_freq;
+
+ /* Configure CPR for the new frequency */
+ quot = cpr->config->get_quot(cpr->config->max_quot,
+ cpr->config->max_freq / 1000,
+ new_freq / 1000);
+ cpr_modify_reg(cpr, RBCPR_GCNT_TARGET(cpr->curr_osc), TARGET_M,
+ quot);
+ pr_debug("RBCPR_GCNT_TARGET(%d): = 0x%x\n", cpr->curr_osc,
+ readl_relaxed(cpr->base +
+ RBCPR_GCNT_TARGET(cpr->curr_osc)));
+ pr_debug("%s: new_freq: %d, set_freq: %d, quot: %d\n", __func__,
+ freqs->new, new_freq, quot);
+
+ enable_irq(cpr->irq);
/**
* Enable all interrupts. One of them could be in a disabled
* state if vdd had hit Vmax / Vmin earlier
*/
- cpr_irq_set(cpr, (UP_INT | DOWN_INT), 1);
-
- enable_irq(cpr->irq);
-
+ cpr_irq_set(cpr, INT_MASK & ~MID_INT, 1);
+ pr_debug("RBIF_IRQ_EN(0): 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line)));
+ pr_debug("RBCPR_CTL: 0x%x\n",
+ readl_relaxed(cpr->base + RBCPR_CTL));
+ pr_debug("RBIF_IRQ_STATUS: 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_STATUS));
cpr_enable(cpr);
-
break;
default:
break;
@@ -614,6 +650,8 @@
struct msm_cpr *cpr = dev_get_drvdata(dev);
int osc_num = cpr->config->cpr_mode_data->ring_osc;
+ cpr->config->clk_enable();
+
cpr_write_reg(cpr, RBCPR_TIMER_INTERVAL,
cpr_save_state.rbif_timer_interval);
cpr_write_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line),
@@ -628,11 +666,11 @@
cpr_save_state.rbcpr_step_quot);
cpr_write_reg(cpr, RBIF_SW_VLEVEL,
cpr_save_state.rbif_sw_level);
-
- cpr_enable(cpr);
cpr_write_reg(cpr, RBCPR_CTL,
cpr_save_state.rbcpr_ctl);
+
enable_irq(cpr->irq);
+ cpr_enable(cpr);
return 0;
}
@@ -643,6 +681,10 @@
struct msm_cpr *cpr = dev_get_drvdata(dev);
int osc_num = cpr->config->cpr_mode_data->ring_osc;
+ /* Disable CPR measurement before IRQ to avoid pending interrupts */
+ cpr_disable(cpr);
+ disable_irq(cpr->irq);
+
cpr_save_state.rbif_timer_interval =
cpr_read_reg(cpr, RBCPR_TIMER_INTERVAL);
cpr_save_state.rbif_int_en =
@@ -660,9 +702,6 @@
cpr_save_state.rbcpr_ctl =
cpr_read_reg(cpr, RBCPR_CTL);
- disable_irq(cpr->irq);
- cpr_disable(cpr);
-
return 0;
}
@@ -700,6 +739,7 @@
const struct msm_cpr_config *pdata = pdev->dev.platform_data;
void __iomem *base;
struct resource *mem;
+ struct msm_cpr_mode *chip_data;
if (!pdata) {
pr_err("CPR: Platform data is not available\n");
@@ -766,6 +806,16 @@
platform_set_drvdata(pdev, cpr);
+ chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
+ pr_info("CPR Platform Data (upside_steps: %d) (downside_steps: %d) ",
+ cpr->config->up_threshold, cpr->config->dn_threshold);
+ pr_info("(nominal_voltage: %duV) (turbo_voltage: %duV)\n",
+ cpr->config->cpr_mode_data[NORMAL_MODE].calibrated_uV,
+ cpr->config->cpr_mode_data[TURBO_MODE].calibrated_uV);
+ pr_info("(Current corner: TURBO) (gcnt_target: %d) (quot: %d)\n",
+ chip_data->ring_osc_data[chip_data->ring_osc].gcnt,
+ chip_data->ring_osc_data[chip_data->ring_osc].quot);
+
/* Initialze the Debugfs Entry for cpr */
res = msm_cpr_debug_init(cpr->base);
if (res) {
@@ -793,7 +843,6 @@
/* Enable the cpr */
cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, ENABLE_CPR);
-
cpr->freq_transition.notifier_call = cpr_freq_transition;
cpufreq_register_notifier(&cpr->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
diff --git a/arch/arm/mach-msm/msm_cpr.h b/arch/arm/mach-msm/msm_cpr.h
index 2642b9c..cb665b7 100644
--- a/arch/arm/mach-msm/msm_cpr.h
+++ b/arch/arm/mach-msm/msm_cpr.h
@@ -120,10 +120,10 @@
/**
* struct msm_vp_data - structure for VP configuration
- * @min_volt_mV: minimum milivolt level for VP
- * @max_volt_mV: maximum milivolt level for VP
- * @default_volt_mV: default milivolt for VP
- * @step_size_mV: step size of voltage
+ * @min_volt: minimum microvolt level for VP
+ * @max_volt: maximum microvolt level for VP
+ * @default_volt: default microvolt for VP
+ * @step_size: step size of voltage in microvolt
*/
struct msm_cpr_vp_data {
int min_volt;
@@ -135,11 +135,11 @@
/**
* struct msm_cpr_osc - Data for CPR ring oscillator
* @gcnt: gate count value for the oscillator
- * @target_count: target value for ring oscillator
+ * @quot: target value for ring oscillator
*/
struct msm_cpr_osc {
int gcnt;
- uint32_t target_count;
+ uint32_t quot;
};
/**
@@ -156,7 +156,7 @@
uint32_t step_quot;
uint32_t Vmax;
uint32_t Vmin;
- uint32_t calibrated_mV;
+ uint32_t calibrated_uV;
};
/**
@@ -180,8 +180,13 @@
uint32_t dn_threshold;
uint32_t up_margin;
uint32_t dn_margin;
- uint32_t nom_freq_limit;
+ uint32_t max_nom_freq;
+ uint32_t max_freq;
+ uint32_t max_quot;
struct msm_cpr_vp_data *vp_data;
+ uint32_t (*get_quot)(uint32_t max_quot, uint32_t max_freq,
+ uint32_t new_freq);
+ void (*clk_enable)(void);
};
/**
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 5b8284d..cd5556a 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -62,7 +62,7 @@
#define DEFAULT_BUFFER_SIZE 256
#define GFP_FLAG(noirq) (noirq ? GFP_ATOMIC : GFP_KERNEL)
-#define INV_HDR "resource does not exist"
+#define INV_RSC "resource does not exist"
#define ERR "err\0"
#define MAX_ERR_BUFFER_SIZE 128
#define INIT_ERROR 1
@@ -172,8 +172,10 @@
int i;
int data_size, msg_size;
- if (!handle)
+ if (!handle) {
+ pr_err("%s(): Invalid handle\n", __func__);
return -EINVAL;
+ }
data_size = ALIGN(size, SZ_4);
msg_size = data_size + sizeof(struct rpm_request_header);
@@ -191,8 +193,11 @@
break;
}
- if (i >= handle->num_elements)
+ if (i >= handle->num_elements) {
+ pr_err("%s(): Number of resources exceeds max allocated\n",
+ __func__);
return -ENOMEM;
+ }
if (i == handle->write_idx)
handle->write_idx++;
@@ -200,8 +205,10 @@
if (!handle->kvp[i].value) {
handle->kvp[i].value = kzalloc(data_size, GFP_FLAG(noirq));
- if (!handle->kvp[i].value)
+ if (!handle->kvp[i].value) {
+ pr_err("%s(): Failed malloc\n", __func__);
return -ENOMEM;
+ }
} else {
/* We enter the else case, if a key already exists but the
* data doesn't match. In which case, we should zero the data
@@ -366,13 +373,20 @@
return elem;
}
-static int msm_rpm_get_next_msg_id(void)
+static uint32_t msm_rpm_get_next_msg_id(void)
{
- int id;
+ uint32_t id;
+
+ /*
+ * A message id of 0 is used by the driver to indicate a error
+ * condition. The RPM driver uses a id of 1 to indicate unsent data
+ * when the data sent over hasn't been modified. This isn't a error
+ * scenario and wait for ack returns a success when the message id is 1.
+ */
do {
id = atomic_inc_return(&msm_rpm_msg_id);
- } while ((id == 0) || msm_rpm_get_entry_from_msg_id(id));
+ } while ((id == 0) || (id == 1) || msm_rpm_get_entry_from_msg_id(id));
return id;
}
@@ -459,8 +473,12 @@
tmp += 2 * sizeof(uint32_t);
- if (!(memcmp(tmp, INV_HDR, min(req_len, sizeof(INV_HDR))-1)))
+ if (!(memcmp(tmp, INV_RSC, min(req_len, sizeof(INV_RSC))-1))) {
+ pr_err("%s(): RPM NACK Unsupported resource\n", __func__);
rc = -EINVAL;
+ } else {
+ pr_err("%s(): RPM NACK Invalid header\n", __func__);
+ }
return rc;
}
@@ -658,7 +676,8 @@
int req_hdr_sz, msg_hdr_sz;
if (!cdata->msg_hdr.data_len)
- return 0;
+ return 1;
+
req_hdr_sz = sizeof(cdata->req_hdr);
msg_hdr_sz = sizeof(cdata->msg_hdr);
@@ -676,8 +695,10 @@
cdata->buf = kzalloc(msg_size, GFP_FLAG(noirq));
}
- if (!cdata->buf)
+ if (!cdata->buf) {
+ pr_err("%s(): Failed malloc\n", __func__);
return 0;
+ }
tmpbuff = cdata->buf;
@@ -722,7 +743,7 @@
ret = smd_write_avail(msm_rpm_data.ch_info);
if (ret < 0) {
- pr_warn("%s(): SMD not initialized\n", __func__);
+ pr_err("%s(): SMD not initialized\n", __func__);
spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags);
return 0;
}
@@ -749,7 +770,7 @@
} else if (ret < msg_size) {
struct msm_rpm_wait_data *rc;
ret = 0;
- pr_info("Failed to write data msg_size:%d ret:%d\n",
+ pr_err("Failed to write data msg_size:%d ret:%d\n",
msg_size, ret);
rc = msm_rpm_get_entry_from_msg_id(cdata->msg_hdr.msg_id);
if (rc)
@@ -774,8 +795,13 @@
{
struct msm_rpm_wait_data *elem;
- if (!msg_id)
- return -EINVAL;
+ if (!msg_id) {
+ pr_err("%s(): Invalid msg id\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (msg_id == 1)
+ return 0;
if (standalone)
return 0;
@@ -798,8 +824,13 @@
uint32_t id = 0;
int count = 0;
- if (!msg_id)
- return -EINVAL;
+ if (!msg_id) {
+ pr_err("%s(): Invalid msg id\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (msg_id == 1)
+ return 0;
if (standalone)
return 0;
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 7bfb208..67a2e6b 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -32,11 +32,17 @@
#define Q_REG_STATUS1 0x8
#define Q_REG_STATUS1_VAL_MASK 0x1
-#define Q_REG_STATUS1_GPIO_EN_MASK 0x2
+#define Q_REG_STATUS1_GPIO_EN_REV0_MASK 0x2
+#define Q_REG_STATUS1_GPIO_EN_MASK 0x80
#define Q_REG_STATUS1_MPP_EN_MASK 0x80
#define Q_NUM_CTL_REGS 0xD
+/* revision registers base address offsets */
+#define Q_REG_DIG_MINOR_REV 0x0
+#define Q_REG_DIG_MAJOR_REV 0x1
+#define Q_REG_ANA_MINOR_REV 0x2
+
/* type registers base address offsets */
#define Q_REG_TYPE 0x4
#define Q_REG_SUBTYPE 0x5
@@ -158,6 +164,7 @@
u8 num_ctl_regs; /* usable number on this pin */
u8 type; /* peripheral type */
u8 subtype; /* peripheral subtype */
+ u8 dig_major_rev;
struct device_node *node;
enum qpnp_pin_param_type params[Q_NUM_PARAMS];
struct qpnp_pin_chip *q_chip;
@@ -646,9 +653,14 @@
Q_REG_ADDR(q_spec, Q_REG_STATUS1),
&buf[0], 1);
- en_mask = q_spec->type == Q_GPIO_TYPE ?
- Q_REG_STATUS1_GPIO_EN_MASK :
- Q_REG_STATUS1_MPP_EN_MASK;
+ if (q_spec->type == Q_GPIO_TYPE && q_spec->dig_major_rev == 0)
+ en_mask = Q_REG_STATUS1_GPIO_EN_REV0_MASK;
+ else if (q_spec->type == Q_GPIO_TYPE &&
+ q_spec->dig_major_rev > 0)
+ en_mask = Q_REG_STATUS1_GPIO_EN_MASK;
+ else /* MPP */
+ en_mask = Q_REG_STATUS1_MPP_EN_MASK;
+
if (!(buf[0] & en_mask))
return -EPERM;
@@ -1099,6 +1111,28 @@
}
#endif
+static int qpnp_pin_is_valid_pin(struct qpnp_pin_spec *q_spec)
+{
+ if (q_spec->type == Q_GPIO_TYPE)
+ switch (q_spec->subtype) {
+ case Q_GPIO_SUBTYPE_GPIO_4CH:
+ case Q_GPIO_SUBTYPE_GPIOC_4CH:
+ case Q_GPIO_SUBTYPE_GPIO_8CH:
+ case Q_GPIO_SUBTYPE_GPIOC_8CH:
+ return 1;
+ }
+ else if (q_spec->type == Q_MPP_TYPE)
+ switch (q_spec->subtype) {
+ case Q_MPP_SUBTYPE_4CH_NO_ANA_OUT:
+ case Q_MPP_SUBTYPE_4CH_NO_SINK:
+ case Q_MPP_SUBTYPE_4CH_FULL_FUNC:
+ case Q_MPP_SUBTYPE_8CH_FULL_FUNC:
+ return 1;
+ }
+
+ return 0;
+}
+
static int qpnp_pin_probe(struct spmi_device *spmi)
{
struct qpnp_pin_chip *q_chip;
@@ -1108,7 +1142,7 @@
int i, rc;
int lowest_gpio = UINT_MAX, highest_gpio = 0;
u32 intspec[3], gpio;
- char buf[2];
+ char version[Q_REG_SUBTYPE - Q_REG_DIG_MAJOR_REV + 1];
const char *dev_name;
dev_name = spmi_get_primary_dev_name(spmi);
@@ -1218,14 +1252,23 @@
q_spec->q_chip = q_chip;
rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_TYPE), &buf[0], 2);
+ Q_REG_ADDR(q_spec, Q_REG_DIG_MAJOR_REV),
+ &version[0], ARRAY_SIZE(version));
if (rc) {
dev_err(&spmi->dev, "%s: unable to read type regs\n",
__func__);
goto err_probe;
}
- q_spec->type = buf[0];
- q_spec->subtype = buf[1];
+ q_spec->dig_major_rev = version[Q_REG_DIG_MAJOR_REV -
+ Q_REG_DIG_MAJOR_REV];
+ q_spec->type = version[Q_REG_TYPE - Q_REG_DIG_MAJOR_REV];
+ q_spec->subtype = version[Q_REG_SUBTYPE - Q_REG_DIG_MAJOR_REV];
+
+ if (!qpnp_pin_is_valid_pin(q_spec)) {
+ dev_err(&spmi->dev, "%s: invalid pin type (type=0x%x subtype=0x%x)\n",
+ __func__, q_spec->type, q_spec->subtype);
+ goto err_probe;
+ }
rc = qpnp_pin_ctl_regs_init(q_spec);
if (rc)
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index bd22233..74493f4 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -226,6 +226,10 @@
adreno_idle(device);
+ if (adreno_is_a20x(adreno_dev) && adreno_dev->drawctxt_active)
+ kgsl_setstate(&device->mmu, adreno_dev->drawctxt_active->id,
+ KGSL_MMUFLAGS_PTUPDATE);
+
kgsl_sharedmem_free(&drawctxt->gpustate);
kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c1617bff..085b632 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -328,12 +328,14 @@
dev->clk_state = state;
if (state != 0) {
clk_enable(dev->clk);
- clk_enable(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_enable(dev->pclk);
} else {
qup_update_state(dev, QUP_RESET_STATE);
clk_disable(dev->clk);
qup_config_core_on_en(dev);
- clk_disable(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_disable(dev->pclk);
}
}
@@ -1325,6 +1327,12 @@
dev->clk_state = 0;
clk_prepare(dev->clk);
clk_prepare(dev->pclk);
+ /* If the same AHB clock is used on Modem side
+ * switch it on here itself and don't switch it
+ * on and off during suspend and resume.
+ */
+ if (dev->pdata->keep_ahb_clk_on)
+ clk_enable(dev->pclk);
setup_timer(&dev->pwr_timer, qup_i2c_pwr_timer, (unsigned long) dev);
pm_runtime_set_active(&pdev->dev);
@@ -1396,9 +1404,11 @@
free_irq(dev->err_irq, dev);
i2c_del_adapter(&dev->adapter);
clk_unprepare(dev->clk);
- clk_unprepare(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on) {
+ clk_unprepare(dev->pclk);
+ clk_put(dev->pclk);
+ }
clk_put(dev->clk);
- clk_put(dev->pclk);
qup_i2c_free_gpios(dev);
if (dev->gsbi)
iounmap(dev->gsbi);
@@ -1434,7 +1444,8 @@
if (dev->clk_state != 0)
qup_i2c_pwr_mgmt(dev, 0);
clk_unprepare(dev->clk);
- clk_unprepare(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_unprepare(dev->pclk);
qup_i2c_free_gpios(dev);
return 0;
}
@@ -1445,7 +1456,8 @@
struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
BUG_ON(qup_i2c_request_gpios(dev) != 0);
clk_prepare(dev->clk);
- clk_prepare(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_prepare(dev->pclk);
dev->suspended = 0;
return 0;
}
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index d3da652..04a7598 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -123,6 +123,7 @@
struct delayed_work input_work;
u32 use_poll;
u32 poll_interval;
+ u32 dlpf_index;
};
struct sensor_regulator {
@@ -137,6 +138,39 @@
{NULL, "vlogic", 1800000, 1800000},
};
+struct dlpf_cfg_tb {
+ u8 cfg; /* cfg index */
+ u32 lpf_bw; /* low pass filter bandwidth in Hz */
+ u32 sample_rate; /* analog sample rate in Khz, 1 or 8 */
+};
+
+static struct dlpf_cfg_tb dlpf_table[] = {
+ {6, 5, 1},
+ {5, 10, 1},
+ {4, 20, 1},
+ {3, 42, 1},
+ {2, 98, 1},
+ {1, 188, 1},
+ {0, 256, 8},
+};
+
+static u8 interval_to_dlpf_cfg(u32 interval)
+{
+ u32 sample_rate = 1000 / interval;
+ u32 i;
+
+ /* the filter bandwidth needs to be greater or
+ * equal to half of the sample rate
+ */
+ for (i = 0; i < sizeof(dlpf_table)/sizeof(dlpf_table[0]); i++) {
+ if (dlpf_table[i].lpf_bw * 2 >= sample_rate)
+ return i;
+ }
+
+ /* return the maximum possible */
+ return --i;
+}
+
static int mpu3050_config_regulator(struct i2c_client *client, bool on)
{
int rc = 0, i;
@@ -217,6 +251,9 @@
{
struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
unsigned long interval_ms;
+ unsigned int dlpf_index;
+ u8 divider, reg;
+ int ret;
if (kstrtoul(buf, 10, &interval_ms))
return -EINVAL;
@@ -224,12 +261,27 @@
(interval_ms > MPU3050_MAX_POLL_INTERVAL))
return -EINVAL;
- if (sensor)
- sensor->poll_interval = interval_ms;
+ dlpf_index = interval_to_dlpf_cfg(interval_ms);
+ divider = interval_ms * dlpf_table[dlpf_index].sample_rate - 1;
- /* Output frequency divider. The poll interval */
- i2c_smbus_write_byte_data(sensor->client, MPU3050_SMPLRT_DIV,
- interval_ms - 1);
+ if (sensor->dlpf_index != dlpf_index) {
+ /* Set low pass filter and full scale */
+ reg = dlpf_table[dlpf_index].cfg;
+ reg |= MPU3050_DEFAULT_FS_RANGE << 3;
+ reg |= MPU3050_EXT_SYNC_NONE << 5;
+ ret = i2c_smbus_write_byte_data(sensor->client,
+ MPU3050_DLPF_FS_SYNC, reg);
+ if (ret == 0)
+ sensor->dlpf_index = dlpf_index;
+ }
+
+ if (sensor->poll_interval != interval_ms) {
+ /* Output frequency divider. The poll interval */
+ ret = i2c_smbus_write_byte_data(sensor->client,
+ MPU3050_SMPLRT_DIV, divider);
+ if (ret == 0)
+ sensor->poll_interval = interval_ms;
+ }
return size;
}
@@ -482,8 +534,8 @@
return ret;
/* Set low pass filter and full scale */
- reg = MPU3050_DEFAULT_FS_RANGE;
- reg |= MPU3050_DLPF_CFG_42HZ << 3;
+ reg = MPU3050_DLPF_CFG_42HZ;
+ reg |= MPU3050_DEFAULT_FS_RANGE << 3;
reg |= MPU3050_EXT_SYNC_NONE << 5;
ret = i2c_smbus_write_byte_data(client, MPU3050_DLPF_FS_SYNC, reg);
if (ret < 0)
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 577648f..3dc0fe7 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -332,7 +332,7 @@
uint32_t data_offset;
};
-#define MSM_DEV_INST_MAX 16
+#define MSM_DEV_INST_MAX 24
struct msm_cam_v4l2_dev_inst {
struct v4l2_fh eventHandle;
struct vb2_queue vid_bufq;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index e8d9e04..407bf2e 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1117,6 +1117,12 @@
return -ENOTRECOVERABLE;
}
+ if (!dev->vp_dummy_complete) {
+ pr_err("VCAP Err: %s: VP dummy read not complete",
+ __func__);
+ return -EINVAL;
+ }
+
switch (c_data->op_mode) {
case VC_VCAP_OP:
mutex_lock(&dev->dev_mutex);
@@ -1390,19 +1396,13 @@
}
dev->vc_resource = 0;
mutex_unlock(&dev->dev_mutex);
+ c_data->streaming = 0;
rc = vb2_streamoff(&c_data->vc_vidq,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (rc >= 0) {
- c_data->streaming = 0;
+ if (rc >= 0)
atomic_set(&c_data->dev->vc_enabled, 0);
- }
return rc;
case VP_VCAP_OP:
- if (!dev->vp_dummy_complete) {
- pr_err("VCAP Err: %s: VP dummy read not complete",
- __func__);
- return -EINVAL;
- }
if (c_data != dev->vp_client) {
pr_err("VCAP Err: %s: VP held by other client",
__func__);
@@ -1441,11 +1441,6 @@
atomic_set(&c_data->dev->vp_enabled, 0);
return rc;
case VC_AND_VP_VCAP_OP:
- if (!dev->vp_dummy_complete) {
- pr_err("VCAP Err: %s: VP dummy read not complete",
- __func__);
- return -EINVAL;
- }
if (c_data != dev->vp_client || c_data != dev->vc_client) {
pr_err("VCAP Err: %s: VC/VP held by other client",
__func__);
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 62cc306..966fa4b 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -120,6 +120,13 @@
dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
+ c_data = dev->vc_client;
+ if (!c_data->streaming) {
+ writel_iowmb(irq, VCAP_VC_INT_CLEAR);
+ pr_err("VC no longer streaming\n");
+ return IRQ_HANDLED;
+ }
+
v4l2_evt.id = 0;
if (irq & 0x8000200) {
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
@@ -161,7 +168,6 @@
pr_err("VC: There is no active vc client\n");
return IRQ_HANDLED;
}
- c_data = dev->vc_client;
spin_lock(&dev->vc_client->cap_slock);
if (list_empty(&dev->vc_client->vid_vc_action.active)) {
@@ -316,15 +322,34 @@
void vc_stop_capture(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
- int rc;
+ unsigned int reg;
+ int timeout;
- rc = readl_relaxed(VCAP_VC_CTRL);
- writel_iowmb(rc & ~(0x1), VCAP_VC_CTRL);
-
- if (atomic_read(&dev->vc_enabled) == 1)
- disable_irq(dev->vcirq->start);
-
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ writel_iowmb(0x0, VCAP_VC_INT_MASK);
flush_workqueue(dev->vcap_wq);
+ if (atomic_read(&dev->vc_enabled) == 1)
+ disable_irq_nosync(dev->vcirq->start);
+
+ writel_iowmb(0x00000000, VCAP_VC_CTRL);
+ writel_iowmb(0x00000001, VCAP_SW_RESET_REQ);
+ timeout = 10000;
+ while (1) {
+ reg = (readl_relaxed(VCAP_SW_RESET_STATUS) & 0x1);
+ if (!reg)
+ break;
+ timeout--;
+ if (timeout == 0) {
+ /* This should not happen */
+ pr_err("VC is not resetting properly\n");
+ writel_iowmb(0x00000000, VCAP_SW_RESET_REQ);
+ break;
+ }
+ }
+
+ reg = readl_relaxed(VCAP_VC_NPL_CTRL);
+ reg = readl_relaxed(VCAP_VC_NPL_CTRL);
+ writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
}
int config_vc_format(struct vcap_client_data *c_data)
@@ -336,21 +361,20 @@
dev = c_data->dev;
/* restart VC */
- writel_relaxed(0x00000001, VCAP_SW_RESET_REQ);
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ writel_iowmb(0x00000001, VCAP_SW_RESET_REQ);
timeout = 10000;
while (1) {
- rc = (readl_relaxed(VCAP_SW_RESET_STATUS) & 0x1);
- if (!rc)
+ if (!(readl_relaxed(VCAP_SW_RESET_STATUS) & 0x1))
break;
timeout--;
if (timeout == 0) {
pr_err("VC is not resetting properly\n");
+ writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
return -EINVAL;
}
}
- writel_relaxed(0x00000000, VCAP_SW_RESET_REQ);
- writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
rc = readl_relaxed(VCAP_VC_NPL_CTRL);
rc = readl_relaxed(VCAP_VC_NPL_CTRL);
writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
diff --git a/drivers/media/video/vcap_vc.h b/drivers/media/video/vcap_vc.h
index 792fb14..76693bb 100644
--- a/drivers/media/video/vcap_vc.h
+++ b/drivers/media/video/vcap_vc.h
@@ -19,14 +19,8 @@
#define VCAP_HARDWARE_VERSION 0x10000000
-#define VCAP_BASE (dev->vcapbase)
-#define VCAP_OFFSET(off) (VCAP_BASE + off)
-
#define VCAP_HARDWARE_VERSION_REG (VCAP_BASE + 0x0000)
-#define VCAP_SW_RESET_REQ (VCAP_BASE + 0x0024)
-#define VCAP_SW_RESET_STATUS (VCAP_BASE + 0x0028)
-
#define VCAP_VC_CTRL (VCAP_BASE + 0x0800)
#define VCAP_VC_NPL_CTRL (VCAP_BASE + 0x0804)
#define VCAP_VC_POLARITY (VCAP_BASE + 0x081c)
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index ba053f2..f8f27d4 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -74,6 +74,12 @@
dev = c_data->dev;
dprintk(2, "Start setup buffers\n");
+ if (dev->vp_shutdown) {
+ dprintk(1, "%s: VP shutting down, no buf setup\n",
+ __func__);
+ return -EPERM;
+ }
+
/* No need to verify vp_client is not NULL caller does so */
vp_act = &dev->vp_client->vid_vp_action;
@@ -262,6 +268,8 @@
writel_relaxed(0x00000000, VCAP_VP_INTERRUPT_ENABLE);
writel_iowmb(irq, VCAP_VP_INT_CLEAR);
atomic_set(&dev->vp_enabled, 0);
+ if (dev->vp_shutdown)
+ wake_up(&dev->vp_dummy_waitq);
return;
}
@@ -350,30 +358,60 @@
return IRQ_HANDLED;
}
+int vp_sw_reset(struct vcap_dev *dev)
+{
+ int timeout;
+ writel_iowmb(0x00000010, VCAP_SW_RESET_REQ);
+ timeout = 10000;
+ while (1) {
+ if (!(readl_relaxed(VCAP_SW_RESET_STATUS) & 0x10))
+ break;
+ timeout--;
+ if (timeout == 0) {
+ /* This should not happen */
+ pr_err("VP is not resetting properly\n");
+ writel_iowmb(0x00000000, VCAP_SW_RESET_REQ);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
void vp_stop_capture(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
+ int rc;
- writel_iowmb(0x00000000, VCAP_VP_CTRL);
+ dev->vp_shutdown = true;
flush_workqueue(dev->vcap_wq);
- if (atomic_read(&dev->vp_enabled) == 1)
- disable_irq(dev->vpirq->start);
+ if (atomic_read(&dev->vp_enabled) == 1) {
+ rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
+ !atomic_read(&dev->vp_enabled),
+ msecs_to_jiffies(50));
+ if (rc == 0 && atomic_read(&dev->vp_enabled) == 1) {
+ /* This should not happen, if it does hw is stuck */
+ pr_err("%s: VP Timeout and VP still running\n",
+ __func__);
+ }
+ }
- writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
- writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+ vp_sw_reset(dev);
+ dev->vp_shutdown = false;
}
int config_vp_format(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
+ int rc;
INIT_WORK(&dev->vp_to_vc_work.work, mov_buf_to_vc);
dev->vp_to_vc_work.cd = c_data;
/* SW restart VP */
- writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
- writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+ rc = vp_sw_reset(dev);
+ if (rc < 0)
+ return rc;
/* Film Mode related settings */
writel_iowmb(0x00000000, VCAP_VP_FILM_PROJECTION_T0);
@@ -668,20 +706,18 @@
dev->vp_dummy_event = true;
+ enable_irq(dev->vpirq->start);
writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
writel_iowmb(0x00000000, VCAP_VP_CTRL);
writel_iowmb(0x00010000, VCAP_VP_CTRL);
- enable_irq(dev->vpirq->start);
rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
dev->vp_dummy_complete, msecs_to_jiffies(50));
if (!rc && !dev->vp_dummy_complete) {
pr_err("%s: VP dummy event timeout", __func__);
rc = -ETIME;
- writel_iowmb(0x00000000, VCAP_VP_CTRL);
- writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
- writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+ vp_sw_reset(dev);
dev->vp_dummy_complete = false;
}
diff --git a/drivers/media/video/vcap_vp.h b/drivers/media/video/vcap_vp.h
index b2b00e9..2ad5848 100644
--- a/drivers/media/video/vcap_vp.h
+++ b/drivers/media/video/vcap_vp.h
@@ -17,9 +17,6 @@
#include <media/vcap_v4l2.h>
-#define VCAP_BASE (dev->vcapbase)
-#define VCAP_OFFSET(off) (VCAP_BASE + off)
-
#define VCAP_VP_INT_STATUS (VCAP_BASE + 0x404)
#define VCAP_VP_INT_CLEAR (VCAP_BASE + 0x40C)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 2b278be..a86798d 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1351,9 +1351,11 @@
*/
if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
|| data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
- pr_err("%s: CMD%d: Data timeout\n",
+ pr_err("%s: CMD%d: Data timeout. DAT0 => %d\n",
mmc_hostname(host->mmc),
- data->mrq->cmd->opcode);
+ data->mrq->cmd->opcode,
+ (readl_relaxed(host->base
+ + MCI_TEST_INPUT) & 0x2) ? 1 : 0);
data->error = -ETIMEDOUT;
msmsdcc_dump_sdcc_state(host);
}
@@ -3358,10 +3360,10 @@
{
struct device *dev = mmc_dev(host->mmc);
- pr_info("%s: PM: sdcc_suspended=%d, pending_resume=%d, sdcc_suspending=%d\n",
+ pr_err("%s: PM: sdcc_suspended=%d, pending_resume=%d, sdcc_suspending=%d\n",
mmc_hostname(host->mmc), host->sdcc_suspended,
host->pending_resume, host->sdcc_suspending);
- pr_info("%s: RPM: runtime_status=%d, usage_count=%d,"
+ pr_err("%s: RPM: runtime_status=%d, usage_count=%d,"
" is_suspended=%d, disable_depth=%d, runtime_error=%d,"
" request_pending=%d, request=%d\n",
mmc_hostname(host->mmc), dev->power.runtime_status,
@@ -4847,10 +4849,10 @@
if (!base)
return;
- pr_info("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
+ pr_err("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
" =====\n", name, phys_base, (u32)base);
for (i = 0; i < no_of_regs; i = i + 4) {
- pr_info("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
+ pr_err("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
(u32)readl_relaxed(base + i*4),
(u32)readl_relaxed(base + ((i+1)*4)),
(u32)readl_relaxed(base + ((i+2)*4)),
@@ -4861,25 +4863,29 @@
static void msmsdcc_dump_sdcc_state(struct msmsdcc_host *host)
{
/* Dump current state of SDCC clocks, power and irq */
- pr_info("%s: SDCC PWR is %s\n", mmc_hostname(host->mmc),
+ pr_err("%s: SDCC PWR is %s\n", mmc_hostname(host->mmc),
(host->pwr ? "ON" : "OFF"));
- pr_info("%s: SDCC clks are %s, MCLK rate=%d\n",
+ pr_err("%s: SDCC clks are %s, MCLK rate=%d\n",
mmc_hostname(host->mmc),
(atomic_read(&host->clks_on) ? "ON" : "OFF"),
(u32)clk_get_rate(host->clk));
- pr_info("%s: SDCC irq is %s\n", mmc_hostname(host->mmc),
+ pr_err("%s: SDCC irq is %s\n", mmc_hostname(host->mmc),
(host->sdcc_irq_disabled ? "disabled" : "enabled"));
/* Now dump SDCC registers. Don't print FIFO registers */
- if (atomic_read(&host->clks_on))
+ if (atomic_read(&host->clks_on)) {
msmsdcc_print_regs("SDCC-CORE", host->base,
host->core_memres->start, 28);
+ pr_err("%s: MCI_TEST_INPUT = 0x%.8x\n",
+ mmc_hostname(host->mmc),
+ readl_relaxed(host->base + MCI_TEST_INPUT));
+ }
if (host->curr.data) {
if (!msmsdcc_is_dma_possible(host, host->curr.data))
- pr_info("%s: PIO mode\n", mmc_hostname(host->mmc));
+ pr_err("%s: PIO mode\n", mmc_hostname(host->mmc));
else if (is_dma_mode(host))
- pr_info("%s: ADM mode: busy=%d, chnl=%d, crci=%d\n",
+ pr_err("%s: ADM mode: busy=%d, chnl=%d, crci=%d\n",
mmc_hostname(host->mmc), host->dma.busy,
host->dma.channel, host->dma.crci);
else if (is_sps_mode(host)) {
@@ -4887,16 +4893,16 @@
msmsdcc_print_regs("SDCC-DML", host->dml_base,
host->dml_memres->start,
16);
- pr_info("%s: SPS mode: busy=%d\n",
+ pr_err("%s: SPS mode: busy=%d\n",
mmc_hostname(host->mmc), host->sps.busy);
}
- pr_info("%s: xfer_size=%d, data_xfered=%d, xfer_remain=%d\n",
+ pr_err("%s: xfer_size=%d, data_xfered=%d, xfer_remain=%d\n",
mmc_hostname(host->mmc), host->curr.xfer_size,
host->curr.data_xfered, host->curr.xfer_remain);
}
- pr_info("%s: got_dataend=%d, prog_enable=%d,"
+ pr_err("%s: got_dataend=%d, prog_enable=%d,"
" wait_for_auto_prog_done=%d, got_auto_prog_done=%d,"
" req_tout_ms=%d\n", mmc_hostname(host->mmc),
host->curr.got_dataend, host->prog_enable,
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index fbe8d3c..295c55c 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -29,6 +29,7 @@
#include <linux/if_arp.h>
#include <linux/msm_rmnet.h>
#include <linux/platform_device.h>
+#include <net/pkt_sched.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
@@ -638,6 +639,16 @@
dev->name);
break;
+ case RMNET_IOCTL_FLOW_ENABLE:
+ tc_qdisc_flow_control(dev, (u32)ifr->ifr_data, 1);
+ DBG0("[%s] rmnet_ioctl(): enabled flow", dev->name);
+ break;
+
+ case RMNET_IOCTL_FLOW_DISABLE:
+ tc_qdisc_flow_control(dev, (u32)ifr->ifr_data, 0);
+ DBG0("[%s] rmnet_ioctl(): disabled flow", dev->name);
+ break;
+
case RMNET_IOCTL_GET_QOS: /* Get QoS header state */
ifr->ifr_ifru.ifru_data =
(void *)(p->operation_mode & RMNET_MODE_QOS);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 49e6ee5..6a4e50c 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3697,24 +3697,9 @@
chip->led_src_config, rc);
}
- /* Workarounds for die 1.1 and 1.0 */
- if (pm8xxx_get_revision(chip->dev->parent) < PM8XXX_REVISION_8921_2p0) {
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST2, 0xF1);
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xCE);
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD8);
-
- /* software workaround for correct battery_id detection */
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_0, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_1, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_2, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_3, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0D);
- udelay(100);
- pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0C);
- }
-
/* Workarounds for die 3.0 */
- if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0)
+ if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0
+ && pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8921)
pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xAC);
/* Enable isub_fine resolution AICL for PM8917 */
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index 78a1292..daf0564 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -159,6 +159,7 @@
enum platform_type hw_type;
int pm_tsens_thr_data;
int pm_tsens_cntl;
+ struct work_struct tsens_work;
struct tsens_tm_device_sensor sensor[0];
};
@@ -610,9 +611,10 @@
NULL, "type");
}
-static irqreturn_t tsens_isr(int irq, void *data)
+static void tsens_scheduler_fn(struct work_struct *work)
{
- struct tsens_tm_device *tm = data;
+ struct tsens_tm_device *tm = container_of(work, struct tsens_tm_device,
+ tsens_work);
unsigned int threshold, threshold_low, i, code, reg, sensor, mask;
unsigned int sensor_addr;
bool upper_th_x, lower_th_x;
@@ -627,6 +629,7 @@
writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
TSENS_UPPER_STATUS_CLR, TSENS_CNTL_ADDR);
}
+
mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR);
threshold = readl_relaxed(TSENS_THRESHOLD_ADDR);
threshold_low = (threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
@@ -658,9 +661,7 @@
/* Notify user space */
schedule_work(&tm->sensor[i].work);
adc_code = readl_relaxed(sensor_addr);
- pr_info("\nTrip point triggered by "
- "current temperature (%d degrees) "
- "measured by Temperature-Sensor %d\n",
+ pr_debug("Trigger (%d degrees) for sensor %d\n",
tsens_tz_code_to_degC(adc_code, i), i);
}
}
@@ -672,6 +673,12 @@
else
writel_relaxed(reg & mask, TSENS_CNTL_ADDR);
mb();
+}
+
+static irqreturn_t tsens_isr(int irq, void *data)
+{
+ schedule_work(&tmdev->tsens_work);
+
return IRQ_HANDLED;
}
@@ -869,8 +876,7 @@
tmdev->sensor[TSENS_MAIN_SENSOR].calib_data =
tmdev->sensor[TSENS_MAIN_SENSOR].calib_data_backup;
if (!tmdev->sensor[TSENS_MAIN_SENSOR].calib_data) {
- pr_err("%s: No temperature sensor data for calibration"
- " in QFPROM!\n", __func__);
+ pr_err("QFPROM TSENS calibration data not present\n");
return -ENODEV;
}
@@ -901,8 +907,7 @@
tmdev->sensor[i].calib_data =
tmdev->sensor[i].calib_data_backup;
if (!tmdev->sensor[i].calib_data) {
- WARN(1, "%s: No temperature sensor:%d data for"
- " calibration in QFPROM!\n", __func__, i);
+ pr_err("QFPROM TSENS calibration data not present\n");
return -ENODEV;
}
tmdev->sensor[i].offset = (TSENS_CAL_DEGC *
@@ -1026,6 +1031,7 @@
thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
goto fail;
}
+ INIT_WORK(&tmdev->tsens_work, tsens_scheduler_fn);
pr_debug("%s: OK\n", __func__);
mb();
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 522e3a4..882aa7f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1378,6 +1378,7 @@
struct platform_device *dwc3;
struct dwc3_msm *msm;
struct resource *res;
+ void __iomem *tcsr;
int ret = 0;
msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
@@ -1484,6 +1485,25 @@
goto free_hs_ldo_init;
}
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_dbg(&pdev->dev, "missing TCSR memory resource\n");
+ } else {
+ tcsr = devm_ioremap_nocache(&pdev->dev, res->start,
+ resource_size(res));
+ if (!tcsr) {
+ dev_dbg(&pdev->dev, "tcsr ioremap failed\n");
+ } else {
+ /* Enable USB3 on the primary USB port. */
+ writel_relaxed(0x1, tcsr);
+ /*
+ * Ensure that TCSR write is completed before
+ * USB registers initialization.
+ */
+ mb();
+ }
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "missing memory base resource\n");
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index b396593..2126ff0 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -27,6 +27,7 @@
#include <linux/err.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/wakelock.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@@ -58,13 +59,14 @@
struct clk *phy_clk;
struct clk *cal_clk;
struct regulator *hsic_vddcx;
+ bool async_int;
atomic_t in_lpm;
+ struct wake_lock wlock;
int peripheral_status_irq;
int wakeup_irq;
int wakeup_gpio;
bool wakeup_irq_enabled;
- bool irq_enabled;
- bool async_int;
+ atomic_t pm_usage_cnt;
uint32_t bus_perf_client;
uint32_t wakeup_int_cnt;
enum usb_vdd_type vdd_type;
@@ -624,15 +626,13 @@
disable_irq(hcd->irq);
- /* make sure we don't race against the root hub being resumed */
- if (HCD_RH_RUNNING(hcd) || HCD_WAKEUP_PENDING(hcd) ||
+ /* make sure we don't race against a remote wakeup */
+ if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
readl_relaxed(USB_PORTSC) & PORT_RESUME) {
- dev_warn(mehci->dev, "%s: Root hub is not suspended\n",
- __func__);
+ dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
enable_irq(hcd->irq);
return -EBUSY;
}
- mehci->irq_enabled = false;
/*
* PHY may take some time or even fail to enter into low power
@@ -690,13 +690,14 @@
}
atomic_set(&mehci->in_lpm, 1);
- mehci->irq_enabled = true;
enable_irq(hcd->irq);
mehci->wakeup_irq_enabled = 1;
enable_irq_wake(mehci->wakeup_irq);
enable_irq(mehci->wakeup_irq);
+ wake_unlock(&mehci->wlock);
+
dev_info(mehci->dev, "HSIC-USB in low power mode\n");
return 0;
@@ -720,6 +721,8 @@
mehci->wakeup_irq_enabled = 0;
}
+ wake_lock(&mehci->wlock);
+
if (mehci->bus_perf_client && debug_bus_voting_enabled) {
mehci->bus_vote = true;
queue_work(ehci_wq, &mehci->bus_vote_w);
@@ -775,14 +778,13 @@
if (mehci->async_int) {
mehci->async_int = false;
pm_runtime_put_noidle(mehci->dev);
- }
-
- if (!mehci->irq_enabled) {
enable_irq(hcd->irq);
- mehci->irq_enabled = true;
}
- pm_relax(mehci->dev);
+ if (atomic_read(&mehci->pm_usage_cnt)) {
+ atomic_set(&mehci->pm_usage_cnt, 0);
+ pm_runtime_put_noidle(mehci->dev);
+ }
dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
@@ -809,11 +811,9 @@
if (atomic_read(&mehci->in_lpm)) {
disable_irq_nosync(hcd->irq);
- mehci->irq_enabled = false;
dev_dbg(mehci->dev, "phy async intr\n");
mehci->async_int = true;
pm_runtime_get(mehci->dev);
- pm_stay_awake(mehci->dev);
return IRQ_HANDLED;
}
@@ -1030,9 +1030,7 @@
dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
__func__, mehci->wakeup_int_cnt);
- mehci->async_int = true;
- pm_runtime_get(mehci->dev);
- pm_stay_awake(mehci->dev);
+ wake_lock(&mehci->wlock);
if (mehci->wakeup_irq_enabled) {
mehci->wakeup_irq_enabled = 0;
@@ -1040,6 +1038,11 @@
disable_irq_nosync(irq);
}
+ if (!atomic_read(&mehci->pm_usage_cnt)) {
+ atomic_set(&mehci->pm_usage_cnt, 1);
+ pm_runtime_get(mehci->dev);
+ }
+
return IRQ_HANDLED;
}
@@ -1345,8 +1348,9 @@
goto unconfig_gpio;
}
- mehci->irq_enabled = true;
device_init_wakeup(&pdev->dev, 1);
+ wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
+ wake_lock(&mehci->wlock);
if (mehci->peripheral_status_irq) {
ret = request_threaded_irq(mehci->peripheral_status_irq,
@@ -1460,6 +1464,7 @@
msm_hsic_init_vddcx(mehci, 0);
msm_hsic_init_clocks(mehci, 0);
+ wake_lock_destroy(&mehci->wlock);
iounmap(hcd->regs);
usb_put_hcd(hcd);
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index 10cbe59..be8b58b 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -58,6 +58,7 @@
struct list_head to_mdm_list;
struct list_head to_ks_list;
wait_queue_head_t ks_wait_q;
+ struct miscdevice *fs_dev;
/* usb specific */
struct usb_device *udev;
@@ -531,7 +532,6 @@
struct usb_endpoint_descriptor *ep_desc;
int i;
struct ks_bridge *ksb;
- struct miscdevice *fs_dev;
ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
@@ -585,8 +585,8 @@
dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
- fs_dev = (struct miscdevice *)id->driver_info;
- misc_register(fs_dev);
+ ksb->fs_dev = (struct miscdevice *)id->driver_info;
+ misc_register(ksb->fs_dev);
usb_enable_autosuspend(ksb->udev);
@@ -649,6 +649,7 @@
}
spin_unlock_irqrestore(&ksb->lock, flags);
+ misc_deregister(ksb->fs_dev);
usb_put_dev(ksb->udev);
ksb->ifc = NULL;
usb_set_intfdata(ifc, NULL);
@@ -713,7 +714,8 @@
ksb = kzalloc(sizeof(struct ks_bridge), GFP_KERNEL);
if (!ksb) {
pr_err("unable to allocat mem for ks_bridge");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto dev_free;
}
__ksb[i] = ksb;
diff --git a/include/linux/msm_rmnet.h b/include/linux/msm_rmnet.h
index 9f52464..063a8f1 100644
--- a/include/linux/msm_rmnet.h
+++ b/include/linux/msm_rmnet.h
@@ -40,6 +40,8 @@
RMNET_IOCTL_GET_OPMODE = 0x000089F7, /* Get operation mode */
RMNET_IOCTL_OPEN = 0x000089F8, /* Open transport port */
RMNET_IOCTL_CLOSE = 0x000089F9, /* Close transport port */
+ RMNET_IOCTL_FLOW_ENABLE = 0x000089FA, /* Flow enable */
+ RMNET_IOCTL_FLOW_DISABLE = 0x000089FB, /* Flow disable */
RMNET_IOCTL_MAX
};
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index bd97b86..f95230e 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -824,29 +824,39 @@
/* extendedmode for the thumb nail image in VIDIOC_S_PARM */
#define MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+4)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RAW \
+/* ISP_PIX_OUTPUT1: no pp, directly send output1 buf to user */
+#define MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT1 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+5)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI \
+/* ISP_PIX_OUTPUT2: no pp, directly send output2 buf to user */
+#define MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT2 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+6)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI1 \
+/* raw image type */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RAW \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+7)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI2 \
+/* RDI dump */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+8)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AEC \
+/* RDI dump 1 */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI1 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+9)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AWB \
+/* RDI dump 2 */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI2 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+10)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AF \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AEC \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+11)
-#define MSM_V4L2_EXT_CAPTURE_MODE_IHIST \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AWB \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+12)
-#define MSM_V4L2_EXT_CAPTURE_MODE_CS \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AF \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+13)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RS \
+#define MSM_V4L2_EXT_CAPTURE_MODE_IHIST \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+14)
-#define MSM_V4L2_EXT_CAPTURE_MODE_CSTA \
+#define MSM_V4L2_EXT_CAPTURE_MODE_CS \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+15)
-#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+16)
+#define MSM_V4L2_EXT_CAPTURE_MODE_RS \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+16)
+#define MSM_V4L2_EXT_CAPTURE_MODE_CSTA \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+17)
+#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+18)
#define MSM_V4L2_PID_MOTION_ISO V4L2_CID_PRIVATE_BASE
#define MSM_V4L2_PID_EFFECT (V4L2_CID_PRIVATE_BASE+1)
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index cf99435..d56e534 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -38,6 +38,12 @@
writel_relaxed(val, addr); \
} while (0)
+#define VCAP_BASE (dev->vcapbase)
+#define VCAP_OFFSET(off) (VCAP_BASE + off)
+
+#define VCAP_SW_RESET_REQ (VCAP_BASE + 0x024)
+#define VCAP_SW_RESET_STATUS (VCAP_BASE + 0x028)
+
struct vcap_client_data;
enum rdy_buf {
@@ -167,6 +173,7 @@
bool vp_resource;
bool vp_dummy_event;
bool vp_dummy_complete;
+ bool vp_shutdown;
wait_queue_head_t vp_dummy_waitq;
struct workqueue_struct *vcap_wq;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 71dcb28..e8c0bf3 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1039,7 +1039,7 @@
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le);
int mgmt_le_conn_params(u16 index, bdaddr_t *bdaddr, u16 interval,
u16 latency, u16 timeout);
-int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
+int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 reason);
int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 4a69331..602fe59 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -311,6 +311,7 @@
#define MGMT_EV_DISCONNECTED 0x000C
struct mgmt_ev_disconnected {
bdaddr_t bdaddr;
+ __u8 reason;
} __packed;
#define MGMT_EV_CONNECT_FAILED 0x000D
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index fffdc60..95ec28b 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -103,7 +103,8 @@
struct tcf_result *res);
extern int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res);
-
+extern void tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle,
+ int flow_enable);
/* Calculate maximal size of packet seen by hard_start_xmit
routine of this device.
*/
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 382052b..90872c9 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -978,6 +978,16 @@
u32 sample_rate;
};
+struct asm_amrwbplus_cfg {
+ u32 size_bytes;
+ u32 version;
+ u32 num_channels;
+ u32 amr_band_mode;
+ u32 amr_dtx_mode;
+ u32 amr_frame_fmt;
+ u32 amr_lsf_idx;
+};
+
struct asm_flac_cfg {
u16 stream_info_present;
u16 min_blk_size;
@@ -1398,6 +1408,7 @@
struct asm_flac_cfg flac_cfg;
struct asm_vorbis_cfg vorbis_cfg;
struct asm_multi_channel_pcm_fmt_blk multi_ch_pcm_cfg;
+ struct asm_amrwbplus_cfg amrwbplus_cfg;
} __attribute__((packed)) write_cfg;
} __attribute__((packed));
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 01f2fac..323a228 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -288,6 +288,9 @@
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+ struct asm_amrwbplus_cfg *cfg);
+
int q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d3402b7..e5f43ec 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1794,7 +1794,7 @@
struct hci_ev_disconn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
- BT_DBG("%s status %d", hdev->name, ev->status);
+ BT_DBG("%s status %d reason %d", hdev->name, ev->status, ev->reason);
if (ev->status) {
hci_dev_lock(hdev);
@@ -1812,7 +1812,7 @@
conn->state = BT_CLOSED;
if (conn->type == ACL_LINK || conn->type == LE_LINK)
- mgmt_disconnected(hdev->id, &conn->dst);
+ mgmt_disconnected(hdev->id, &conn->dst, ev->reason);
if (conn->type == LE_LINK)
del_timer(&conn->smp_timer);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1702ce3..d7deaaf 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2875,21 +2875,22 @@
mgmt_pending_remove(cmd);
}
-int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
+int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 reason)
{
struct mgmt_ev_disconnected ev;
struct sock *sk = NULL;
int err;
- mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
-
bacpy(&ev.bdaddr, bdaddr);
+ ev.reason = reason;
err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
if (sk)
sock_put(sk);
+ mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
+
return err;
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 3d8981f..60e2fa9 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1030,6 +1030,35 @@
}
/*
+ * enable/disable flow on qdisc.
+ */
+void
+tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle, int enable_flow)
+{
+ struct Qdisc *q;
+ struct __qdisc_change_req {
+ struct nlattr attr;
+ struct tc_prio_qopt data;
+ } req = {
+ .attr = {sizeof(struct __qdisc_change_req), TCA_OPTIONS},
+ .data = {3, {1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 1}
+ };
+
+ /* override flow bit */
+ req.data.enable_flow = enable_flow;
+
+ /* look up using tcm handle */
+ q = qdisc_lookup(dev, tcm_handle);
+
+ /* call registered change function */
+ if (q) {
+ if (q->ops->change(q, &(req.attr)) != 0)
+ pr_err("tc_qdisc_flow_control: qdisc change failed");
+ }
+}
+EXPORT_SYMBOL(tc_qdisc_flow_control);
+
+/*
* Create/change qdisc.
*/
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 3b880ed..be0395b 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -133,7 +133,7 @@
static int msm_ext_top_spk_pamp;
static int msm_slim_0_rx_ch = 1;
static int msm_slim_0_tx_ch = 1;
-static int msm_hdmi_rx_ch = 2;
+static int msm_hdmi_rx_ch = 8;
static struct clk *codec_clk;
static int clk_users;
@@ -515,14 +515,15 @@
static const char *spk_function[] = {"Off", "On"};
static const char *slim0_rx_ch_text[] = {"One", "Two"};
static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
-static const char *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five", "Six"};
+static const char * const hdmi_rx_ch_text[] = {"Two", "Three", "Four",
+ "Five", "Six", "Seven", "Eight"};
static const struct soc_enum msm_enum[] = {
SOC_ENUM_SINGLE_EXT(2, spk_function),
SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
- SOC_ENUM_SINGLE_EXT(5, hdmi_rx_ch_text),
+ SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
};
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 42bc979..dd576c4 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -26,6 +26,7 @@
#include <sound/initval.h>
#include <sound/control.h>
#include <sound/q6asm.h>
+#include <sound/pcm_params.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/android_pmem.h>
@@ -82,12 +83,12 @@
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.buffer_bytes_max = 1200 * 1024 * 2,
- .period_bytes_min = 4800,
+ .period_bytes_min = 2400,
.period_bytes_max = 1200 * 1024,
.periods_min = 2,
- .periods_max = 512,
+ .periods_max = 1024,
.fifo_size = 0,
};
@@ -134,8 +135,6 @@
break;
} else
atomic_set(&prtd->pending_buffer, 0);
- if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
- break;
buf = prtd->audio_client->port[IN].buf;
pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
__func__, prtd->pcm_count, prtd->out_head);
@@ -292,6 +291,7 @@
struct asm_aac_cfg aac_cfg;
struct asm_wma_cfg wma_cfg;
struct asm_wmapro_cfg wma_pro_cfg;
+ struct asm_amrwbplus_cfg amrwb_cfg;
int ret;
pr_debug("compressed stream prepare\n");
@@ -389,6 +389,27 @@
return ret;
}
break;
+ case SND_AUDIOCODEC_AMRWB:
+ pr_debug("SND_AUDIOCODEC_AMRWB\n");
+ ret = q6asm_media_format_block(prtd->audio_client,
+ compr->codec);
+ if (ret < 0) {
+ pr_err("%s: CMD Format block failed\n", __func__);
+ return ret;
+ }
+ break;
+ case SND_AUDIOCODEC_AMRWBPLUS:
+ pr_debug("SND_AUDIOCODEC_AMRWBPLUS\n");
+ memset(&amrwb_cfg, 0x0, sizeof(struct asm_amrwbplus_cfg));
+ amrwb_cfg.size_bytes = sizeof(struct asm_amrwbplus_cfg);
+ pr_debug("calling q6asm_media_format_block_amrwbplus");
+ ret = q6asm_media_format_block_amrwbplus(prtd->audio_client,
+ &amrwb_cfg);
+ if (ret < 0) {
+ pr_err("%s: CMD Format block failed\n", __func__);
+ return ret;
+ }
+ break;
default:
return -EINVAL;
}
@@ -506,7 +527,7 @@
{
pr_debug("%s\n", __func__);
/* MP3 Block */
- compr->info.compr_cap.num_codecs = 1;
+ compr->info.compr_cap.num_codecs = 10;
compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
@@ -519,6 +540,8 @@
compr->info.compr_cap.codecs[5] = SND_AUDIOCODEC_DTS;
compr->info.compr_cap.codecs[6] = SND_AUDIOCODEC_DTS_LBR;
compr->info.compr_cap.codecs[7] = SND_AUDIOCODEC_DTS_PASS_THROUGH;
+ compr->info.compr_cap.codecs[8] = SND_AUDIOCODEC_AMRWB;
+ compr->info.compr_cap.codecs[9] = SND_AUDIOCODEC_AMRWBPLUS;
/* Add new codecs here */
}
@@ -790,7 +813,17 @@
pr_err("%s: Set IO mode failed\n", __func__);
return -ENOMEM;
}
-
+ /* Modifying kernel hardware params based on userspace config */
+ if (params_periods(params) > 0 &&
+ (params_periods(params) != runtime->hw.periods_max)) {
+ runtime->hw.periods_max = params_periods(params);
+ }
+ if (params_period_bytes(params) > 0 &&
+ (params_period_bytes(params) != runtime->hw.period_bytes_min)) {
+ runtime->hw.period_bytes_min = params_period_bytes(params);
+ }
+ runtime->hw.buffer_bytes_max =
+ runtime->hw.period_bytes_min * runtime->hw.periods_max;
ret = q6asm_audio_client_buf_alloc_contiguous(dir,
prtd->audio_client,
runtime->hw.period_bytes_min,
@@ -906,10 +939,17 @@
pr_debug("SND_AUDIOCODEC_DTS\n");
compr->codec = FORMAT_DTS_LBR;
break;
- default:
- pr_debug("FORMAT_LINEAR_PCM\n");
- compr->codec = FORMAT_LINEAR_PCM;
+ case SND_AUDIOCODEC_AMRWB:
+ pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWB\n");
+ compr->codec = FORMAT_AMRWB;
break;
+ case SND_AUDIOCODEC_AMRWBPLUS:
+ pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWBPLUS\n");
+ compr->codec = FORMAT_AMR_WB_PLUS;
+ break;
+ default:
+ pr_err("msm_compr_ioctl failed..unknown codec\n");
+ return -EFAULT;
}
return 0;
case SNDRV_PCM_IOCTL1_RESET:
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 011ff29..011912e 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -82,7 +82,7 @@
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 6,
+ .channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -173,7 +173,7 @@
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 6,
+ .channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
index c082ed7..2b3dd5f 100644
--- a/sound/soc/msm/msm-dai-q6-hdmi.c
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -111,6 +111,13 @@
dai_data->port_config.hdmi_multi_ch.channel_allocation =
channel_allocation;
break;
+ case 8:
+ channel_allocation = 0x1F;
+ hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_8,
+ channel_allocation, level_shift, down_mix);
+ dai_data->port_config.hdmi_multi_ch.channel_allocation =
+ channel_allocation;
+ break;
default:
dev_err(dai->dev, "invalid Channels = %u\n",
dai_data->channels);
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 89b709f..ee1ab79 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -465,6 +465,9 @@
dai_data->channels = params_channels(params);
switch (dai_data->channels) {
case 2:
+ case 4:
+ case 6:
+ case 8:
dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
break;
case 1:
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index a13d4da..10b8f7a 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -83,7 +83,7 @@
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
- .channels_max = 6,
+ .channels_max = 8,
.buffer_bytes_max = PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
.period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
.period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 374357d..5f0a20e 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1302,6 +1302,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -1317,6 +1320,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT_FM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT_FM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
@@ -1332,6 +1338,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -1347,6 +1356,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
@@ -1407,6 +1419,18 @@
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
@@ -2322,6 +2346,7 @@
{"MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"MI2S_RX", NULL, "MI2S_RX Audio Mixer"},
{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
@@ -2336,24 +2361,30 @@
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"INTERNAL_FM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"AFE_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"MultiMedia5 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+ {"MultiMedia5 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"MultiMedia5 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MM_UL1", NULL, "MultiMedia1 Mixer"},
{"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MM_UL2", NULL, "MultiMedia2 Mixer"},
@@ -2364,6 +2395,7 @@
{"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 76940ee..1aac158 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1526,6 +1526,14 @@
case FORMAT_DTS_LBR:
open.format = DTS_LBR;
break;
+ case FORMAT_AMRWB:
+ open.format = AMRWB_FS;
+ pr_debug("q6asm_open_write FORMAT_AMRWB");
+ break;
+ case FORMAT_AMR_WB_PLUS:
+ open.format = AMR_WB_PLUS;
+ pr_debug("q6asm_open_write FORMAT_AMR_WB_PLUS");
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
goto fail_cmd;
@@ -2372,7 +2380,56 @@
return -EINVAL;
}
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+ struct asm_amrwbplus_cfg *cfg)
+{
+ struct asm_stream_media_format_update fmt;
+ int rc = 0;
+ pr_debug("q6asm_media_format_block_amrwbplus");
+ pr_debug("%s:session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
+ __func__,
+ ac->session,
+ cfg->amr_band_mode,
+ cfg->amr_frame_fmt,
+ cfg->num_channels);
+
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+
+ fmt.format = AMR_WB_PLUS;
+ fmt.cfg_size = cfg->size_bytes;
+
+ fmt.write_cfg.amrwbplus_cfg.size_bytes = cfg->size_bytes;
+ fmt.write_cfg.amrwbplus_cfg.version = cfg->version;
+ fmt.write_cfg.amrwbplus_cfg.num_channels = cfg->num_channels;
+ fmt.write_cfg.amrwbplus_cfg.amr_band_mode = cfg->amr_band_mode;
+ fmt.write_cfg.amrwbplus_cfg.amr_dtx_mode = cfg->amr_dtx_mode;
+ fmt.write_cfg.amrwbplus_cfg.amr_frame_fmt = cfg->amr_frame_fmt;
+ fmt.write_cfg.amrwbplus_cfg.amr_lsf_idx = cfg->amr_lsf_idx;
+
+ pr_debug("%s: num_channels=%x amr_band_mode=%d amr_frame_fmt=%d\n",
+ __func__,
+ cfg->num_channels,
+ cfg->amr_band_mode,
+ cfg->amr_frame_fmt);
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s:Comamnd media format update failed..\n", __func__);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
int q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg)
{
@@ -2444,6 +2501,9 @@
case FORMAT_AMRWB:
fmt.format = AMRWB_FS;
break;
+ case FORMAT_AMR_WB_PLUS:
+ fmt.format = AMR_WB_PLUS;
+ break;
case FORMAT_AMRNB:
fmt.format = AMRNB_FS;
break;