Merge "ARM: dts: msm: optimize CPR configurations for msm8226-v1/v2 and msm8926"
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index 83237f9..7b70369 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -36,6 +36,10 @@
to include it more than once.
- qcom,s3-debounce The debounce delay for stage3 reset trigger in
secs. The values range from 0 to 128.
+- qcom,s3-src The source for stage 3 reset. It can be one of
+ "kpdpwr", "resin", "kpdpwr-or-resin" or
+ "kpdpwr-and-resin". The default value is
+ "kpdpwr-and-resin".
All the below properties are in the sub-node section (properties of the child
node).
@@ -92,6 +96,7 @@
qcom,pon-dbc-delay = <15625>;
qcom,system-reset;
qcom,s3-debounce = <32>;
+ qcom,s3-src = "resin";
qcom,pon_1 {
qcom,pon-type = <0>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 0558ee5..9dde30e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -39,6 +39,7 @@
qcom,pon-dbc-delay = <15625>;
qcom,system-reset;
qcom,s3-debounce = <32>;
+ qcom,s3-src = "kpdpwr-and-resin";
qcom,pon_1 {
qcom,pon-type = <0>;
@@ -50,10 +51,6 @@
qcom,pon-type = <1>;
qcom,pull-up = <1>;
linux,code = <114>;
- qcom,s1-timer = <6720>;
- qcom,s2-timer = <2000>;
- qcom,s2-type = <7>;
- qcom,support-reset = <1>;
};
qcom,pon_3 {
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index da6d018..3b4c881 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -766,3 +766,26 @@
&dsi_jdi_1080_vid {
qcom,cont-splash-enabled;
};
+
+&dsi_dual_jdi_video_0 {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <7>;
+ qcom,cont-splash-enabled;
+};
+
+&dsi_dual_jdi_video_1 {
+ qcom,cont-splash-enabled;
+};
+
+&dsi_dual_jdi_cmd_0 {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <7>;
+ qcom,cont-splash-enabled;
+};
+
+&dsi_dual_jdi_cmd_1 {
+ qcom,cont-splash-enabled;
+};
+
diff --git a/arch/arm/boot/dts/msm8974-mdss-panels.dtsi b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
index d405bf8..c11ef0a 100644
--- a/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,3 +15,7 @@
/include/ "dsi-panel-sharp-qhd-video.dtsi"
/include/ "dsi-panel-generic-720p-cmd.dtsi"
/include/ "dsi-panel-jdi-1080p-video.dtsi"
+/include/ "dsi-panel-jdi-dualmipi0-video.dtsi"
+/include/ "dsi-panel-jdi-dualmipi1-video.dtsi"
+/include/ "dsi-panel-jdi-dualmipi0-cmd.dtsi"
+/include/ "dsi-panel-jdi-dualmipi1-cmd.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 89f4af8..7f63234 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -175,6 +175,47 @@
vdda-supply = <&pm8941_l2>;
qcom,mdss-fb-map = <&mdss_fb0>;
qcom,mdss-mdp = <&mdss_mdp>;
+ qcom,platform-strength-ctrl = [ff 06];
+ qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
+ qcom,platform-regulator-settings = [07 09 03 00 20 00 01];
+ qcom,platform-lane-config = [00 00 00 00 00 00 00 01 97
+ 00 00 00 00 05 00 00 01 97
+ 00 00 00 00 0a 00 00 01 97
+ 00 00 00 00 0f 00 00 01 97
+ 00 c0 00 00 00 00 00 01 bb];
+ qcom,platform-supply-entry1 {
+ qcom,supply-name = "vdd";
+ qcom,supply-min-voltage = <3000000>;
+ qcom,supply-max-voltage = <3000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-pre-on-sleep = <0>;
+ qcom,supply-post-on-sleep = <20>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <0>;
+ };
+ qcom,platform-supply-entry2 {
+ qcom,supply-name = "vddio";
+ qcom,supply-min-voltage = <1800000>;
+ qcom,supply-max-voltage = <1800000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-pre-on-sleep = <0>;
+ qcom,supply-post-on-sleep = <20>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <0>;
+ };
+ qcom,platform-supply-entry3 {
+ qcom,supply-name = "vdda";
+ qcom,supply-min-voltage = <1200000>;
+ qcom,supply-max-voltage = <1200000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-pre-on-sleep = <0>;
+ qcom,supply-post-on-sleep = <0>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <0>;
+ };
};
mdss_hdmi_tx: qcom,hdmi_tx@fd922100 {
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e8d1627..acfbfc7 100755
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -1546,7 +1546,7 @@
},
};
-/* This table is for MSM8974Pro AC SDCC1 */
+/* For MSM8974Pro SDCC1 */
static struct clk_freq_tbl ftbl_gcc_sdcc1_apps_clk_ac[] = {
F( 144000, cxo, 16, 3, 25),
F( 400000, cxo, 12, 1, 4),
@@ -1559,11 +1559,7 @@
F_END
};
-/*
- * This table is for:
- * 1) SDCC[1-4] on MSM8974Pro AB, MSM8974 v2 and before
- * 2) SDCC[2-4] on MSM8974Pro AC
- */
+/* For SDCC1 on MSM8974 v2 and SDCC[2-4] on all MSM8974 */
static struct clk_freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
F( 144000, cxo, 16, 3, 25),
F( 400000, cxo, 12, 1, 4),
@@ -5790,11 +5786,9 @@
ce2_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
ce2_clk_src.freq_tbl = ftbl_gcc_ce2_pro_clk;
- if (cpu_is_msm8974pro_ac()) {
- sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
- sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
- sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_ac;
- }
+ sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
+ sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+ sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_ac;
vfe0_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
vfe0_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index f1904de..c81720e 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -228,6 +228,9 @@
static unsigned int msm_cpufreq_get_freq(unsigned int cpu)
{
+ if (is_clk && is_sync)
+ cpu = 0;
+
if (is_clk)
return clk_get_rate(cpu_clk[cpu]) / 1000;
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 6f9eb94..4f39838 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -139,7 +139,7 @@
unsigned int p;
for (p = 0; p < entity->num_pads; p++) {
- struct media_pad_desc pad;
+ struct media_pad_desc pad = {0};
media_device_kpad_to_upad(&entity->pads[p], &pad);
if (copy_to_user(&links.pads[p], &pad, sizeof(pad)))
return -EFAULT;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 4424c1f..d8b608437 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -125,6 +125,14 @@
"Turbo"
};
+static const char *const intra_refresh_modes[] = {
+ "None",
+ "Cyclic",
+ "Adaptive",
+ "Cyclic Adaptive",
+ "Random"
+};
+
enum msm_venc_ctrl_cluster {
MSM_VENC_CTRL_CLUSTER_QP = 1 << 0,
MSM_VENC_CTRL_CLUSTER_INTRA_PERIOD = 1 << 1,
@@ -566,6 +574,7 @@
(1 << V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC_ADAPTIVE) |
(1 << V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM)
),
+ .qmenu = intra_refresh_modes,
.cluster = MSM_VENC_CTRL_CLUSTER_INTRA_REFRESH,
},
{
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 99f6b5a..1839d07 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -4014,6 +4014,83 @@
return ret;
}
+static int qseecom_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret = 0;
+ struct qseecom_clk *qclk;
+ qclk = &qseecom.qsee;
+
+ if (qseecom.cumulative_mode != INACTIVE) {
+ ret = __qseecom_set_msm_bus_request(INACTIVE);
+ if (ret)
+ pr_err("Fail to scale down bus\n");
+ }
+ mutex_lock(&clk_access_lock);
+ if (qclk->clk_access_cnt) {
+ if (qclk->ce_clk != NULL)
+ clk_disable_unprepare(qclk->ce_clk);
+ if (qclk->ce_core_clk != NULL)
+ clk_disable_unprepare(qclk->ce_core_clk);
+ if (qclk->ce_bus_clk != NULL)
+ clk_disable_unprepare(qclk->ce_bus_clk);
+ }
+ mutex_unlock(&clk_access_lock);
+ return 0;
+}
+
+static int qseecom_resume(struct platform_device *pdev)
+{
+ int mode = 0;
+ int ret = 0;
+ struct qseecom_clk *qclk;
+ qclk = &qseecom.qsee;
+
+ if (qseecom.cumulative_mode >= HIGH)
+ mode = HIGH;
+ else
+ mode = qseecom.cumulative_mode;
+
+ if (qseecom.cumulative_mode != INACTIVE) {
+ ret = __qseecom_set_msm_bus_request(mode);
+ if (ret)
+ pr_err("Fail to scale down bus\n");
+ }
+
+ mutex_lock(&clk_access_lock);
+ if (qclk->clk_access_cnt) {
+
+ ret = clk_prepare_enable(qclk->ce_core_clk);
+ if (ret) {
+ pr_err("Unable to enable/prepare CE core clk\n");
+ qclk->clk_access_cnt = 0;
+ goto err;
+ }
+
+ ret = clk_prepare_enable(qclk->ce_clk);
+ if (ret) {
+ pr_err("Unable to enable/prepare CE iface clk\n");
+ qclk->clk_access_cnt = 0;
+ goto ce_clk_err;
+ }
+
+ ret = clk_prepare_enable(qclk->ce_bus_clk);
+ if (ret) {
+ pr_err("Unable to enable/prepare CE bus clk\n");
+ qclk->clk_access_cnt = 0;
+ goto ce_bus_clk_err;
+ }
+ }
+ mutex_unlock(&clk_access_lock);
+ return 0;
+
+ce_bus_clk_err:
+ clk_disable_unprepare(qclk->ce_clk);
+ce_clk_err:
+ clk_disable_unprepare(qclk->ce_core_clk);
+err:
+ mutex_unlock(&clk_access_lock);
+ return -EIO;
+}
static struct of_device_id qseecom_match[] = {
{
.compatible = "qcom,qseecom",
@@ -4024,6 +4101,8 @@
static struct platform_driver qseecom_plat_driver = {
.probe = qseecom_probe,
.remove = qseecom_remove,
+ .suspend = qseecom_suspend,
+ .resume = qseecom_resume,
.driver = {
.name = "qseecom",
.owner = THIS_MODULE,
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 507d02c..0ef2639 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -52,8 +52,15 @@
#define QPNP_PON_PS_HOLD_RST_CTL2(base) (base + 0x5B)
#define QPNP_PON_WD_RST_S2_CTL(base) (base + 0x56)
#define QPNP_PON_WD_RST_S2_CTL2(base) (base + 0x57)
-#define QPNP_PON_TRIGGER_EN(base) (base + 0x80)
+#define QPNP_PON_S3_SRC(base) (base + 0x74)
#define QPNP_PON_S3_DBC_CTL(base) (base + 0x75)
+#define QPNP_PON_TRIGGER_EN(base) (base + 0x80)
+
+#define QPNP_PON_S3_SRC_KPDPWR 0
+#define QPNP_PON_S3_SRC_RESIN 1
+#define QPNP_PON_S3_SRC_KPDPWR_OR_RESIN 2
+#define QPNP_PON_S3_SRC_KPDPWR_AND_RESIN 3
+#define QPNP_PON_S3_SRC_MASK 0x3
#define QPNP_PON_WARM_RESET_TFT BIT(4)
@@ -990,7 +997,17 @@
"Unable to config pon reset\n");
goto unreg_input_dev;
}
+ } else {
+ /* disable S2 reset */
+ rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
+ QPNP_PON_S2_CNTL_EN, 0);
+ if (rc) {
+ dev_err(&pon->spmi->dev,
+ "Unable to disable S2 reset\n");
+ goto unreg_input_dev;
+ }
}
+
rc = qpnp_pon_request_irqs(pon, cfg);
if (rc) {
dev_err(&pon->spmi->dev, "Unable to request-irq's\n");
@@ -1019,6 +1036,8 @@
u32 delay = 0, s3_debounce = 0;
int rc, sys_reset, index;
u8 pon_sts = 0;
+ const char *s3_src;
+ u8 s3_src_reg;
pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
GFP_KERNEL);
@@ -1119,6 +1138,32 @@
}
}
+ /* program s3 source */
+ s3_src = "kpdpwr-and-resin";
+ rc = of_property_read_string(pon->spmi->dev.of_node,
+ "qcom,s3-src", &s3_src);
+ if (rc && rc != -EINVAL) {
+ dev_err(&pon->spmi->dev, "Unable to read s3 timer\n");
+ return rc;
+ }
+
+ if (!strcmp(s3_src, "kpdpwr"))
+ s3_src_reg = QPNP_PON_S3_SRC_KPDPWR;
+ else if (!strcmp(s3_src, "resin"))
+ s3_src_reg = QPNP_PON_S3_SRC_RESIN;
+ else if (!strcmp(s3_src, "kpdpwr-or-resin"))
+ s3_src_reg = QPNP_PON_S3_SRC_KPDPWR_OR_RESIN;
+ else /* default combination */
+ s3_src_reg = QPNP_PON_S3_SRC_KPDPWR_AND_RESIN;
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_SRC(pon->base),
+ QPNP_PON_S3_SRC_MASK, s3_src_reg);
+ if (rc) {
+ dev_err(&spmi->dev,
+ "Unable to program s3 source\n");
+ return rc;
+ }
+
dev_set_drvdata(&spmi->dev, pon);
INIT_DELAYED_WORK(&pon->bark_work, bark_work_func);
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 44cc4a2..2efb973 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -316,20 +316,10 @@
/* disable DSI controller */
mdss_dsi_controller_cfg(0, pdata);
- mdss_dsi_clk_ctrl(ctrl_pdata, 0);
-
- ret = mdss_dsi_enable_bus_clocks(ctrl_pdata);
- if (ret) {
- pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
- ret);
- mdss_dsi_panel_power_on(pdata, 0);
- return ret;
- }
-
/* disable DSI phy */
- mdss_dsi_phy_enable(ctrl_pdata, 0);
+ mdss_dsi_phy_disable(ctrl_pdata);
- mdss_dsi_disable_bus_clocks(ctrl_pdata);
+ mdss_dsi_clk_ctrl(ctrl_pdata, 0);
ret = mdss_dsi_panel_power_on(pdata, 0);
if (ret) {
@@ -389,7 +379,7 @@
if (!pdata->panel_info.mipi.lp11_init)
mdss_dsi_panel_reset(pdata, 1);
- ret = mdss_dsi_enable_bus_clocks(ctrl_pdata);
+ ret = mdss_dsi_bus_clk_start(ctrl_pdata);
if (ret) {
pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
ret);
@@ -400,7 +390,7 @@
mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
mdss_dsi_phy_init(pdata);
- mdss_dsi_disable_bus_clocks(ctrl_pdata);
+ mdss_dsi_bus_clk_stop(ctrl_pdata);
mdss_dsi_clk_ctrl(ctrl_pdata, 1);
@@ -850,35 +840,39 @@
static struct device_node *mdss_dsi_find_panel_of_node(
struct platform_device *pdev, char *panel_cfg)
{
- int l;
- int ctrl_id = -1;
- char *panel_name;
+ int len, i;
+ int ctrl_id = pdev->id - 1;
+ char panel_name[MDSS_MAX_PANEL_LEN];
+ char ctrl_id_stream[3] = "0:";
+ char *stream = NULL, *pan = NULL;
struct device_node *dsi_pan_node = NULL, *mdss_node = NULL;
- l = strlen(panel_cfg);
- if (!l) {
+ len = strlen(panel_cfg);
+ if (!len) {
/* no panel cfg chg, parse dt */
pr_debug("%s:%d: no cmd line cfg present\n",
__func__, __LINE__);
- dsi_pan_node = mdss_dsi_pref_prim_panel(pdev);
+ goto end;
} else {
- if (panel_cfg[0] == '0') {
- pr_debug("%s:%d: DSI ctrl 1\n", __func__, __LINE__);
- ctrl_id = 0;
- } else if (panel_cfg[0] == '1') {
- pr_debug("%s:%d: DSI ctrl 2\n", __func__, __LINE__);
- ctrl_id = 1;
+ if (ctrl_id == 1)
+ strlcpy(ctrl_id_stream, "1:", 3);
+
+ stream = strnstr(panel_cfg, ctrl_id_stream, len);
+ if (!stream) {
+ pr_err("controller config is not present\n");
+ goto end;
}
- if ((pdev->id - 1) != ctrl_id) {
- pr_err("%s:%d:pdev_ID=[%d]\n",
- __func__, __LINE__, pdev->id);
- return NULL;
+ stream += 2;
+
+ pan = strnchr(stream, strlen(stream), ':');
+ if (!pan) {
+ strlcpy(panel_name, stream, MDSS_MAX_PANEL_LEN);
+ } else {
+ for (i = 0; (stream + i) < pan; i++)
+ panel_name[i] = *(stream + i);
+ panel_name[i] = 0;
}
- /*
- * skip first two chars '<dsi_ctrl_id>' and
- * ':' to get to the panel name
- */
- panel_name = panel_cfg + 2;
+
pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
panel_cfg, panel_name);
@@ -895,9 +889,12 @@
if (!dsi_pan_node) {
pr_err("%s: invalid pan node, selecting prim panel\n",
__func__);
- dsi_pan_node = mdss_dsi_pref_prim_panel(pdev);
+ goto end;
}
+ return dsi_pan_node;
}
+end:
+ dsi_pan_node = mdss_dsi_pref_prim_panel(pdev);
return dsi_pan_node;
}
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index b89a935..2c9c37d 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -227,6 +227,8 @@
#define DSI_EV_MDP_FIFO_UNDERFLOW 0x0002
#define DSI_EV_MDP_BUSY_RELEASE 0x80000000
+#define DSI_FLAG_CLOCK_MASTER 0x80000000
+
struct mdss_dsi_ctrl_pdata {
int ndx; /* panel_num */
int (*on) (struct mdss_panel_data *pdata);
@@ -238,6 +240,8 @@
unsigned char *ctrl_base;
int reg_size;
u32 clk_cnt;
+ int clk_cnt_sub;
+ u32 flags;
struct clk *mdp_core_clk;
struct clk *ahb_clk;
struct clk *axi_clk;
@@ -308,13 +312,20 @@
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
void mdss_dsi_ack_err_status(struct mdss_dsi_ctrl_pdata *ctrl);
-int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
+void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
+int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl);
+int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl,
int enable);
void mdss_dsi_controller_cfg(int enable,
struct mdss_panel_data *pdata);
void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
+struct mdss_dsi_ctrl_pdata *mdss_dsi_ctrl_slave(
+ struct mdss_dsi_ctrl_pdata *ctrl);
+
irqreturn_t mdss_dsi_isr(int irq, void *ptr);
void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
@@ -327,7 +338,7 @@
int mdss_dsi_enable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
void mdss_dsi_disable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable);
-void mdss_dsi_phy_enable(struct mdss_dsi_ctrl_pdata *ctrl, int on);
+void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_phy_init(struct mdss_panel_data *pdata);
void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base);
void mdss_dsi_cmd_test_pattern(struct mdss_dsi_ctrl_pdata *ctrl);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index bd156fc..b4478ac 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -92,6 +92,10 @@
ctrl_list[ctrl->ndx] = ctrl; /* keep it */
+ if (ctrl->shared_pdata.broadcast_enable)
+ if (ctrl->ndx == DSI_CTRL_1)
+ ctrl->flags |= DSI_FLAG_CLOCK_MASTER;
+
if (mdss_register_irq(ctrl->dsi_hw))
pr_err("%s: mdss_register_irq failed.\n", __func__);
@@ -117,6 +121,22 @@
}
}
+struct mdss_dsi_ctrl_pdata *mdss_dsi_ctrl_slave(
+ struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ int ndx;
+ struct mdss_dsi_ctrl_pdata *sctrl = NULL;
+
+ /* only two controllers */
+ ndx = ctrl->ndx;
+ ndx += 1;
+ ndx %= DSI_CTRL_MAX;
+ sctrl = ctrl_list[ndx];
+
+ return sctrl;
+
+}
+
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
{
if (enable == 0) {
@@ -1460,10 +1480,10 @@
MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0);
}
- pr_debug("%s: isr=%x", __func__, isr);
+ pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);
if (isr & DSI_INTR_ERROR) {
- pr_err("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
+ pr_err("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);
mdss_dsi_error(ctrl);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 088472f..eeb697b 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1044,6 +1044,14 @@
return rc;
}
+/**
+ * mdss_mdp_footswitch_ctrl_splash() - clocks handoff for cont. splash screen
+ * @on: 1 to start handoff, 0 to complete the handoff after first frame update
+ *
+ * MDSS Clocks and GDSC are already on during continous splash screen, but
+ * increasing ref count will keep clocks from being turned off until handoff
+ * has properly happend after frame update.
+ */
void mdss_mdp_footswitch_ctrl_splash(int on)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -1052,9 +1060,11 @@
pr_debug("Enable MDP FS for splash.\n");
mdata->handoff_pending = true;
regulator_enable(mdata->fs);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdss_hw_init(mdata);
} else {
pr_debug("Disable MDP FS for splash.\n");
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
regulator_disable(mdata->fs);
mdata->handoff_pending = false;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 1a4885c..18b6338 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1085,8 +1085,21 @@
return 0;
}
+static inline struct mdss_mdp_ctl *mdss_mdp_get_split_ctl(
+ struct mdss_mdp_ctl *ctl)
+{
+ if (ctl && ctl->mixer_right && (ctl->mixer_right->ctl != ctl))
+ return ctl->mixer_right->ctl;
+
+ return NULL;
+}
+
int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff)
{
+ struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+ if (sctl)
+ sctl->panel_data->panel_info.cont_splash_enabled = 0;
+
switch (ctl->panel_data->panel_info.type) {
case MIPI_VIDEO_PANEL:
case EDP_PANEL:
@@ -1111,15 +1124,6 @@
return 0;
}
-static inline struct mdss_mdp_ctl *mdss_mdp_get_split_ctl(
- struct mdss_mdp_ctl *ctl)
-{
- if (ctl && ctl->mixer_right && (ctl->mixer_right->ctl != ctl))
- return ctl->mixer_right->ctl;
-
- return NULL;
-}
-
static int mdss_mdp_ctl_fbc_enable(int enable,
struct mdss_mdp_mixer *mixer, struct mdss_panel_info *pdata)
{
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index ce0b757..79bdee2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -435,7 +435,6 @@
pdata->panel_info.cont_splash_enabled = 0;
mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 7304694..55a4a4d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -736,7 +736,6 @@
free_bootmem_late(mdp5_data->splash_mem_addr,
mdp5_data->splash_mem_size);
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 910f405..baea509 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -2545,14 +2545,9 @@
int mdss_panel_register_done(struct mdss_panel_data *pdata)
{
- /*
- * Clocks are already on if continuous splash is enabled,
- * increasing ref_cnt to help balance clocks once done.
- */
- if (pdata->panel_info.cont_splash_enabled) {
+ if (pdata->panel_info.cont_splash_enabled)
mdss_mdp_footswitch_ctrl_splash(1);
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- }
+
return 0;
}
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 5d4610c..6ebcdf6 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -247,10 +247,12 @@
return 0;
}
-int mdss_dsi_enable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
int rc = 0;
+ pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);
+
rc = clk_prepare_enable(ctrl_pdata->mdp_core_clk);
if (rc) {
pr_err("%s: failed to enable mdp_core_clock. rc=%d\n",
@@ -277,14 +279,14 @@
return rc;
}
-void mdss_dsi_disable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
clk_disable_unprepare(ctrl_pdata->axi_clk);
clk_disable_unprepare(ctrl_pdata->ahb_clk);
clk_disable_unprepare(ctrl_pdata->mdp_core_clk);
}
-static int mdss_dsi_clk_prepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static int mdss_dsi_link_clk_prepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
int rc = 0;
@@ -316,7 +318,7 @@
return rc;
}
-static void mdss_dsi_clk_unprepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static void mdss_dsi_link_clk_unprepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
if (!ctrl_pdata) {
pr_err("%s: Invalid input data\n", __func__);
@@ -328,7 +330,7 @@
clk_unprepare(ctrl_pdata->esc_clk);
}
-static int mdss_dsi_clk_set_rate(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static int mdss_dsi_link_clk_set_rate(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
u32 esc_clk_rate = 19200000;
int rc = 0;
@@ -369,7 +371,7 @@
return rc;
}
-static int mdss_dsi_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static int mdss_dsi_link_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
int rc = 0;
@@ -378,6 +380,8 @@
return -EINVAL;
}
+ pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);
+
if (ctrl_pdata->mdss_dsi_clk_on) {
pr_info("%s: mdss_dsi_clks already ON\n", __func__);
return 0;
@@ -413,13 +417,15 @@
return rc;
}
-static void mdss_dsi_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static void mdss_dsi_link_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
if (!ctrl_pdata) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);
+
if (ctrl_pdata->mdss_dsi_clk_on == 0) {
pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
return;
@@ -432,62 +438,110 @@
ctrl_pdata->mdss_dsi_clk_on = 0;
}
-int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl)
{
int rc = 0;
- mutex_lock(&ctrl->mutex);
+ rc = mdss_dsi_link_clk_set_rate(ctrl);
+ if (rc) {
+ pr_err("%s: failed to set clk rates. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+
+ rc = mdss_dsi_link_clk_prepare(ctrl);
+ if (rc) {
+ pr_err("%s: failed to prepare clks. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+
+ rc = mdss_dsi_link_clk_enable(ctrl);
+ if (rc) {
+ pr_err("%s: failed to enable clks. rc=%d\n",
+ __func__, rc);
+ mdss_dsi_link_clk_unprepare(ctrl);
+ goto error;
+ }
+
+error:
+ return rc;
+}
+
+void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ mdss_dsi_link_clk_disable(ctrl);
+ mdss_dsi_link_clk_unprepare(ctrl);
+}
+
+static void mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+{
+ int changed = 0;
+
if (enable) {
- if (ctrl->clk_cnt == 0) {
- rc = mdss_dsi_enable_bus_clocks(ctrl);
- if (rc) {
- pr_err("%s: failed to enable bus clks. rc=%d\n",
- __func__, rc);
- goto error;
- }
-
- rc = mdss_dsi_clk_set_rate(ctrl);
- if (rc) {
- pr_err("%s: failed to set clk rates. rc=%d\n",
- __func__, rc);
- mdss_dsi_disable_bus_clocks(ctrl);
- goto error;
- }
-
- rc = mdss_dsi_clk_prepare(ctrl);
- if (rc) {
- pr_err("%s: failed to prepare clks. rc=%d\n",
- __func__, rc);
- mdss_dsi_disable_bus_clocks(ctrl);
- goto error;
- }
-
- rc = mdss_dsi_clk_enable(ctrl);
- if (rc) {
- pr_err("%s: failed to enable clks. rc=%d\n",
- __func__, rc);
- mdss_dsi_clk_unprepare(ctrl);
- mdss_dsi_disable_bus_clocks(ctrl);
- goto error;
- }
+ if (ctrl->clk_cnt_sub == 0)
+ changed++;
+ ctrl->clk_cnt_sub++;
+ } else {
+ if (ctrl->clk_cnt_sub) {
+ ctrl->clk_cnt_sub--;
+ if (ctrl->clk_cnt_sub == 0)
+ changed++;
+ } else {
+ pr_debug("%s: Can not be turned off\n", __func__);
}
+ }
+
+ pr_debug("%s: ndx=%d clk_cnt_sub=%d changed=%d enable=%d\n",
+ __func__, ctrl->ndx, ctrl->clk_cnt_sub, changed, enable);
+ if (changed) {
+ if (enable) {
+ if (mdss_dsi_bus_clk_start(ctrl) == 0)
+ mdss_dsi_link_clk_start(ctrl);
+ } else {
+ mdss_dsi_link_clk_stop(ctrl);
+ mdss_dsi_bus_clk_stop(ctrl);
+ }
+ }
+}
+
+static DEFINE_MUTEX(dsi_clk_lock); /* per system */
+
+void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+{
+ int changed = 0;
+ struct mdss_dsi_ctrl_pdata *sctrl = NULL;
+
+ mutex_lock(&dsi_clk_lock);
+ if (enable) {
+ if (ctrl->clk_cnt == 0)
+ changed++;
ctrl->clk_cnt++;
} else {
if (ctrl->clk_cnt) {
ctrl->clk_cnt--;
- if (ctrl->clk_cnt == 0) {
- mdss_dsi_clk_disable(ctrl);
- mdss_dsi_clk_unprepare(ctrl);
- mdss_dsi_disable_bus_clocks(ctrl);
- }
+ if (ctrl->clk_cnt == 0)
+ changed++;
+ } else {
+ pr_debug("%s: Can not be turned off\n", __func__);
}
}
- pr_debug("%s: ctrl ndx=%d enabled=%d clk_cnt=%d\n",
- __func__, ctrl->ndx, enable, ctrl->clk_cnt);
-error:
- mutex_unlock(&ctrl->mutex);
- return rc;
+ pr_debug("%s: ndx=%d clk_cnt=%d changed=%d enable=%d\n",
+ __func__, ctrl->ndx, ctrl->clk_cnt, changed, enable);
+ if (ctrl->flags & DSI_FLAG_CLOCK_MASTER)
+ sctrl = mdss_dsi_ctrl_slave(ctrl);
+
+ if (changed) {
+ if (enable && sctrl)
+ mdss_dsi_clk_ctrl_sub(sctrl, enable);
+
+ mdss_dsi_clk_ctrl_sub(ctrl, enable);
+
+ if (!enable && sctrl)
+ mdss_dsi_clk_ctrl_sub(sctrl, enable);
+ }
+ mutex_unlock(&dsi_clk_lock);
}
void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base)
@@ -502,7 +556,7 @@
wmb();
}
-void mdss_dsi_phy_enable(struct mdss_dsi_ctrl_pdata *ctrl, int on)
+void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl)
{
static struct mdss_dsi_ctrl_pdata *left_ctrl;
@@ -511,59 +565,28 @@
return;
}
- if (!left_ctrl
- && ctrl->shared_pdata.broadcast_enable)
- if ((ctrl->panel_data).panel_info.pdest
- == DISPLAY_1)
- left_ctrl = ctrl;
+ if (left_ctrl &&
+ (ctrl->panel_data.panel_info.pdest == DISPLAY_1))
+ return;
- if (on) {
- MIPI_OUTP(ctrl->ctrl_base + 0x03cc, 0x03);
- wmb();
- usleep(100);
- MIPI_OUTP(ctrl->ctrl_base + 0x0220, 0x006);
- wmb();
- usleep(100);
- MIPI_OUTP(ctrl->ctrl_base + 0x0268, 0x001);
- wmb();
- usleep(100);
- MIPI_OUTP(ctrl->ctrl_base + 0x0268, 0x000);
- wmb();
- usleep(100);
- MIPI_OUTP(ctrl->ctrl_base + 0x0220, 0x007);
- wmb();
- MIPI_OUTP(ctrl->ctrl_base + 0x03cc, 0x01);
- wmb();
- usleep(100);
-
- /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x07e);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x06e);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x06c);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x064);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x065);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x075);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x077);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x07f);
- wmb();
- } else {
- if (left_ctrl &&
+ if (left_ctrl &&
(ctrl->panel_data.panel_info.pdest
- == DISPLAY_1))
- return;
-
- if (left_ctrl &&
- (ctrl->panel_data.panel_info.pdest
- == DISPLAY_2)) {
- MIPI_OUTP(left_ctrl->ctrl_base + 0x0220, 0x006);
- MIPI_OUTP(left_ctrl->ctrl_base + 0x0470, 0x000);
- MIPI_OUTP(left_ctrl->ctrl_base + 0x0598, 0x000);
- }
- MIPI_OUTP(ctrl->ctrl_base + 0x0220, 0x006);
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x000);
- MIPI_OUTP(ctrl->ctrl_base + 0x0598, 0x000);
- wmb();
+ ==
+ DISPLAY_2)) {
+ MIPI_OUTP(left_ctrl->ctrl_base + 0x0470,
+ 0x000);
+ MIPI_OUTP(left_ctrl->ctrl_base + 0x0598,
+ 0x000);
}
+
+ MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x000);
+ MIPI_OUTP(ctrl->ctrl_base + 0x0598, 0x000);
+
+ /*
+ * Wait for the registers writes to complete in order to
+ * ensure that the phy is completely disabled
+ */
+ wmb();
}
void mdss_dsi_phy_init(struct mdss_panel_data *pdata)