From ba57fd387c36bf59b43c80c63235e0c74a000386 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Tue, 27 Apr 2021 16:26:14 -0700 Subject: [PATCH 1/4] disp: msm: add helper to retrieve gpio address mappings Add helper in util to retrieve IO address mappings for a given global gpio pin. This will be used by the Trusted UI framework to secure gpio pins. Change-Id: If8ad069d724394f0772c9cf7371484a7cdc5bc78 Signed-off-by: Jeykumar Sankaran --- include/linux/sde_io_util.h | 1 + msm/sde_io_util.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/linux/sde_io_util.h b/include/linux/sde_io_util.h index 8bca51e522..76b1f2a808 100644 --- a/include/linux/sde_io_util.h +++ b/include/linux/sde_io_util.h @@ -107,6 +107,7 @@ int msm_dss_get_io_mem(struct platform_device *pdev, void msm_dss_clean_io_mem(struct list_head *mem_list); int msm_dss_get_pmic_io_mem(struct platform_device *pdev, struct list_head *mem_list); +int msm_dss_get_gpio_io_mem(const int gpio_pin, struct list_head *mem_list); int msm_dss_get_io_irq(struct platform_device *pdev, struct list_head *irq_list, u32 label); void msm_dss_clean_io_irq(struct list_head *irq_list); diff --git a/msm/sde_io_util.c b/msm/sde_io_util.c index b8b9fb8f25..d15b9cdbe0 100644 --- a/msm/sde_io_util.c +++ b/msm/sde_io_util.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,40 @@ void msm_dss_iounmap(struct dss_io_data *io_data) } /* msm_dss_iounmap */ EXPORT_SYMBOL(msm_dss_iounmap); +int msm_dss_get_gpio_io_mem(const int gpio_pin, struct list_head *mem_list) +{ + struct msm_io_mem_entry *io_mem; + struct resource res; + bool gpio_pin_status = false; + int rc = 0; + + if (!gpio_is_valid(gpio_pin)) + return -EINVAL; + + io_mem = kzalloc(sizeof(struct msm_io_mem_entry), GFP_KERNEL); + if (!io_mem) + return -ENOMEM; + + gpio_pin_status = msm_gpio_get_pin_address(gpio_pin, &res); + if (!gpio_pin_status) { + rc = -ENODEV; + goto parse_fail; + } + + io_mem->base = res.start; + io_mem->size = resource_size(&res); + + list_add(&io_mem->list, mem_list); + + return 0; + +parse_fail: + kfree(io_mem); + + return rc; +} +EXPORT_SYMBOL(msm_dss_get_gpio_io_mem); + int msm_dss_get_pmic_io_mem(struct platform_device *pdev, struct list_head *mem_list) { From 77d648442fc147b79339ca9cac7048db61a1a457 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Tue, 27 Apr 2021 16:44:18 -0700 Subject: [PATCH 2/4] disp: msm: dsi: implement ESD trigger for trusted vm DSI driver stubs out GPIO parsing in trusted vm. Add support for ESD trigger in trusted vm by explicitly parsing the reset gpio and setting the value. Change-Id: I8c04e4b27b234eb236ec51df633c06738f2a5c96 Signed-off-by: Jeykumar Sankaran --- msm/dsi/dsi_display.c | 5 ++- msm/dsi/dsi_panel.c | 87 +++++++++++++++++++++++++------------------ msm/dsi/dsi_panel.h | 3 +- 3 files changed, 54 insertions(+), 41 deletions(-) diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index a9e0d3cac4..155111f5b7 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -1660,9 +1660,10 @@ static ssize_t debugfs_esd_trigger_check(struct file *file, } if (display->esd_trigger) { + struct dsi_panel *panel = display->panel; + DSI_INFO("ESD attack triggered by user\n"); - rc = dsi_panel_trigger_esd_attack(display->panel, - display->trusted_vm_env); + rc = panel->panel_ops.trigger_esd_attack(panel); if (rc) { DSI_ERR("Failed to trigger ESD attack\n"); goto error; diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 4948fee514..7b6ba80fc2 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -193,47 +193,14 @@ static int dsi_panel_gpio_release(struct dsi_panel *panel) return rc; } -int dsi_panel_trigger_esd_attack(struct dsi_panel *panel, bool trusted_vm_env) +static int dsi_panel_trigger_esd_attack_sub(int reset_gpio) { - if (!panel) { - DSI_ERR("Invalid panel param\n"); + if (!gpio_is_valid(reset_gpio)) { + DSI_INFO("failed to pull down the reset gpio\n"); return -EINVAL; } - /* toggle reset-gpio by writing directly to register in trusted-vm */ - if (trusted_vm_env) { - struct dsi_tlmm_gpio *gpio = NULL; - void __iomem *io; - u32 offset = 0x4; - int i; - - for (i = 0; i < panel->tlmm_gpio_count; i++) - if (!strcmp(panel->tlmm_gpio[i].name, "reset-gpio")) - gpio = &panel->tlmm_gpio[i]; - - if (!gpio) { - DSI_ERR("reset gpio not found\n"); - return -EINVAL; - } - - io = ioremap(gpio->addr, gpio->size); - writel_relaxed(0, io + offset); - iounmap(io); - - } else { - struct dsi_panel_reset_config *r_config = &panel->reset_config; - - if (!r_config) { - DSI_ERR("Invalid panel reset configuration\n"); - return -EINVAL; - } - - if (!gpio_is_valid(r_config->reset_gpio)) { - DSI_ERR("failed to pull down gpio\n"); - return -EINVAL; - } - gpio_set_value(r_config->reset_gpio, 0); - } + gpio_set_value(reset_gpio, 0); SDE_EVT32(SDE_EVTLOG_FUNC_CASE1); DSI_INFO("GPIO pulled low to simulate ESD\n"); @@ -241,6 +208,50 @@ int dsi_panel_trigger_esd_attack(struct dsi_panel *panel, bool trusted_vm_env) return 0; } +static int dsi_panel_vm_trigger_esd_attack(struct dsi_panel *panel) +{ + struct dsi_parser_utils *utils = &panel->utils; + int reset_gpio; + int rc = 0; + + reset_gpio = utils->get_named_gpio(utils->data, + "qcom,platform-reset-gpio", 0); + if (!gpio_is_valid(reset_gpio)) { + DSI_ERR("[%s] reset gpio not provided\n", panel->name); + return -EINVAL; + } + + rc = gpio_request(reset_gpio, "reset_gpio"); + if (rc) { + DSI_ERR("request for reset_gpio failed, rc=%d\n", rc); + return rc; + } + + rc = dsi_panel_trigger_esd_attack_sub(reset_gpio); + + gpio_free(reset_gpio); + + return rc; +} + +static int dsi_panel_trigger_esd_attack(struct dsi_panel *panel) +{ + struct dsi_panel_reset_config *r_config; + + if (!panel) { + DSI_ERR("Invalid panel param\n"); + return -EINVAL; + } + + r_config = &panel->reset_config; + if (!r_config) { + DSI_ERR("Invalid panel reset configuration\n"); + return -EINVAL; + } + + return dsi_panel_trigger_esd_attack_sub(r_config->reset_gpio); +} + static int dsi_panel_reset(struct dsi_panel *panel) { int rc = 0; @@ -3485,6 +3496,7 @@ static void dsi_panel_setup_vm_ops(struct dsi_panel *panel, bool trusted_vm_env) panel->panel_ops.bl_unregister = dsi_panel_vm_stub; panel->panel_ops.parse_gpios = dsi_panel_vm_stub; panel->panel_ops.parse_power_cfg = dsi_panel_vm_stub; + panel->panel_ops.trigger_esd_attack = dsi_panel_vm_trigger_esd_attack; } else { panel->panel_ops.pinctrl_init = dsi_panel_pinctrl_init; panel->panel_ops.gpio_request = dsi_panel_gpio_request; @@ -3494,6 +3506,7 @@ static void dsi_panel_setup_vm_ops(struct dsi_panel *panel, bool trusted_vm_env) panel->panel_ops.bl_unregister = dsi_panel_bl_unregister; panel->panel_ops.parse_gpios = dsi_panel_parse_gpios; panel->panel_ops.parse_power_cfg = dsi_panel_parse_power_cfg; + panel->panel_ops.trigger_esd_attack = dsi_panel_trigger_esd_attack; } } diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index a9cd767a01..918e406568 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -209,6 +209,7 @@ struct dsi_panel_ops { int (*bl_unregister)(struct dsi_panel *panel); int (*parse_gpios)(struct dsi_panel *panel); int (*parse_power_cfg)(struct dsi_panel *panel); + int (*trigger_esd_attack)(struct dsi_panel *panel); }; struct dsi_panel { @@ -310,8 +311,6 @@ struct dsi_panel *dsi_panel_get(struct device *parent, int topology_override, bool trusted_vm_env); -int dsi_panel_trigger_esd_attack(struct dsi_panel *panel, bool trusted_vm_env); - void dsi_panel_put(struct dsi_panel *panel); int dsi_panel_drv_init(struct dsi_panel *panel, struct mipi_dsi_host *host); From 5ec8dc1afce5a60be32ffcfb3c86c116a4a5302c Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Tue, 27 Apr 2021 16:46:31 -0700 Subject: [PATCH 3/4] disp: msm: dsi: update gpio mappings using tlmm api Use tlmm api to retrieve and populate address mappings of the panel gpio pins participating in the VM swtich on Trusted UI. Change-Id: Ibf2d13eac3fe907b729f4c2b54c63a3808022583 Signed-off-by: Jeykumar Sankaran --- msm/dsi/dsi_display.c | 35 +++++++++++++++-- msm/dsi/dsi_panel.c | 88 +++++-------------------------------------- msm/dsi/dsi_panel.h | 10 ----- 3 files changed, 41 insertions(+), 92 deletions(-) diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 155111f5b7..b87d1cad91 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -5443,22 +5443,49 @@ static int dsi_display_get_io_resources(struct msm_io_res *io_res, void *data) { int rc = 0; struct dsi_display *display; + struct platform_device *pdev; + int te_gpio, avdd_gpio; if (!data) return -EINVAL; + display = (struct dsi_display *)data; + + pdev = display->pdev; + if (!pdev) + return -EINVAL; + rc = dsi_ctrl_get_io_resources(io_res); if (rc) - goto end; + return rc; rc = dsi_phy_get_io_resources(io_res); if (rc) - goto end; + return rc; - display = (struct dsi_display *)data; rc = dsi_panel_get_io_resources(display->panel, io_res); + if (rc) + return rc; + + te_gpio = of_get_named_gpio(pdev->dev.of_node, "qcom,platform-te-gpio", 0); + if (gpio_is_valid(te_gpio)) { + rc = msm_dss_get_gpio_io_mem(te_gpio, &io_res->mem); + if (rc) { + DSI_ERR("[%s] failed to retrieve the te gpio address\n", + display->panel->name); + return rc; + } + } + + avdd_gpio = of_get_named_gpio(pdev->dev.of_node, + "qcom,avdd-regulator-gpio", 0); + if (gpio_is_valid(avdd_gpio)) { + rc = msm_dss_get_gpio_io_mem(avdd_gpio, &io_res->mem); + if (rc) + DSI_ERR("[%s] failed to retrieve the avdd gpio address\n", + display->panel->name); + } -end: return rc; } diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 7b6ba80fc2..9c5d62d5fe 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -2217,34 +2217,21 @@ error: int dsi_panel_get_io_resources(struct dsi_panel *panel, struct msm_io_res *io_res) { - struct list_head temp_head; - struct msm_io_mem_entry *io_mem, *pos, *tmp; + struct dsi_parser_utils *utils = &panel->utils; struct list_head *mem_list = &io_res->mem; - int i, rc = 0; + int reset_gpio; + int rc = 0; - INIT_LIST_HEAD(&temp_head); - - for (i = 0; i < panel->tlmm_gpio_count; i++) { - io_mem = kzalloc(sizeof(*io_mem), GFP_KERNEL); - if (!io_mem) { - rc = -ENOMEM; - goto parse_fail; + reset_gpio = utils->get_named_gpio(utils->data, + "qcom,platform-reset-gpio", 0); + if (gpio_is_valid(reset_gpio)) { + rc = msm_dss_get_gpio_io_mem(reset_gpio, mem_list); + if (rc) { + DSI_ERR("[%s] failed to retrieve the reset gpio address\n", panel->name); + goto end; } - - io_mem->base = panel->tlmm_gpio[i].addr; - io_mem->size = panel->tlmm_gpio[i].size; - - list_add(&io_mem->list, &temp_head); } - list_splice(&temp_head, mem_list); - goto end; - -parse_fail: - list_for_each_entry_safe(pos, tmp, &temp_head, list) { - list_del(&pos->list); - kfree(pos); - } end: return rc; } @@ -2333,54 +2320,6 @@ error: return rc; } -static int dsi_panel_parse_tlmm_gpio(struct dsi_panel *panel) -{ - struct dsi_parser_utils *utils = &panel->utils; - u32 base, size, pin; - int pin_count, address_count, name_count, i; - - 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; - } - - utils->read_u32_index(utils->data, - "qcom,dsi-panel-gpio-address", 0, &base); - utils->read_u32_index(utils->data, - "qcom,dsi-panel-gpio-address", 1, &size); - - pin_count = utils->count_u32_elems(utils->data, - "qcom,dsi-panel-gpio-pins"); - 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"); - return -EINVAL; - } - - panel->tlmm_gpio = kcalloc(pin_count, - sizeof(struct dsi_tlmm_gpio), GFP_KERNEL); - if (!panel->tlmm_gpio) - return -ENOMEM; - - panel->tlmm_gpio_count = pin_count; - for (i = 0; i < pin_count; i++) { - 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; - - utils->read_string_index(utils->data, - "qcom,dsi-panel-gpio-names", i, - &(panel->tlmm_gpio[i].name)); - } - - return 0; -} - static int dsi_panel_parse_bl_pwm_config(struct dsi_panel *panel) { int rc = 0; @@ -3591,12 +3530,6 @@ struct dsi_panel *dsi_panel_get(struct device *parent, goto error; } - rc = dsi_panel_parse_tlmm_gpio(panel); - if (rc) { - DSI_ERR("failed to parse panel tlmm gpios, rc=%d\n", rc); - goto error; - } - rc = panel->panel_ops.parse_power_cfg(panel); if (rc) DSI_ERR("failed to parse power config, rc=%d\n", rc); @@ -3752,7 +3685,6 @@ int dsi_panel_drv_deinit(struct dsi_panel *panel) if (rc) DSI_ERR("[%s] failed to put regs, rc=%d\n", panel->name, rc); - kfree(panel->tlmm_gpio); panel->host = NULL; memset(&panel->mipi_device, 0x0, sizeof(panel->mipi_device)); diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index 918e406568..72e66f490f 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -191,13 +191,6 @@ struct dsi_panel_spr_info { enum msm_display_spr_pack_type pack_type; }; -struct dsi_tlmm_gpio { - u32 num; - u32 addr; - u32 size; - const char *name; -}; - struct dsi_panel; struct dsi_panel_ops { @@ -273,9 +266,6 @@ struct dsi_panel { int power_mode; enum dsi_panel_physical_type panel_type; - struct dsi_tlmm_gpio *tlmm_gpio; - u32 tlmm_gpio_count; - struct dsi_panel_ops panel_ops; }; From 7a112bb7440cec43ca5378d346a6465b02cf7152 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Sat, 29 May 2021 00:25:07 -0700 Subject: [PATCH 4/4] disp: msm: sde: add explicit sub-driver mappings for TVM TUI clients are the display sub-drivers that participate during the TUI transition. They register with the display TUI notification framework with a list of callbacks functions that will be invoked during pre/post transitions and for quering I/O memory that need to be access controlled. This change adds RSC to the TUI client list. In Trusted VM, all the sub-drivers are not enabled to avoid any re-configuration of respective module registers. But the TUI framework need to know the sub-driver I/O memory ranges in order to accept the I/O memory list lent by the HLOS VM. So, SDE provides them ranges by reading from a custom devicetree property. Change-Id: I2c4b254d539d04771339ae4a7bf4d296b7a7f91a Signed-off-by: Jeykumar Sankaran --- msm/sde/sde_hw_catalog.c | 12 ++++++++++++ msm/sde/sde_hw_catalog.h | 7 +++++++ msm/sde/sde_kms.c | 38 ++++++++++++++++++++++++++++++++++++++ msm/sde_rsc.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index fe163162c9..ec8c941515 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -210,6 +210,7 @@ enum sde_prop { BASE_LAYER, TRUSTED_VM_ENV, MAX_TRUSTED_VM_DISPLAYS, + TVM_INCLUDE_REG, SDE_PROP_MAX, }; @@ -598,6 +599,7 @@ static struct sde_prop_type sde_prop[] = { {TRUSTED_VM_ENV, "qcom,sde-trusted-vm-env", false, PROP_TYPE_BOOL}, {MAX_TRUSTED_VM_DISPLAYS, "qcom,sde-max-trusted-vm-displays", false, PROP_TYPE_U32}, + {TVM_INCLUDE_REG, "qcom,tvm-include-reg", false, PROP_TYPE_U32_ARRAY}, }; static struct sde_prop_type sde_perf_prop[] = { @@ -3965,6 +3967,16 @@ static void _sde_top_parse_dt_helper(struct sde_mdss_cfg *cfg, 0); cfg->max_trusted_vm_displays = PROP_VALUE_ACCESS(props->values, MAX_TRUSTED_VM_DISPLAYS, 0); + if (props->exists[TVM_INCLUDE_REG]) { + cfg->tvm_reg_count = props->counts[TVM_INCLUDE_REG] / 2; + for (i = 0; i < cfg->tvm_reg_count; i++) { + cfg->tvm_reg[i].start = PROP_VALUE_ACCESS(props->values, + TVM_INCLUDE_REG, i * 2); + cfg->tvm_reg[i].end = cfg->tvm_reg[i].start + + PROP_VALUE_ACCESS(props->values, TVM_INCLUDE_REG, + i * 2 + 1); + } + } } static int sde_top_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 61256b139c..c1fef54e12 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -19,6 +19,7 @@ * based on current design */ #define MAX_BLOCKS 12 +#define MAX_REG_SIZE_ENTRIES 14 #define SDE_HW_VER(MAJOR, MINOR, STEP) ((u32)((MAJOR & 0xF) << 28) |\ ((MINOR & 0xFFF) << 16) |\ @@ -1472,6 +1473,10 @@ struct sde_perf_cfg { * the trusted VM. false, otherwise. * @max_trusted_vm_displays maximum number of concurrent trusted * vm displays supported. + * @tvm_reg_count number of sub-driver register ranges that need to be included + * for trusted vm for accepting the resources + * @tvm_reg array of sub-driver register ranges entries that need to be + * included * @max_sspp_linewidth max source pipe line width support. * @vig_sspp_linewidth max vig source pipe line width support. * @scaling_linewidth max vig source pipe linewidth for scaling usecases @@ -1561,6 +1566,8 @@ struct sde_mdss_cfg { u32 hwversion; bool trusted_vm_env; u32 max_trusted_vm_displays; + u32 tvm_reg_count; + struct resource tvm_reg[MAX_REG_SIZE_ENTRIES]; u32 max_sspp_linewidth; u32 vig_sspp_linewidth; diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index a6020506c0..7be4982f92 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -4583,6 +4583,38 @@ power_error: return rc; } +int _sde_kms_get_tvm_inclusion_mem(struct sde_mdss_cfg *catalog, struct list_head *mem_list) +{ + struct list_head temp_head; + struct msm_io_mem_entry *io_mem; + int rc, i = 0; + + INIT_LIST_HEAD(&temp_head); + + for (i = 0; i < catalog->tvm_reg_count; i++) { + struct resource *res = &catalog->tvm_reg[i]; + + io_mem = kzalloc(sizeof(struct msm_io_mem_entry), GFP_KERNEL); + if (!io_mem) { + rc = -ENOMEM; + goto parse_fail; + } + + io_mem->base = res->start; + io_mem->size = resource_size(res); + + list_add(&io_mem->list, &temp_head); + } + + list_splice(&temp_head, mem_list); + + return 0; +parse_fail: + msm_dss_clean_io_mem(&temp_head); + + return rc; +} + int sde_kms_get_io_resources(struct sde_kms *sde_kms, struct msm_io_res *io_res) { struct platform_device *pdev = to_platform_device(sde_kms->dev->dev); @@ -4606,6 +4638,12 @@ int sde_kms_get_io_resources(struct sde_kms *sde_kms, struct msm_io_res *io_res) return rc; } + rc = _sde_kms_get_tvm_inclusion_mem(sde_kms->catalog, &io_res->mem); + if (rc) { + SDE_ERROR("failed to get tvm inclusion mem ranges"); + return rc; + } + return rc; } diff --git a/msm/sde_rsc.c b/msm/sde_rsc.c index 790592dc4a..afe39256d4 100644 --- a/msm/sde_rsc.c +++ b/msm/sde_rsc.c @@ -1597,6 +1597,28 @@ static void sde_rsc_deinit(struct platform_device *pdev, kfree(rsc); } +/** + * sde_rsc_get_io_resources - collect register ranges for the device to + * perform access control on TUI transition + * @io_res: io resource list + * @data: payload data provided during msm_register_vm_event + * Returns: zero on success + */ +static int sde_rsc_get_io_resources(struct msm_io_res *io_res, void *data) +{ + int rc = 0; + struct sde_rsc_priv *rsc = (struct sde_rsc_priv *)data; + struct platform_device *pdev = to_platform_device(rsc->dev); + + rc = msm_dss_get_io_mem(pdev, &io_res->mem); + if (rc) { + pr_err("failed to get rsc io mem, rc = %d\n", rc); + return rc; + } + + return 0; +} + /** * sde_rsc_bind - bind rsc device with controlling device * @dev: Pointer to base of platform device @@ -1611,6 +1633,9 @@ static int sde_rsc_bind(struct device *dev, struct sde_rsc_priv *rsc; struct drm_device *drm; struct platform_device *pdev = to_platform_device(dev); + struct msm_vm_ops vm_event_ops = { + .vm_get_io_resources = sde_rsc_get_io_resources, + }; if (!dev || !pdev || !master) { pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n", @@ -1630,6 +1655,9 @@ static int sde_rsc_bind(struct device *dev, rsc->drv_io.len, msm_get_phys_addr(pdev, "drv"), SDE_DBG_RSC); sde_dbg_reg_register_base(SDE_RSC_WRAPPER_DBG_NAME, rsc->wrapper_io.base, rsc->wrapper_io.len, msm_get_phys_addr(pdev, "wrapper"), SDE_DBG_RSC); + + msm_register_vm_event(master, dev, &vm_event_ops, (void *)rsc); + return 0; } @@ -1655,6 +1683,8 @@ static void sde_rsc_unbind(struct device *dev, pr_err("invalid display rsc\n"); return; } + + msm_unregister_vm_event(master, dev); } static const struct component_ops sde_rsc_comp_ops = {