diff --git a/config/gki_waipiodisp.conf b/config/gki_waipiodisp.conf index 817b9ef5ee..c4327eba76 100644 --- a/config/gki_waipiodisp.conf +++ b/config/gki_waipiodisp.conf @@ -10,3 +10,4 @@ export CONFIG_DRM_SDE_RSC=y export CONFIG_DRM_SDE_WB=y export CONFIG_DRM_MSM_REGISTER_LOGGING=y export CONFIG_DISPLAY_BUILD=m +export CONFIG_DRM_SDE_VM=y diff --git a/config/gki_waipiodispconf.h b/config/gki_waipiodispconf.h index 8f0c0162da..d652a52892 100644 --- a/config/gki_waipiodispconf.h +++ b/config/gki_waipiodispconf.h @@ -17,4 +17,4 @@ #define CONFIG_QCOM_MDSS_PLL 1 #define CONFIG_GKI_DISPLAY 1 #define CONFIG_MSM_EXT_DISPLAY 1 - +#define CONFIG_DRM_SDE_VM 1 diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 4e1fbec9c9..08a9f645bb 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -3966,6 +3966,37 @@ end: return rc; } +static int dsi_display_validate_res(struct dsi_display *display) +{ + struct device_node *of_node = display->pdev->dev.of_node; + struct of_phandle_iterator it; + struct dsi_ctrl *dsi_ctrl; + bool ctrl_avail = false; + + of_phandle_iterator_init(&it, of_node, "qcom,dsi-ctrl", NULL, 0); + while (of_phandle_iterator_next(&it) == 0) { + dsi_ctrl = dsi_ctrl_get(it.node); + if (IS_ERR(dsi_ctrl)) { + int rc = PTR_ERR(dsi_ctrl); + + if (rc == -EPROBE_DEFER) + return rc; + /* + * With dual display mode, the seconday display needs at least + * one ctrl to proceed through the probe. Exact ctrl match + * will be done after parsing the DT or firmware data. + */ + if (rc == -EBUSY) + ctrl_avail |= false; + } else { + dsi_ctrl_put(dsi_ctrl); + ctrl_avail = true; + } + } + + return ctrl_avail ? 0 : -EBUSY; +} + static int dsi_display_get_phandle_count(struct dsi_display *display, const char *propname) { @@ -4048,7 +4079,7 @@ error: return rc; } -static int dsi_display_validate_resources(struct dsi_display *display) +static int dsi_display_res_init(struct dsi_display *display) { int rc = 0; int i; @@ -4061,7 +4092,7 @@ static int dsi_display_validate_resources(struct dsi_display *display) rc = PTR_ERR(ctrl->ctrl); DSI_ERR("failed to get dsi controller, rc=%d\n", rc); ctrl->ctrl = NULL; - goto error; + goto error_ctrl_put; } ctrl->phy = dsi_phy_get(ctrl->phy_of_node); @@ -4070,24 +4101,9 @@ static int dsi_display_validate_resources(struct dsi_display *display) DSI_ERR("failed to get phy controller, rc=%d\n", rc); dsi_ctrl_put(ctrl->ctrl); ctrl->phy = NULL; - goto error; + goto error_ctrl_put; } } - return rc; - -error: - for (i = i - 1; i >= 0; i--) { - ctrl = &display->ctrl[i]; - dsi_ctrl_put(ctrl->ctrl); - dsi_phy_put(ctrl->phy); - } - return -EPROBE_DEFER; -} - -static int dsi_display_res_init(struct dsi_display *display) -{ - int rc = 0; - int i; display->panel = dsi_panel_get(&display->pdev->dev, display->panel_node, @@ -4099,7 +4115,7 @@ static int dsi_display_res_init(struct dsi_display *display) rc = PTR_ERR(display->panel); DSI_ERR("failed to get panel, rc=%d\n", rc); display->panel = NULL; - goto error; + goto error_ctrl_put; } display_for_each_ctrl(i, display) { @@ -4127,13 +4143,13 @@ static int dsi_display_res_init(struct dsi_display *display) rc = dsi_display_parse_lane_map(display); if (rc) { DSI_ERR("Lane map not found, rc=%d\n", rc); - goto error; + goto error_ctrl_put; } rc = dsi_display_clocks_init(display); if (rc) { DSI_ERR("Failed to parse clock data, rc=%d\n", rc); - goto error; + goto error_ctrl_put; } /** @@ -4144,7 +4160,14 @@ static int dsi_display_res_init(struct dsi_display *display) display->is_active = false; else display->is_active = true; -error: + + return 0; +error_ctrl_put: + for (i = i - 1; i >= 0; i--) { + ctrl = &display->ctrl[i]; + dsi_ctrl_put(ctrl->ctrl); + dsi_phy_put(ctrl->phy); + } return rc; } @@ -5126,6 +5149,12 @@ static int _dsi_display_dev_init(struct dsi_display *display) display->parser, display->fw->data, display->fw->size); + rc = dsi_display_parse_dt(display); + if (rc) { + DSI_ERR("[%s] failed to parse dt, rc=%d\n", display->name, rc); + goto error; + } + rc = dsi_display_res_init(display); if (rc) { DSI_ERR("[%s] failed to initialize resources, rc=%d\n", @@ -5673,6 +5702,8 @@ static int dsi_display_init(struct dsi_display *display) int rc = 0; struct platform_device *pdev = display->pdev; + mutex_init(&display->display_lock); + rc = _dsi_display_dev_init(display); if (rc) { DSI_ERR("device init failed, rc=%d\n", rc); @@ -5754,7 +5785,6 @@ int dsi_display_dev_probe(struct platform_device *pdev) rc = -ENOMEM; goto end; } - mutex_init(&display->display_lock); display->dma_cmd_workq = create_singlethread_workqueue( "dsi_dma_cmd_workq"); @@ -5812,23 +5842,28 @@ int dsi_display_dev_probe(struct platform_device *pdev) platform_set_drvdata(pdev, display); - rc = dsi_display_parse_dt(display); + rc = dsi_display_validate_res(display); if (rc) { - DSI_ERR("[%s] failed to parse dt, rc=%d\n", display->name, rc); - goto end; - } + /* + * Display's bailing out without probe deferral must register its + * components to complete MDSS binding. Scheduled to be fixed in the future + * with dynamic component binding. + */ + if (rc == -EBUSY) { + int ret = component_add(&pdev->dev, + &dsi_display_comp_ops); + if (ret) + DSI_ERR( + "component add failed for display type: %s, rc=%d\n" + , display->type, ret); + } - rc = dsi_display_validate_resources(display); - if (rc) { - DSI_ERR("[%s] needed resources not probed yet, rc=%d\n", - display->name, rc); goto end; } /* initialize display in firmware callback */ if (!boot_disp->boot_disp_en && - IS_ENABLED(CONFIG_DSI_PARSER) && - !display->trusted_vm_env) { + IS_ENABLED(CONFIG_DSI_PARSER)) { if (!strcmp(display->display_type, "primary")) firm_req = !request_firmware_nowait( THIS_MODULE, 1, "dsi_prop", @@ -5850,10 +5885,8 @@ int dsi_display_dev_probe(struct platform_device *pdev) return 0; end: - if (display) { - mutex_destroy(&display->display_lock); + if (display) devm_kfree(&pdev->dev, display); - } return rc; } diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index ef141a688d..5d16e76ca7 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -2293,21 +2293,21 @@ static int dsi_panel_parse_tlmm_gpio(struct dsi_panel *panel) u32 base, size, pin; int pin_count, address_count, name_count, i; - address_count = of_property_count_u32_elems(utils->data, + address_count = utils->count_u32_elems(utils->data, "qcom,dsi-panel-gpio-address"); if (address_count != 2) { DSI_DEBUG("panel gpio address not defined\n"); return 0; } - of_property_read_u32_index(utils->data, + utils->read_u32_index(utils->data, "qcom,dsi-panel-gpio-address", 0, &base); - of_property_read_u32_index(utils->data, + utils->read_u32_index(utils->data, "qcom,dsi-panel-gpio-address", 1, &size); - pin_count = of_property_count_u32_elems(utils->data, + pin_count = utils->count_u32_elems(utils->data, "qcom,dsi-panel-gpio-pins"); - name_count = of_property_count_strings(utils->data, + name_count = utils->count_strings(utils->data, "qcom,dsi-panel-gpio-names"); if ((pin_count < 0) || (name_count < 0) || (pin_count != name_count)) { DSI_ERR("invalid gpio pins/names\n"); @@ -2321,13 +2321,13 @@ static int dsi_panel_parse_tlmm_gpio(struct dsi_panel *panel) panel->tlmm_gpio_count = pin_count; for (i = 0; i < pin_count; i++) { - of_property_read_u32_index(utils->data, + utils->read_u32_index(utils->data, "qcom,dsi-panel-gpio-pins", i, &pin); panel->tlmm_gpio[i].num = pin; panel->tlmm_gpio[i].addr = base + (pin * size); panel->tlmm_gpio[i].size = size; - of_property_read_string_index(utils->data, + utils->read_string_index(utils->data, "qcom,dsi-panel-gpio-names", i, &(panel->tlmm_gpio[i].name)); } diff --git a/msm/dsi/dsi_parser.c b/msm/dsi/dsi_parser.c index cef5fe70cf..b4c737d24a 100644 --- a/msm/dsi/dsi_parser.c +++ b/msm/dsi/dsi_parser.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -596,6 +596,49 @@ end: return rc; } +int dsi_parser_read_u32_index(const struct device_node *np, + const char *propname, u32 index, u32 *out_value) +{ + struct dsi_parser_node *node = (struct dsi_parser_node *)np; + struct dsi_parser_prop *prop; + char *property, *to_int, item[SZ_128]; + int rc = 0, base; + + prop = dsi_parser_search_property(node, propname); + if (!prop) { + DSI_DEBUG("%s not found\n", propname); + rc = -EINVAL; + goto end; + } + + if (index >= prop->len) { + rc = -EINVAL; + goto end; + } + + strlcpy(item, prop->items[index], SZ_128); + property = item; + to_int = strsep(&property, "x"); + + if (!property) { + property = to_int; + base = 10; + } else { + base = 16; + } + + rc = kstrtoint(property, base, out_value); + if (rc) { + DSI_ERR("prop=%s error(%d) converting %s, base=%d\n", + propname, rc, property, base); + goto end; + } + + DSI_DEBUG("%s=%d\n", propname, *out_value); +end: + return rc; +} + int dsi_parser_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz) diff --git a/msm/dsi/dsi_parser.h b/msm/dsi/dsi_parser.h index 949de1b4b0..7b7a251338 100644 --- a/msm/dsi/dsi_parser.h +++ b/msm/dsi/dsi_parser.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_PARSER_H_ @@ -24,6 +24,8 @@ int dsi_parser_read_u64(const struct device_node *np, const char *propname, u64 *out_value); int dsi_parser_read_u32(const struct device_node *np, const char *propname, u32 *out_value); +int dsi_parser_read_u32_index(const struct device_node *np, + const char *propname, u32 index, u32 *out_value); int dsi_parser_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz); @@ -90,6 +92,12 @@ static inline int dsi_parser_read_u32(const struct device_node *np, return -ENODEV; } +int dsi_parser_read_u32_index(const struct device_node *np, + const char *propname, u32 index, u32 *out_value) +{ + return -ENODEV; +} + static inline int dsi_parser_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz) { @@ -170,12 +178,17 @@ struct dsi_parser_utils { const char *propname, u64 *out_value); int (*read_u32)(const struct device_node *np, const char *propname, u32 *out_value); + int (*read_u32_index)(const struct device_node *np, + const char *propname, u32 index, u32 *out_value); bool (*read_bool)(const struct device_node *np, const char *propname); int (*read_u32_array)(const struct device_node *np, const char *propname, u32 *out_values, size_t sz); int (*read_string)(const struct device_node *np, const char *propname, const char **out_string); + int (*read_string_index)(const struct device_node *np, + const char *propname, + int index, const char **output); struct device_node *(*get_child_by_name)( const struct device_node *node, const char *name); @@ -186,6 +199,8 @@ struct dsi_parser_utils { struct device_node *prev); int (*count_u32_elems)(const struct device_node *np, const char *propname); + int (*count_strings)(const struct device_node *np, + const char *propname); int (*get_named_gpio)(struct device_node *np, const char *propname, int index); int (*get_available_child_count)(const struct device_node *np); @@ -198,14 +213,17 @@ static inline struct dsi_parser_utils *dsi_parser_get_of_utils(void) .read_bool = of_property_read_bool, .read_u64 = of_property_read_u64, .read_u32 = of_property_read_u32, + .read_u32_index = of_property_read_u32_index, .read_u32_array = of_property_read_u32_array, .read_string = of_property_read_string, + .read_string_index = of_property_read_string_index, .get_child_by_name = of_get_child_by_name, .get_child_count = of_get_child_count, .get_available_child_count = of_get_available_child_count, .find_property = of_find_property, .get_next_child = of_get_next_child, .count_u32_elems = of_property_count_u32_elems, + .count_strings = of_property_count_strings, .get_named_gpio = of_get_named_gpio, }; @@ -219,14 +237,17 @@ static inline struct dsi_parser_utils *dsi_parser_get_parser_utils(void) .read_bool = dsi_parser_read_bool, .read_u64 = dsi_parser_read_u64, .read_u32 = dsi_parser_read_u32, + .read_u32_index = dsi_parser_read_u32_index, .read_u32_array = dsi_parser_read_u32_array, .read_string = dsi_parser_read_string, + .read_string_index = dsi_parser_read_string_index, .get_child_by_name = dsi_parser_get_child_by_name, .get_child_count = dsi_parser_get_child_count, .get_available_child_count = dsi_parser_get_child_count, .find_property = dsi_parser_find_property, .get_next_child = dsi_parser_get_next_child, .count_u32_elems = dsi_parser_count_u32_elems, + .count_strings = dsi_parser_count_strings, .get_named_gpio = dsi_parser_get_named_gpio, }; diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 4269a83faf..57a73cc981 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -5056,6 +5056,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->has_fp16 = true; set_bit(SDE_MDP_PERIPH_TOP_0_REMOVED, &sde_cfg->mdp[0].features); sde_cfg->has_precise_vsync_ts = true; + sde_cfg->has_trusted_vm_support = true; } else { SDE_ERROR("unsupported chipset id:%X\n", hw_rev); sde_cfg->perf.min_prefill_lines = 0xffff;