summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-edp.txt2
-rw-r--r--drivers/video/fbdev/msm/mdss_edp.c67
-rw-r--r--drivers/video/fbdev/msm/mdss_edp.h5
-rw-r--r--drivers/video/fbdev/msm/mdss_edp_aux.c11
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c13
5 files changed, 86 insertions, 12 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-edp.txt b/Documentation/devicetree/bindings/fb/mdss-edp.txt
index f5996bceeafc..8b9940f3f6cf 100644
--- a/Documentation/devicetree/bindings/fb/mdss-edp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-edp.txt
@@ -15,6 +15,7 @@ Required properties
- vdda-supply : Phandle for vdd regulator device node.
- gpio-panel-en : GPIO for supplying power to panel and backlight
driver.
+- gpio-lvl-en : GPIO to enable HPD be received by host.
- status : A string that has to be set to "okay/ok" to enable
the driver. By default this property will be set to
"disable". Will be set to "ok/okay" status for
@@ -41,6 +42,7 @@ Example:
reg-names = "edp_base", "mmss_cc_base";
vdda-supply = <&pm8941_l12>;
gpio-panel-en = <&msmgpio 58 0>;
+ gpio-lvl-en = <&msmgpio 91 0>;
qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
qcom,panel-pwm-period = <53>;
status = "disable";
diff --git a/drivers/video/fbdev/msm/mdss_edp.c b/drivers/video/fbdev/msm/mdss_edp.c
index 8e1ebefc83fd..af553c621834 100644
--- a/drivers/video/fbdev/msm/mdss_edp.c
+++ b/drivers/video/fbdev/msm/mdss_edp.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
@@ -153,6 +153,41 @@ gpio_err:
return -ENODEV;
}
+static int mdss_edp_gpio_lvl_en(struct mdss_edp_drv_pdata *edp_drv)
+{
+ int ret = 0;
+
+ edp_drv->gpio_lvl_en = of_get_named_gpio(edp_drv->pdev->dev.of_node,
+ "gpio-lvl-en", 0);
+ if (!gpio_is_valid(edp_drv->gpio_lvl_en)) {
+ pr_err("%s: gpio_lvl_en=%d not specified\n", __func__,
+ edp_drv->gpio_lvl_en);
+ ret = -ENODEV;
+ goto gpio_err;
+ }
+
+ ret = gpio_request(edp_drv->gpio_lvl_en, "lvl_enable");
+ if (ret) {
+ pr_err("%s: Request reset gpio_lvl_en failed, ret=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = gpio_direction_output(edp_drv->gpio_lvl_en, 1);
+ if (ret) {
+ pr_err("%s: Set direction for gpio_lvl_en failed, ret=%d\n",
+ __func__, ret);
+ goto gpio_free;
+ }
+
+ return ret;
+
+gpio_free:
+ gpio_free(edp_drv->gpio_lvl_en);
+gpio_err:
+ return ret;
+}
+
static int mdss_edp_pwm_config(struct mdss_edp_drv_pdata *edp_drv)
{
int ret = 0;
@@ -578,6 +613,8 @@ int mdss_edp_on(struct mdss_panel_data *pdata)
mdss_edp_timing_cfg(edp_drv);
gpio_set_value(edp_drv->gpio_panel_en, 1);
+ if (gpio_is_valid(edp_drv->gpio_lvl_en))
+ gpio_set_value(edp_drv->gpio_lvl_en, 1);
INIT_COMPLETION(edp_drv->idle_comp);
mdss_edp_mainlink_ctrl(edp_drv, 1);
@@ -587,6 +624,11 @@ int mdss_edp_on(struct mdss_panel_data *pdata)
mdss_edp_irq_enable(edp_drv);
+ if (edp_drv->delay_link_train) {
+ mdss_edp_link_train(edp_drv);
+ edp_drv->delay_link_train = 0;
+ }
+
mdss_edp_wait4train(edp_drv);
edp_drv->cont_splash = 0;
@@ -626,6 +668,8 @@ int mdss_edp_off(struct mdss_panel_data *pdata)
mdss_edp_irq_disable(edp_drv);
gpio_set_value(edp_drv->gpio_panel_en, 0);
+ if (gpio_is_valid(edp_drv->gpio_lvl_en))
+ gpio_set_value(edp_drv->gpio_lvl_en, 0);
if (edp_drv->bl_pwm != NULL)
pwm_disable(edp_drv->bl_pwm);
edp_drv->is_pwm_enabled = 0;
@@ -720,6 +764,8 @@ static int mdss_edp_remove(struct platform_device *pdev)
edp_drv = platform_get_drvdata(pdev);
gpio_free(edp_drv->gpio_panel_en);
+ if (gpio_is_valid(edp_drv->gpio_lvl_en))
+ gpio_free(edp_drv->gpio_lvl_en);
mdss_edp_regulator_off(edp_drv);
iounmap(edp_drv->base);
iounmap(edp_drv->mmss_cc_base);
@@ -756,7 +802,7 @@ static int mdss_edp_device_register(struct mdss_edp_drv_pdata *edp_drv)
return ret;
}
- pr_debug("%s: eDP initialized\n", __func__);
+ pr_info("%s: eDP initialized\n", __func__);
return 0;
}
@@ -829,6 +875,11 @@ static void mdss_edp_do_link_train(struct mdss_edp_drv_pdata *ep)
if (ep->cont_splash)
return;
+ if (!ep->inited) {
+ ep->delay_link_train++;
+ return;
+ }
+
mdss_edp_link_train(ep);
}
@@ -1094,6 +1145,10 @@ static int mdss_edp_probe(struct platform_device *pdev)
if (ret)
goto edp_clk_deinit;
+ ret = mdss_edp_gpio_lvl_en(edp_drv);
+ if (ret)
+ pr_err("%s: No gpio_lvl_en detected\n", __func__);
+
ret = mdss_edp_pwm_config(edp_drv);
if (ret)
goto edp_free_gpio_panel_en;
@@ -1107,8 +1162,6 @@ static int mdss_edp_probe(struct platform_device *pdev)
edp_drv->cont_splash = of_property_read_bool(pdev->dev.of_node,
"qcom,cont-splash-enabled");
- pr_debug("%s:cont_splash=%d\n", __func__, edp_drv->cont_splash);
-
/* only need aux and ahb clock for aux channel */
mdss_edp_prepare_aux_clocks(edp_drv);
mdss_edp_aux_clk_enable(edp_drv);
@@ -1144,13 +1197,17 @@ static int mdss_edp_probe(struct platform_device *pdev)
mdss_edp_device_register(edp_drv);
- pr_info("%s: done\n", __func__);
+ edp_drv->inited = true;
+
+ pr_debug("%s: done\n", __func__);
return 0;
edp_free_gpio_panel_en:
gpio_free(edp_drv->gpio_panel_en);
+ if (gpio_is_valid(edp_drv->gpio_lvl_en))
+ gpio_free(edp_drv->gpio_lvl_en);
edp_clk_deinit:
mdss_edp_clk_deinit(edp_drv);
mdss_edp_regulator_off(edp_drv);
diff --git a/drivers/video/fbdev/msm/mdss_edp.h b/drivers/video/fbdev/msm/mdss_edp.h
index 78563b556265..7ce525c4e191 100644
--- a/drivers/video/fbdev/msm/mdss_edp.h
+++ b/drivers/video/fbdev/msm/mdss_edp.h
@@ -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
@@ -262,6 +262,8 @@ struct mdss_edp_drv_pdata {
struct mutex emutex;
int clk_cnt;
int cont_splash;
+ bool inited;
+ int delay_link_train;
/* edp specific */
unsigned char *base;
@@ -298,6 +300,7 @@ struct mdss_edp_drv_pdata {
/* gpios */
int gpio_panel_en;
+ int gpio_lvl_en;
/* backlight */
struct pwm_device *bl_pwm;
diff --git a/drivers/video/fbdev/msm/mdss_edp_aux.c b/drivers/video/fbdev/msm/mdss_edp_aux.c
index 8df24ae1930f..63b55a6da846 100644
--- a/drivers/video/fbdev/msm/mdss_edp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_edp_aux.c
@@ -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
@@ -1201,7 +1201,6 @@ static int edp_aux_link_train(struct mdss_edp_drv_pdata *ep)
{
int ret = 0;
- pr_debug("%s", __func__);
ret = edp_aux_chan_ready(ep);
if (ret == 0) {
pr_err("%s: LINK Train failed: aux chan NOT ready\n", __func__);
@@ -1229,13 +1228,13 @@ train_start:
if (edp_link_rate_down_shift(ep) == 0) {
goto train_start;
} else {
- pr_err("%s: Training 1 failed", __func__);
+ pr_err("%s: Training 1 failed\n", __func__);
ret = -1;
goto clear;
}
}
- pr_debug("%s: Training 1 completed successfully", __func__);
+ pr_debug("%s: Training 1 completed successfully\n", __func__);
mdss_edp_state_ctrl(ep, 0);
edp_clear_training_pattern(ep);
@@ -1244,13 +1243,13 @@ train_start:
if (edp_link_rate_down_shift(ep) == 0) {
goto train_start;
} else {
- pr_err("%s: Training 2 failed", __func__);
+ pr_err("%s: Training 2 failed\n", __func__);
ret = -1;
goto clear;
}
}
- pr_debug("%s: Training 2 completed successfully", __func__);
+ pr_debug("%s: Training 2 completed successfully\n", __func__);
mdss_edp_state_ctrl(ep, ST_SEND_VIDEO);
clear:
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index ffee82328be2..8b5b2062762f 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -1492,6 +1492,17 @@ void mdss_edp_aux_clk_disable(struct mdss_edp_drv_pdata *edp_drv)
clk_disable(edp_drv->mdp_core_clk);
}
+static void mdss_edp_clk_set_rate(struct mdss_edp_drv_pdata *edp_drv)
+{
+ if (clk_set_rate(edp_drv->link_clk, edp_drv->link_rate * 27000000) < 0)
+ pr_err("%s: link_clk - clk_set_rate failed\n",
+ __func__);
+
+ if (clk_set_rate(edp_drv->pixel_clk, edp_drv->pixel_rate) < 0)
+ pr_err("%s: pixel_clk - clk_set_rate failed\n",
+ __func__);
+}
+
int mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
{
int ret;
@@ -1615,6 +1626,8 @@ int mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
{
int ret;
+ mdss_edp_clk_set_rate(edp_drv);
+
/* ahb clock should be prepared first */
ret = clk_prepare(edp_drv->ahb_clk);
if (ret) {