diff options
| author | Padmanabhan Komanduru <pkomandu@codeaurora.org> | 2015-04-22 20:14:49 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:42:13 -0700 |
| commit | 411d694bc12b7bab3f855a831bd31bba27525ab7 (patch) | |
| tree | 57e217756f9e3f1e63a4ddf24f0b9288bbd768ba | |
| parent | 50fd1860673ca4d3c5af2a5c05f467da0dd0064a (diff) | |
msm: mdss: refactor MDSS DSI driver
Current DSI driver implementation treats the two DSI controllers
as separate devices. However, some use cases might require the
two DSI devices to be aware of the global configuration of the
display interfaces. For instance, the panel/board configuration
might require both the DSI controllers to work in tandem and
drive a split DSI panel or else drive two different panels
independently. Add a root DSI node in MDSS dtsi and the two
DSI controller nodes as the child nodes. Refactor the DSI
panel related dtsi files and DSI drivers to support this new
design. The DSI root node contains the global information needed
for the DSI controllers like the DSI h/w configuration needed to
drive the panel(s), the DSI register space ranges etc.
Change-Id: I3661adf9ce2ecbef83ae3267e4aae18e0f0c8d04
Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
Signed-off-by: Siddhartha Agrawal <agrawals@codeaurora.org>
[cip@codeaurora.org: Removed .dtsi file updates]
Signed-off-by: Clarence Ip <cip@codeaurora.org>
| -rw-r--r-- | Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt | 4 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/fb/mdss-dsi.txt (renamed from Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt) | 216 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 499 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 70 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 138 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/msm_mdss_io_8974.c | 78 |
6 files changed, 580 insertions, 425 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index a3d4601dcf03..8c359938ac6d 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -85,9 +85,6 @@ Optional properties: screen using the qcom,memblock-reserve binding for the framebuffer device attached to the panel. - qcom,cmd-sync-wait-broadcast: Boolean used to broadcast dcs command to panels. -- qcom,cmd-sync-wait-trigger: Boolean used to identify the which panel in a dual-dsi - configuration will be used to trigger the DCS commands. - This flag should be set only for one of the two panels. - qcom,mdss-dsi-fbc-enable: Boolean used to enable frame buffer compression mode. - qcom,mdss-dsi-fbc-slice-height: Slice height(in lines) of compressed block. Expressed as power of 2. To set as 128 lines, @@ -429,7 +426,6 @@ Example: qcom,mdss-dsi-pixel-packing = <0>; qcom,mdss-dsi-panel-destination = "display_1"; qcom,cmd-sync-wait-broadcast; - qcom,cmd-sync-wait-trigger; qcom,mdss-dsi-fbc-enable; qcom,mdss-dsi-fbc-slice-height = <5>; qcom,mdss-dsi-fbc-2d-pred-mode; diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi.txt index 51d92fae781d..2c520a7f72e0 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi.txt @@ -1,7 +1,18 @@ -Qualcomm mdss-dsi-ctrl +Qualcomm mdss-dsi -mdss-dsi-ctrl is a dsi controller device which supports host controllers that -are compatable with MIPI display serial interface specification. +mdss-dsi is the master DSI device which supports multiple DSI host controllers that +are compatible with MIPI display serial interface specification. + +Required properties: +- compatible: Must be "qcom,mdss-dsi" +- hw-config: Specifies the DSI host setup configuration + "hw-config" = "single_dsi" + "hw-config" = "dual_dsi" + "hw-config" = "split_dsi" +- ranges: The standard property which specifies the child address + space, parent address space and the length. + +mdss-dsi-ctrl is a dsi controller device which is treated as a subnode of the mdss-dsi device. Required properties: - compatible: Must be "qcom,mdss-dsi-ctrl" @@ -79,98 +90,115 @@ Optional properties: "lane_map_3210" = <3 2 1 0> Example: - mdss_dsi0: qcom,mdss_dsi@fd922800 { - compatible = "qcom,mdss-dsi-ctrl"; - label = "MDSS DSI CTRL->0"; - cell-index = <0>; - reg = <0xfd922800 0x1f8>, - <0xfd922b00 0x2b0>, - <0xfd998780 0x30>, - <0xfd828000 0x108>; - reg-names = "dsi_ctrl", "dsi_phy", "dsi_phy_regulator", "mmss_misc_phys"; - vdd-supply = <&pm8226_l15>; - vddio-supply = <&pm8226_l8>; - vdda-supply = <&pm8226_l4>; - vcca-supply = <&pm8226_l28>; - qcom,dsi-pref-prim-pan = <&dsi_tosh_720_vid>; - qcom,platform-strength-ctrl = [ff 06]; - qcom,platform-bist-ctrl = [00 00 b1 ff 00 00]; - qcom,regulator-ldo-mode; - 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,mmss-ulp-clamp-ctrl-offset = <0x20>; - qcom,mmss-phyreset-ctrl-offset = <0x24>; - qcom,mdss-fb-map = <&mdss_fb0>; - qcom,mdss-mdp = <&mdss_mdp>; - pinctrl-names = "mdss_default", "mdss_sleep"; - pinctrl-0 = <&mdss_dsi_active>; - pinctrl-1 = <&mdss_dsi_suspend>; - qcom,platform-reset-gpio = <&msmgpio 25 1>; - qcom,platform-te-gpio = <&msmgpio 24 0>; - qcom,platform-enable-gpio = <&msmgpio 58 1>; - qcom,platform-bklight-en-gpio = <&msmgpio 86 0>; - qcom,platform-mode-gpio = <&msmgpio 7 0>; - qcom,dsi-irq-line; - qcom,timing-db-mode; - qcom,dsi-clk-ln-recovery; - qcom,lane-map = "lane_map_3012"; - - qcom,core-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,core-supply-entry@0 { - reg = <0>; - qcom,supply-name = "gdsc"; - qcom,supply-min-voltage = <0>; - qcom,supply-max-voltage = <0>; - qcom,supply-enable-load = <0>; - qcom,supply-disable-load = <0>; - 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_dsi: qcom,mdss_dsi@0 { + compatible = "qcom,mdss-dsi"; + hw-config = "single_dsi"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x1a98000 0x1a98000 0x25c + 0x1a98500 0x1a98500 0x280 + 0x1a98780 0x1a98780 0x30 + 0x193e000 0x193e000 0x30>; + + mdss_dsi0: mdss_dsi_ctrl0@fd922800 { + compatible = "qcom,mdss-dsi-ctrl"; + label = "MDSS DSI CTRL->0"; + cell-index = <0>; + reg = <0xfd922800 0x1f8>, + <0xfd922b00 0x2b0>, + <0xfd998780 0x30>, + <0xfd828000 0x108>; + reg-names = "dsi_ctrl", "dsi_phy", + "dsi_phy_regulator", "mmss_misc_phys"; + + vdd-supply = <&pm8226_l15>; + vddio-supply = <&pm8226_l8>; + vdda-supply = <&pm8226_l4>; + vcca-supply = <&pm8226_l28>; + qcom,mdss-fb-map = <&mdss_fb0>; + qcom,mdss-mdp = <&mdss_mdp>; + + qcom,dsi-pref-prim-pan = <&dsi_tosh_720_vid>; + + 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,mmss-ulp-clamp-ctrl-offset = <0x20>; + qcom,mmss-phyreset-ctrl-offset = <0x24>; + qcom,regulator-ldo-mode; + + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_dsi_active>; + pinctrl-1 = <&mdss_dsi_suspend>; + qcom,platform-reset-gpio = <&msmgpio 25 1>; + qcom,platform-te-gpio = <&msmgpio 24 0>; + qcom,platform-enable-gpio = <&msmgpio 58 1>; + qcom,platform-bklight-en-gpio = <&msmgpio 86 0>; + qcom,platform-mode-gpio = <&msmgpio 7 0>; + qcom,dsi-irq-line; + qcom,timing-db-mode; + qcom,dsi-clk-ln-recovery; + qcom,lane-map = "lane_map_3012"; + + qcom,core-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,core-supply-entry@0 { + reg = <0>; + qcom,supply-name = "gdsc"; + qcom,supply-min-voltage = <0>; + qcom,supply-max-voltage = <0>; + qcom,supply-enable-load = <0>; + qcom,supply-disable-load = <0>; + qcom,supply-pre-on-sleep = <0>; + qcom,supply-post-on-sleep = <0>; + qcom,supply-pre-off-sleep = <0>; + qcom,supply-post-off-sleep = <0>; + }; }; - }; - - qcom,phy-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,phy-supply-entry@0 { - reg = <0>; - 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,phy-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,phy-supply-entry@0 { + reg = <0>; + 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,ctrl-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,ctrl-supply-entry@0 { - reg = <0>; - 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 = <20>; - qcom,supply-pre-off-sleep = <0>; - qcom,supply-post-off-sleep = <0>; + + qcom,ctrl-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,ctrl-supply-entry@0 { + reg = <0>; + 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 = <20>; + qcom,supply-pre-off-sleep = <0>; + qcom,supply-post-off-sleep = <0>; + }; }; - }; - }; + }; + }; diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 64c28dd39718..aa7d870fd4a7 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -32,11 +32,22 @@ #define XO_CLK_RATE 19200000 +/* Master structure to hold all the information about the DSI/panel */ +static struct mdss_dsi_data *mdss_dsi_res; + static struct dsi_drv_cm_data shared_ctrl_data; static int mdss_dsi_pinctrl_set_state(struct mdss_dsi_ctrl_pdata *ctrl_pdata, bool active); +static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_ctrl(u32 ctrl_id) +{ + if (ctrl_id >= DSI_CTRL_MAX || !mdss_dsi_res) + return NULL; + + return mdss_dsi_res->ctrl_pdata[ctrl_id]; +} + static int mdss_dsi_regulator_init(struct platform_device *pdev) { int rc = 0; @@ -243,7 +254,7 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev, */ supply_root_node = of_parse_phandle(of_node, pm_supply_name, 0); if (!supply_root_node) { - pr_err("no supply entry present\n"); + pr_err("no supply entry present: %s\n", pm_supply_name); goto novreg; } } @@ -2007,55 +2018,86 @@ end: return dsi_pan_node; } +static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev) +{ + struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev); + char panel_cfg[MDSS_MAX_PANEL_LEN]; + struct device_node *dsi_pan_node = NULL; + bool cmd_cfg_cont_splash = true; + int rc = 0; + + if (!ctrl_pdata) { + pr_err("%s: Unable to get the ctrl_pdata\n", __func__); + return NULL; + } + + /* DSI panels can be different between controllers */ + rc = mdss_dsi_get_panel_cfg(panel_cfg, ctrl_pdata); + if (!rc) + /* dsi panel cfg not present */ + pr_warn("%s:%d:dsi specific cfg not present\n", + __func__, __LINE__); + + /* find panel device node */ + dsi_pan_node = mdss_dsi_find_panel_of_node(pdev, panel_cfg); + if (!dsi_pan_node) { + pr_err("%s: can't find panel node %s\n", __func__, panel_cfg); + of_node_put(dsi_pan_node); + return NULL; + } + + cmd_cfg_cont_splash = mdss_panel_get_boot_cfg() ? true : false; + + rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, cmd_cfg_cont_splash); + if (rc) { + pr_err("%s: dsi panel init failed\n", __func__); + of_node_put(dsi_pan_node); + return NULL; + } + + return dsi_pan_node; +} + static int mdss_dsi_ctrl_probe(struct platform_device *pdev) { int rc = 0, i = 0; u32 index; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct device_node *dsi_pan_node = NULL; - char panel_cfg[MDSS_MAX_PANEL_LEN]; const char *ctrl_name; - bool cmd_cfg_cont_splash = true; - struct mdss_panel_cfg *pan_cfg = NULL; struct mdss_util_intf *util; - util = mdss_get_util_intf(); - if (util == NULL) { - pr_err("Failed to get mdss utility functions\n"); + if (!pdev || !pdev->dev.of_node) { + pr_err("%s: pdev not found for DSI controller\n", __func__); return -ENODEV; } - - if (!util->mdp_probe_done) { - pr_err("%s: MDP not probed yet!\n", __func__); - return -EPROBE_DEFER; + rc = of_property_read_u32(pdev->dev.of_node, + "cell-index", &index); + if (rc) { + dev_err(&pdev->dev, "%s: Cell-index not specified, rc=%d\n", + __func__, rc); + return rc; } - if (!pdev->dev.of_node) { - pr_err("DSI driver only supports device tree probe\n"); - return -ENOTSUPP; + if (index == 0) + pdev->id = 1; + else + pdev->id = 2; + + ctrl_pdata = mdss_dsi_get_ctrl(index); + if (!ctrl_pdata) { + pr_err("%s: Unable to get the ctrl_pdata\n", __func__); + return -EINVAL; } - pan_cfg = util->panel_intf_type(MDSS_PANEL_INTF_HDMI); - if (IS_ERR(pan_cfg)) { - return PTR_ERR(pan_cfg); - } else if (pan_cfg) { - pr_debug("%s: HDMI is primary\n", __func__); + platform_set_drvdata(pdev, ctrl_pdata); + + util = mdss_get_util_intf(); + if (util == NULL) { + pr_err("Failed to get mdss utility functions\n"); return -ENODEV; } - ctrl_pdata = platform_get_drvdata(pdev); - if (!ctrl_pdata) { - ctrl_pdata = devm_kzalloc(&pdev->dev, - sizeof(struct mdss_dsi_ctrl_pdata), - GFP_KERNEL); - if (!ctrl_pdata) { - pr_err("%s: FAILED: cannot alloc dsi ctrl\n", - __func__); - rc = -ENOMEM; - goto error_no_mem; - } - platform_set_drvdata(pdev, ctrl_pdata); - } ctrl_pdata->mdss_util = util; atomic_set(&ctrl_pdata->te_irq_ready, 0); @@ -2067,29 +2109,6 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) pr_info("%s: DSI Ctrl name = %s\n", __func__, ctrl_name); - rc = of_property_read_u32(pdev->dev.of_node, - "cell-index", &index); - if (rc) { - dev_err(&pdev->dev, - "%s: Cell-index not specified, rc=%d\n", - __func__, rc); - goto error_no_mem; - } - - if (index == 0) - pdev->id = 1; - else - pdev->id = 2; - - rc = of_platform_populate(pdev->dev.of_node, - NULL, NULL, &pdev->dev); - if (rc) { - dev_err(&pdev->dev, - "%s: failed to add child nodes, rc=%d\n", - __func__, rc); - goto error_no_mem; - } - rc = mdss_dsi_pinctrl_init(pdev); if (rc) pr_warn("%s: failed to get pin resources\n", __func__); @@ -2107,38 +2126,37 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) } } - /* DSI panels can be different between controllers */ - rc = mdss_dsi_get_panel_cfg(panel_cfg, ctrl_pdata); - if (!rc) - /* dsi panel cfg not present */ - pr_warn("%s:%d:dsi specific cfg not present\n", - __func__, __LINE__); + if (index == 0) + ctrl_pdata->panel_data.panel_info.pdest = DISPLAY_1; + else + ctrl_pdata->panel_data.panel_info.pdest = DISPLAY_2; - /* find panel device node */ - dsi_pan_node = mdss_dsi_find_panel_of_node(pdev, panel_cfg); + dsi_pan_node = mdss_dsi_config_panel(pdev); if (!dsi_pan_node) { - pr_err("%s: can't find panel node %s\n", __func__, panel_cfg); - goto error_pan_node; + pr_err("%s: panel configuration failed\n", __func__); + i--; + rc = -EINVAL; + goto error_vreg; } - cmd_cfg_cont_splash = mdss_panel_get_boot_cfg() ? true : false; - - rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, cmd_cfg_cont_splash); - if (rc) { - pr_err("%s: dsi panel init failed\n", __func__); - goto error_pan_node; + if ((mdss_dsi_res->hw_config != SPLIT_DSI) || + ((mdss_dsi_res->hw_config == SPLIT_DSI) && + (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1))) { + rc = mdss_panel_parse_bl_settings(dsi_pan_node, ctrl_pdata); + if (rc) { + pr_err("%s: dsi bl settings parse failed\n", __func__); + goto error_pan_node; + } + } else { + ctrl_pdata->bklt_ctrl = UNKNOWN_CTRL; } - rc = dsi_panel_device_register(dsi_pan_node, ctrl_pdata); + rc = dsi_panel_device_register(pdev, dsi_pan_node, ctrl_pdata); if (rc) { pr_err("%s: dsi panel dev reg failed\n", __func__); goto error_pan_node; } - ctrl_pdata->cmd_clk_ln_recovery_en = - of_property_read_bool(pdev->dev.of_node, - "qcom,dsi-clk-ln-recovery"); - if (mdss_dsi_is_te_based_esd(ctrl_pdata)) { rc = devm_request_irq(&pdev->dev, gpio_to_irq(ctrl_pdata->disp_te_gpio), @@ -2160,12 +2178,170 @@ error_vreg: for (; i >= 0; i--) mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data[i]); -error_no_mem: - devm_kfree(&pdev->dev, ctrl_pdata); + return rc; +} + +static void mdss_dsi_res_deinit(struct platform_device *pdev) +{ + int i; + struct mdss_dsi_data *dsi_res = platform_get_drvdata(pdev); + if (!dsi_res) { + pr_err("%s: DSI root device drvdata not found\n", __func__); + return; + } + + for (i = 0; i < DSI_CTRL_MAX; i++) { + if (dsi_res->ctrl_pdata[i]) + devm_kfree(&pdev->dev, dsi_res->ctrl_pdata[i]); + } + + if (dsi_res) + devm_kfree(&pdev->dev, dsi_res); + + return; +} + +static int mdss_dsi_res_init(struct platform_device *pdev) +{ + int rc = 0, i; + + mdss_dsi_res = platform_get_drvdata(pdev); + if (!mdss_dsi_res) { + mdss_dsi_res = devm_kzalloc(&pdev->dev, + sizeof(struct mdss_dsi_data), + GFP_KERNEL); + if (!mdss_dsi_res) { + pr_err("%s: FAILED: cannot alloc dsi data\n", + __func__); + rc = -ENOMEM; + goto mem_fail; + } + + for (i = 0; i < DSI_CTRL_MAX; i++) { + mdss_dsi_res->ctrl_pdata[i] = devm_kzalloc(&pdev->dev, + sizeof(struct mdss_dsi_ctrl_pdata), + GFP_KERNEL); + pr_debug("%s Allocated ctrl_pdata[%d]=%p\n", + __func__, i, mdss_dsi_res->ctrl_pdata[i]); + if (!mdss_dsi_res->ctrl_pdata[i]) { + pr_err("%s Unable to alloc mem for ctrl=%d\n", + __func__, i); + rc = -ENOMEM; + goto mem_fail; + } + } + + platform_set_drvdata(pdev, mdss_dsi_res); + } + + mdss_dsi_res->pdev = pdev; + pr_debug("%s: Setting up mdss_dsi_res=%p\n", __func__, mdss_dsi_res); + + return 0; + +mem_fail: + mdss_dsi_res_deinit(pdev); return rc; } +static int mdss_dsi_parse_hw_cfg(struct platform_device *pdev) +{ + const char *data; + struct mdss_dsi_data *dsi_res = platform_get_drvdata(pdev); + + if (!dsi_res) { + pr_err("%s: DSI root device drvdata not found\n", __func__); + return -EINVAL; + } + + dsi_res->hw_config = SINGLE_DSI; + + data = of_get_property(pdev->dev.of_node, "hw-config", NULL); + if (data) { + if (!strcmp(data, "dual_dsi")) + dsi_res->hw_config = DUAL_DSI; + else if (!strcmp(data, "split_dsi")) + dsi_res->hw_config = SPLIT_DSI; + else if (!strcmp(data, "single_dsi")) + dsi_res->hw_config = SINGLE_DSI; + else + pr_err("%s: Incorrect string for DSI config:%s. Setting default as SINGLE_DSI\n", + __func__, data); + } else { + pr_err("%s: Error: No DSI HW config found\n", + __func__); + return -EINVAL; + } + + pr_debug("%s: DSI h/w configuration is %d\n", __func__, + dsi_res->hw_config); + + return 0; +} + +static const struct of_device_id mdss_dsi_ctrl_dt_match[] = { + {.compatible = "qcom,mdss-dsi-ctrl"}, + {} +}; +MODULE_DEVICE_TABLE(of, mdss_dsi_ctrl_dt_match); + +static int mdss_dsi_probe(struct platform_device *pdev) +{ + struct mdss_panel_cfg *pan_cfg = NULL; + struct mdss_util_intf *util; + int rc = 0; + + util = mdss_get_util_intf(); + if (util == NULL) { + pr_err("%s: Failed to get mdss utility functions\n", __func__); + return -ENODEV; + } + + if (!util->mdp_probe_done) { + pr_err("%s: MDP not probed yet!\n", __func__); + return -EPROBE_DEFER; + } + + if (!pdev || !pdev->dev.of_node) { + pr_err("%s: DSI driver only supports device tree probe\n", + __func__); + return -ENOTSUPP; + } + + pan_cfg = util->panel_intf_type(MDSS_PANEL_INTF_HDMI); + if (IS_ERR(pan_cfg)) { + return PTR_ERR(pan_cfg); + } else if (pan_cfg) { + pr_debug("%s: HDMI is primary\n", __func__); + return -ENODEV; + } + + rc = mdss_dsi_res_init(pdev); + if (rc) { + pr_err("%s Unable to set dsi res\n", __func__); + return rc; + } + + rc = mdss_dsi_parse_hw_cfg(pdev); + if (rc) { + pr_err("%s Unable to parse dsi h/w config\n", __func__); + mdss_dsi_res_deinit(pdev); + return rc; + } + + of_platform_populate(pdev->dev.of_node, mdss_dsi_ctrl_dt_match, + NULL, &pdev->dev); + + return 0; +} + +static int mdss_dsi_remove(struct platform_device *pdev) +{ + mdss_dsi_res_deinit(pdev); + return 0; +} + static int mdss_dsi_ctrl_remove(struct platform_device *pdev) { struct msm_fb_data_type *mfd; @@ -2321,53 +2497,12 @@ static void mdss_dsi_parse_lane_swap(struct device_node *np, char *dlane_swap) } } -int dsi_panel_device_register(struct device_node *pan_node, - struct mdss_dsi_ctrl_pdata *ctrl_pdata) +static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, + struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata) { - struct mipi_panel_info *mipi; int rc, i, len; struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); - struct device_node *dsi_ctrl_np = NULL; - struct platform_device *ctrl_pdev = NULL; const char *data; - u64 clk_rate; - struct resource *res; - - mipi = &(pinfo->mipi); - - pinfo->type = - ((mipi->mode == DSI_VIDEO_MODE) - ? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL); - - rc = mdss_dsi_clk_div_config(pinfo, mipi->frame_rate); - if (rc) { - pr_err("%s: unable to initialize the clk dividers\n", __func__); - return rc; - } - - dsi_ctrl_np = of_parse_phandle(pan_node, - "qcom,mdss-dsi-panel-controller", 0); - if (!dsi_ctrl_np) { - pr_err("%s: Dsi controller node not initialized\n", __func__); - return -EPROBE_DEFER; - } - - ctrl_pdev = of_find_device_by_node(dsi_ctrl_np); - - rc = mdss_dsi_get_dt_vreg_data(&ctrl_pdev->dev, pan_node, - &ctrl_pdata->power_data[DSI_PANEL_PM], DSI_PANEL_PM); - if (rc) { - DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n", - __func__, __mdss_dsi_pm_name(DSI_PANEL_PM), rc); - return rc; - } - - rc = mdss_dsi_regulator_init(ctrl_pdev); - if (rc) { - pr_err("%s: failed to init regulator, rc=%d\n", - __func__, rc); - return rc; - } data = of_get_property(ctrl_pdev->dev.of_node, "qcom,platform-strength-ctrl", &len); @@ -2435,15 +2570,33 @@ int dsi_panel_device_register(struct device_node *pan_node, ctrl_pdata->cmd_sync_wait_broadcast = of_property_read_bool( pan_node, "qcom,cmd-sync-wait-broadcast"); - ctrl_pdata->cmd_sync_wait_trigger = of_property_read_bool( - pan_node, "qcom,cmd-sync-wait-trigger"); + if (ctrl_pdata->cmd_sync_wait_broadcast && + (mdss_dsi_res->hw_config == SPLIT_DSI) && + (pinfo->pdest == DISPLAY_2)) + ctrl_pdata->cmd_sync_wait_trigger = true; pr_debug("%s: cmd_sync_wait_enable=%d trigger=%d\n", __func__, ctrl_pdata->cmd_sync_wait_broadcast, ctrl_pdata->cmd_sync_wait_trigger); - pinfo->panel_max_fps = mdss_panel_get_framerate(pinfo); - pinfo->panel_max_vtotal = mdss_panel_get_vtotal(pinfo); + ctrl_pdata->timing_db_mode = of_property_read_bool( + ctrl_pdev->dev.of_node, "qcom,timing-db-mode"); + + ctrl_pdata->cmd_clk_ln_recovery_en = of_property_read_bool( + ctrl_pdev->dev.of_node, "qcom,dsi-clk-ln-recovery"); + + mdss_dsi_parse_lane_swap(ctrl_pdev->dev.of_node, + &(ctrl_pdata->dlane_swap)); + + return 0; + + +} + +static int mdss_dsi_parse_gpio_params(struct platform_device *ctrl_pdev, + struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); /* * If disp_en_gpio has been set previously (disp_en_gpio > 0) @@ -2489,11 +2642,61 @@ int dsi_panel_device_register(struct device_node *pan_node, ctrl_pdata->mode_gpio = -EINVAL; } - mdss_dsi_parse_lane_swap(ctrl_pdev->dev.of_node, - &(ctrl_pdata->dlane_swap)); + return 0; +} - ctrl_pdata->timing_db_mode = of_property_read_bool( - ctrl_pdev->dev.of_node, "qcom,timing-db-mode"); +int dsi_panel_device_register(struct platform_device *ctrl_pdev, + struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + struct mipi_panel_info *mipi; + int rc; + struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); + struct resource *res; + u64 clk_rate; + + mipi = &(pinfo->mipi); + + pinfo->type = + ((mipi->mode == DSI_VIDEO_MODE) + ? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL); + + rc = mdss_dsi_clk_div_config(pinfo, mipi->frame_rate); + if (rc) { + pr_err("%s: unable to initialize the clk dividers\n", __func__); + return rc; + } + + rc = mdss_dsi_get_dt_vreg_data(&ctrl_pdev->dev, pan_node, + &ctrl_pdata->power_data[DSI_PANEL_PM], DSI_PANEL_PM); + if (rc) { + DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM), rc); + return rc; + } + + rc = mdss_dsi_regulator_init(ctrl_pdev); + if (rc) { + pr_err("%s: failed to init regulator, rc=%d\n", + __func__, rc); + return rc; + } + + rc = mdss_dsi_parse_ctrl_params(ctrl_pdev, pan_node, ctrl_pdata); + if (rc) { + pr_err("%s: failed to parse ctrl settings, rc=%d\n", + __func__, rc); + return rc; + } + + pinfo->panel_max_fps = mdss_panel_get_framerate(pinfo); + pinfo->panel_max_vtotal = mdss_panel_get_vtotal(pinfo); + + rc = mdss_dsi_parse_gpio_params(ctrl_pdev, ctrl_pdata); + if (rc) { + pr_err("%s: failed to parse gpio params, rc=%d\n", + __func__, rc); + return rc; + } if (mdss_dsi_clk_init(ctrl_pdev, ctrl_pdata)) { pr_err("%s: unable to initialize Dsi ctrl clks\n", __func__); @@ -2629,11 +2832,21 @@ int dsi_panel_device_register(struct device_node *pan_node, return 0; } -static const struct of_device_id mdss_dsi_ctrl_dt_match[] = { - {.compatible = "qcom,mdss-dsi-ctrl"}, +static const struct of_device_id mdss_dsi_dt_match[] = { + {.compatible = "qcom,mdss-dsi"}, {} }; -MODULE_DEVICE_TABLE(of, mdss_dsi_ctrl_dt_match); +MODULE_DEVICE_TABLE(of, mdss_dsi_dt_match); + +static struct platform_driver mdss_dsi_driver = { + .probe = mdss_dsi_probe, + .remove = mdss_dsi_remove, + .shutdown = NULL, + .driver = { + .name = "mdss_dsi", + .of_match_table = mdss_dsi_dt_match, + }, +}; static struct platform_driver mdss_dsi_ctrl_driver = { .probe = mdss_dsi_ctrl_probe, @@ -2647,7 +2860,7 @@ static struct platform_driver mdss_dsi_ctrl_driver = { static int mdss_dsi_register_driver(void) { - return platform_driver_register(&mdss_dsi_ctrl_driver); + return platform_driver_register(&mdss_dsi_driver); } static int __init mdss_dsi_driver_init(void) @@ -2664,6 +2877,26 @@ static int __init mdss_dsi_driver_init(void) } module_init(mdss_dsi_driver_init); + +static int mdss_dsi_ctrl_register_driver(void) +{ + return platform_driver_register(&mdss_dsi_ctrl_driver); +} + +static int __init mdss_dsi_ctrl_driver_init(void) +{ + int ret; + + ret = mdss_dsi_ctrl_register_driver(); + if (ret) { + pr_err("mdss_dsi_ctrl_register_driver() failed!\n"); + return ret; + } + + return ret; +} +module_init(mdss_dsi_ctrl_driver_init); + static void __exit mdss_dsi_driver_cleanup(void) { platform_driver_unregister(&mdss_dsi_ctrl_driver); diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 5a403d542528..a8076b6cac91 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -204,48 +204,34 @@ extern struct device dsi_dev; extern u32 dsi_irq; extern struct mdss_dsi_ctrl_pdata *ctrl_list[]; -struct dsiphy_pll_divider_config { - u64 clk_rate; - u32 fb_divider; - u32 ref_divider_ratio; - u32 bit_clk_divider; /* oCLK1 */ - u32 byte_clk_divider; /* oCLK2 */ - u32 analog_posDiv; - u32 digital_posDiv; -}; - -extern struct dsiphy_pll_divider_config pll_divider_config; - -struct dsi_clk_mnd_table { - u8 lanes; - u8 bpp; - u8 pll_digital_posDiv; - u8 pclk_m; - u8 pclk_n; - u8 pclk_d; +enum { + DSI_CTRL_0, + DSI_CTRL_1, + DSI_CTRL_MAX, }; -static const struct dsi_clk_mnd_table mnd_table[] = { - { 1, 2, 8, 1, 1, 0}, - { 1, 3, 12, 1, 1, 0}, - { 2, 2, 4, 1, 1, 0}, - { 2, 3, 6, 1, 1, 0}, - { 3, 2, 1, 3, 8, 4}, - { 3, 3, 4, 1, 1, 0}, - { 4, 2, 2, 1, 1, 0}, - { 4, 3, 3, 1, 1, 0}, +struct mdss_dsi_data { + u32 hw_config; /* DSI setup configuration i.e. single/dual/split */ + bool res_init; + struct platform_device *pdev; + /* List of controller specific struct data */ + struct mdss_dsi_ctrl_pdata *ctrl_pdata[DSI_CTRL_MAX]; }; -struct dsi_clk_desc { - u32 src; - u32 m; - u32 n; - u32 d; - u32 mnd_mode; - u32 pre_div_func; +/* + * enum mdss_dsi_hw_config - Supported DSI h/w configurations + * + * @SINGLE_DSI: Single DSI panel driven by either DSI0 or DSI1. + * @DUAL_DSI: Two DSI panels driven independently by DSI0 & DSI1. + * @SPLIT_DSI: A split DSI panel driven by both the DSI controllers + * with the DSI link clocks sourced by a single DSI PLL. + */ +enum mdss_dsi_hw_config { + SINGLE_DSI, + DUAL_DSI, + SPLIT_DSI, }; - struct dsi_panel_cmds { char *buf; int blen; @@ -277,12 +263,6 @@ struct panel_horizontal_idle { int idle; }; -enum { - DSI_CTRL_0, - DSI_CTRL_1, - DSI_CTRL_MAX, -}; - #define DSI_CTRL_LEFT DSI_CTRL_0 #define DSI_CTRL_RIGHT DSI_CTRL_1 #define DSI_CTRL_CLK_SLAVE DSI_CTRL_RIGHT @@ -441,8 +421,8 @@ struct dsi_status_data { }; void mdss_dsi_read_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl); -int dsi_panel_device_register(struct device_node *pan_node, - struct mdss_dsi_ctrl_pdata *ctrl_pdata); +int dsi_panel_device_register(struct platform_device *ctrl_pdev, + struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt); @@ -510,6 +490,8 @@ u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, int mdss_dsi_panel_init(struct device_node *node, struct mdss_dsi_ctrl_pdata *ctrl_pdata, bool cmd_cfg_cont_splash); +int mdss_panel_parse_bl_settings(struct device_node *np, + struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing, char *dst_format); diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 8feaf5188a11..b05689da9ec5 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1588,7 +1588,8 @@ static int mdss_dsi_parse_panel_features(struct device_node *np, "qcom,partial-update-roi-merge"); } - pinfo->dcs_cmd_by_left = of_property_read_bool(np, + if (pinfo->pdest == DISPLAY_1) + pinfo->dcs_cmd_by_left = of_property_read_bool(np, "qcom,dcs-cmd-by-left"); } @@ -1754,13 +1755,73 @@ static void mdss_dsi_parse_dfps_config(struct device_node *pan_node, return; } +int mdss_panel_parse_bl_settings(struct device_node *np, + struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + const char *data; + int rc = 0; + u32 tmp; + + ctrl_pdata->bklt_ctrl = UNKNOWN_CTRL; + data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL); + if (data) { + if (!strcmp(data, "bl_ctrl_wled")) { + led_trigger_register_simple("bkl-trigger", + &bl_led_trigger); + pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", + __func__); + ctrl_pdata->bklt_ctrl = BL_WLED; + } else if (!strcmp(data, "bl_ctrl_pwm")) { + ctrl_pdata->bklt_ctrl = BL_PWM; + ctrl_pdata->pwm_pmi = of_property_read_bool(np, + "qcom,mdss-dsi-bl-pwm-pmi"); + rc = of_property_read_u32(np, + "qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp); + if (rc) { + pr_err("%s:%d, Error, panel pwm_period\n", + __func__, __LINE__); + return -EINVAL; + } + ctrl_pdata->pwm_period = tmp; + if (ctrl_pdata->pwm_pmi) { + ctrl_pdata->pwm_bl = of_pwm_get(np, NULL); + if (IS_ERR(ctrl_pdata->pwm_bl)) { + pr_err("%s: Error, pwm device\n", + __func__); + ctrl_pdata->pwm_bl = NULL; + return -EINVAL; + } + } else { + rc = of_property_read_u32(np, + "qcom,mdss-dsi-bl-pmic-bank-select", + &tmp); + if (rc) { + pr_err("%s:%d, Error, lpg channel\n", + __func__, __LINE__); + return -EINVAL; + } + ctrl_pdata->pwm_lpg_chan = tmp; + tmp = of_get_named_gpio(np, + "qcom,mdss-dsi-pwm-gpio", 0); + ctrl_pdata->pwm_pmic_gpio = tmp; + pr_debug("%s: Configured PWM bklt ctrl\n", + __func__); + } + } else if (!strcmp(data, "bl_ctrl_dcs")) { + ctrl_pdata->bklt_ctrl = BL_DCS_CMD; + pr_debug("%s: Configured DCS_CMD bklt ctrl\n", + __func__); + } + } + return 0; +} + static int mdss_panel_parse_dt(struct device_node *np, struct mdss_dsi_ctrl_pdata *ctrl_pdata) { u32 tmp; int rc, i, len; const char *data; - static const char *pdest; struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-width", &tmp); @@ -1829,28 +1890,6 @@ static int mdss_panel_parse_dt(struct device_node *np, pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888; } - pdest = of_get_property(np, - "qcom,mdss-dsi-panel-destination", NULL); - - if (pdest) { - if (strlen(pdest) != 9) { - pr_err("%s: Unknown pdest specified\n", __func__); - return -EINVAL; - } - if (!strcmp(pdest, "display_1")) - pinfo->pdest = DISPLAY_1; - else if (!strcmp(pdest, "display_2")) - pinfo->pdest = DISPLAY_2; - else { - pr_debug("%s: incorrect pdest. Set Default\n", - __func__); - pinfo->pdest = DISPLAY_1; - } - } else { - pr_debug("%s: pdest not specified. Set Default\n", - __func__); - pinfo->pdest = DISPLAY_1; - } rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp); pinfo->lcdc.h_front_porch = (!rc ? tmp : 6); rc = of_property_read_u32(np, "qcom,mdss-dsi-h-back-porch", &tmp); @@ -1882,57 +1921,6 @@ static int mdss_panel_parse_dt(struct device_node *np, pinfo->panel_orientation = MDP_FLIP_UD; } - ctrl_pdata->bklt_ctrl = UNKNOWN_CTRL; - data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL); - if (data) { - if (!strncmp(data, "bl_ctrl_wled", 12)) { - led_trigger_register_simple("bkl-trigger", - &bl_led_trigger); - pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", - __func__); - ctrl_pdata->bklt_ctrl = BL_WLED; - } else if (!strncmp(data, "bl_ctrl_pwm", 11)) { - ctrl_pdata->bklt_ctrl = BL_PWM; - ctrl_pdata->pwm_pmi = of_property_read_bool(np, - "qcom,mdss-dsi-bl-pwm-pmi"); - rc = of_property_read_u32(np, - "qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp); - if (rc) { - pr_err("%s:%d, Error, panel pwm_period\n", - __func__, __LINE__); - return -EINVAL; - } - ctrl_pdata->pwm_period = tmp; - if (ctrl_pdata->pwm_pmi) { - ctrl_pdata->pwm_bl = of_pwm_get(np, NULL); - if (IS_ERR(ctrl_pdata->pwm_bl)) { - pr_err("%s: Error, pwm device\n", - __func__); - ctrl_pdata->pwm_bl = NULL; - return -EINVAL; - } - } else { - rc = of_property_read_u32(np, - "qcom,mdss-dsi-bl-pmic-bank-select", - &tmp); - if (rc) { - pr_err("%s:%d, Error, lpg channel\n", - __func__, __LINE__); - return -EINVAL; - } - ctrl_pdata->pwm_lpg_chan = tmp; - tmp = of_get_named_gpio(np, - "qcom,mdss-dsi-pwm-gpio", 0); - ctrl_pdata->pwm_pmic_gpio = tmp; - pr_debug("%s: Configured PWM bklt ctrl\n", - __func__); - } - } else if (!strncmp(data, "bl_ctrl_dcs", 11)) { - ctrl_pdata->bklt_ctrl = BL_DCS_CMD; - pr_debug("%s: Configured DCS_CMD bklt ctrl\n", - __func__); - } - } rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level", &tmp); pinfo->brightness_max = (!rc ? tmp : MDSS_MAX_BL_BRIGHTNESS); rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp); diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 047f1090926f..6d2c28acb3a1 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -51,8 +51,6 @@ #define DSIPHY_PLL_CLKBUFLR_EN 0x041c #define DSIPHY_PLL_PLL_BANDGAP 0x0508 -static struct dsi_clk_desc dsi_pclk; - static void mdss_dsi_ctrl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl) { /* start phy sw reset */ @@ -796,8 +794,6 @@ void mdss_dsi_shadow_clk_deinit(struct mdss_dsi_ctrl_pdata *ctrl) clk_put(ctrl->shadow_pixel_clk); } -#define PREF_DIV_RATIO 27 -struct dsiphy_pll_divider_config pll_divider_config; int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, int frame_rate) @@ -806,13 +802,9 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, struct mdss_panel_data, panel_info); struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); - u32 fb_divider, rate, vco; - u32 div_ratio = 0; - u32 pll_analog_posDiv = 1; u64 h_period, v_period, clk_rate; u32 dsi_pclk_rate; u8 lanes = 0, bpp; - struct dsi_clk_mnd_table const *mnd_entry = mnd_table; if (panel_info->mipi.data_lane3) lanes += 1; @@ -854,75 +846,11 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, h_period * v_period * frame_rate * bpp * 8; } } - pll_divider_config.clk_rate = panel_info->clk_rate; - - if (pll_divider_config.clk_rate == 0) - pll_divider_config.clk_rate = 454000000; - - /* Half Bit Clock In Mhz */ - clk_rate = pll_divider_config.clk_rate; - do_div(clk_rate, 2U); - do_div(clk_rate, 1000000U); - rate = (u32)clk_rate; - - if (rate < 43) { - vco = rate * 16; - div_ratio = 16; - pll_analog_posDiv = 8; - } else if (rate < 85) { - vco = rate * 8; - div_ratio = 8; - pll_analog_posDiv = 4; - } else if (rate < 170) { - vco = rate * 4; - div_ratio = 4; - pll_analog_posDiv = 2; - } else if (rate < 340) { - vco = rate * 2; - div_ratio = 2; - pll_analog_posDiv = 1; - } else { - /* DSI PLL Direct path configuration */ - vco = rate * 1; - div_ratio = 1; - pll_analog_posDiv = 1; - } - /* find the mnd settings from mnd_table entry */ - for (; mnd_entry < mnd_table + ARRAY_SIZE(mnd_table); ++mnd_entry) { - if (((mnd_entry->lanes) == lanes) && - ((mnd_entry->bpp) == bpp)) - break; - } + if (panel_info->clk_rate == 0) + panel_info->clk_rate = 454000000; - if (mnd_entry == mnd_table + ARRAY_SIZE(mnd_table)) { - pr_err("%s: requested Lanes, %u & BPP, %u, not supported\n", - __func__, lanes, bpp); - return -EINVAL; - } - fb_divider = ((vco * PREF_DIV_RATIO) / 27); - pll_divider_config.fb_divider = fb_divider; - pll_divider_config.ref_divider_ratio = PREF_DIV_RATIO; - pll_divider_config.bit_clk_divider = div_ratio; - pll_divider_config.byte_clk_divider = - pll_divider_config.bit_clk_divider * 8; - pll_divider_config.analog_posDiv = pll_analog_posDiv; - pll_divider_config.digital_posDiv = - (mnd_entry->pll_digital_posDiv) * div_ratio; - - if ((mnd_entry->pclk_d == 0) - || (mnd_entry->pclk_m == 1)) { - dsi_pclk.mnd_mode = 0; - dsi_pclk.src = 0x3; - dsi_pclk.pre_div_func = (mnd_entry->pclk_n - 1); - } else { - dsi_pclk.mnd_mode = 2; - dsi_pclk.src = 0x3; - dsi_pclk.m = mnd_entry->pclk_m; - dsi_pclk.n = mnd_entry->pclk_n; - dsi_pclk.d = mnd_entry->pclk_d; - } - clk_rate = pll_divider_config.clk_rate; + clk_rate = panel_info->clk_rate; do_div(clk_rate, 8 * bpp); dsi_pclk_rate = (u32) clk_rate * lanes; |
