diff options
| -rw-r--r-- | Documentation/devicetree/bindings/fb/mdss-edp.txt | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_edp.c | 67 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_edp.h | 5 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_edp_aux.c | 11 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/msm_mdss_io_8974.c | 13 |
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) { |
