//---duguowei static int mdss_dsi_regulator_init(struct platform_device *pdev) { int rc = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int i = 0; if (!pdev) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } ctrl_pdata = platform_get_drvdata(pdev); if (!ctrl_pdata) { pr_err("%s: invalid driver data\n", __func__); return -EINVAL; } for (i = 0; !rc && (i < DSI_MAX_PM); i++) { rc = msm_dss_config_vreg(&pdev->dev, ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1); if (rc) pr_err("%s: failed to init vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); } return rc; }
int dsi_ctrl_config_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int rc = 0, i; for (i = 0; i < DSI_MAX_PM; i++) { rc = mdss_dsi_get_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data[i], i); if (rc) { DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n", __func__, __mdss_dsi_pm_name(i), rc); return rc; } } rc = dsi_parse_gpio(pdev, ctrl_pdata); if (rc) { pr_err("fail to parse panel GPIOs\n"); return rc; } rc = dsi_parse_phy(pdev, ctrl_pdata); if (rc) { pr_err("fail to parse DSI PHY settings\n"); return rc; } return 0; }
static int mdss_dsi_ctrl_remove(struct platform_device *pdev) { struct msm_fb_data_type *mfd; struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev); int i = 0; if (!ctrl_pdata) { pr_err("%s: no driver data\n", __func__); return -ENODEV; } for (i = DSI_MAX_PM - 1; i >= 0; i--) { if (msm_dss_config_vreg(&pdev->dev, ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1) < 0) pr_err("%s: failed to de-init vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data[i]); } mfd = platform_get_drvdata(pdev); msm_dss_iounmap(&ctrl_pdata->mmss_misc_io); msm_dss_iounmap(&ctrl_pdata->phy_io); msm_dss_iounmap(&ctrl_pdata->ctrl_io); return 0; }
static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int i = 0; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); for (i = 0; i < DSI_MAX_PM; i++) { /* * Core power module will be enabled when the * clocks are enabled */ if (DSI_CORE_PM == i) continue; ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1); if (ret) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); goto error; } } i--; /* * If continuous splash screen feature is enabled, then we need to * request all the GPIOs that have already been configured in the * bootloader. This needs to be done irresepective of whether * the lp11_init flag is set or not. */ if (pdata->panel_info.cont_splash_enabled || !pdata->panel_info.mipi.lp11_init) { ret = mdss_dsi_panel_reset(pdata, 1); if (ret) pr_err("%s: Panel reset failed. rc=%d\n", __func__, ret); } error: if (ret) { for (; i >= 0; i--) msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); } return ret; }
static int mdss_dsi_regulator_init(struct platform_device *pdev) { int rc = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int i = 0; /* #if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_CMD_WQHD_PT_PANEL)|| \ defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_CMD_FHD_FA2_PT_PANEL) || \ defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_S6E3HA2_CMD_WQHD_PT_PANEL) || \ defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_S6E3HA2_CMD_WQXGA_PT_PANEL) struct dsi_drv_cm_data *dsi_drv = NULL; #endif */ struct dsi_drv_cm_data *dsi_drv = NULL; if (!pdev) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } ctrl_pdata = platform_get_drvdata(pdev); if (!ctrl_pdata) { pr_err("%s: invalid driver data\n", __func__); return -EINVAL; } dsi_drv = &(ctrl_pdata->shared_pdata); pr_info("mdss_dsi_regulator_init %s\n", dev_name(&pdev->dev)); dsi_drv->vdd_vreg = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(dsi_drv->vdd_vreg)) { pr_err("%s: could not get vddreg, rc=%ld\n", __func__, PTR_ERR(dsi_drv->vdd_vreg)); return PTR_ERR(dsi_drv->vdd_vreg); } else { pr_info("%s: vdd - pma8084_l22 (i/o) init.. \n", __func__); } for (i = 0; !rc && (i < DSI_MAX_PM); i++) { rc = msm_dss_config_vreg(&pdev->dev, ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1); if (rc) pr_err("%s: failed to init vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); } return rc; }
static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int i = 0; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); ret = -EINVAL; goto end; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); ret = mdss_dsi_panel_reset(pdata, 0); if (ret) { pr_warn("%s: Panel reset failed. rc=%d\n", __func__, ret); ret = 0; } for (i = DSI_MAX_PM - 1; i >= 0; i--) { /* * Core power module will be disabled when the * clocks are disabled */ if (DSI_CORE_PM == i) continue; ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); if (ret) pr_err("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); } end: return ret; }
/** * mdss_dsi_core_power_ctrl() - Enable/disable DSI core power * @ctrl: pointer to DSI controller structure * @enable: 1 to enable power, 0 to disable power * * When all DSI bus clocks are disabled, DSI core power module can be turned * off to save any leakage current. This function implements the necessary * programming sequence for the same. For command mode panels, the core power * can be turned off for idle-screen usecases, where additional programming is * needed to clamp DSI phy. */ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) { int rc = 0; struct mdss_panel_data *pdata = NULL; if (!ctrl) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } pdata = &ctrl->panel_data; if (!pdata) { pr_err("%s: Invalid panel data\n", __func__); return -EINVAL; } if (enable) { if (!ctrl->core_power) { /* enable mdss gdsc */ pr_debug("%s: Enable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 1); if (rc) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); goto error; } ctrl->core_power = true; } rc = mdss_dsi_bus_clk_start(ctrl); if (rc) { pr_err("%s: Failed to start bus clocks. rc=%d\n", __func__, rc); goto error_bus_clk_start; } /* * Phy software reset should not be done for: * 1.) Idle screen power collapse use-case. Issue a phy software * reset only when unblanking the panel in this case. * 2.) When ULPS during suspend is enabled. */ if (pdata->panel_info.blank_state == MDSS_PANEL_BLANK_BLANK && !pdata->panel_info.ulps_suspend_enabled) mdss_dsi_phy_sw_reset(ctrl); /* * Phy and controller setup need not be done during bootup * when continuous splash screen is enabled. */ if (!pdata->panel_info.cont_splash_enabled) { mdss_dsi_phy_init(ctrl); mdss_dsi_ctrl_setup(ctrl); } if (ctrl->ulps) { /* * ULPS Entry Request. This is needed if the lanes were * in ULPS prior to power collapse, since after * power collapse and reset, the DSI controller resets * back to idle state and not ULPS. This ulps entry * request will transition the state of the DSI * controller to ULPS which will match the state of the * DSI phy. This needs to be done prior to disabling * the DSI clamps. * * Also, reset the ulps flag so that ulps_config * function would reconfigure the controller state to * ULPS. */ ctrl->ulps = false; rc = mdss_dsi_ulps_config(ctrl, 1); if (rc) { pr_err("%s: Failed to enter ULPS. rc=%d\n", __func__, rc); goto error_ulps; } } rc = mdss_dsi_clamp_ctrl(ctrl, 0); if (rc) { pr_err("%s: Failed to disable dsi clamps. rc=%d\n", __func__, rc); goto error_ulps; } } else { /* * Enable DSI clamps only if entering idle power collapse or * when ULPS during suspend is enabled. */ if ((pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK) || pdata->panel_info.ulps_suspend_enabled) { rc = mdss_dsi_clamp_ctrl(ctrl, 1); if (rc) pr_err("%s: Failed to enable dsi clamps. rc=%d\n", __func__, rc); } /* * disable bus clocks irrespective of whether dsi phy was * successfully clamped or not */ mdss_dsi_bus_clk_stop(ctrl); /* disable mdss gdsc only if dsi phy was successfully clamped*/ if (rc) { pr_debug("%s: leaving mdss gdsc on\n", __func__); } else { pr_debug("%s: Disable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0); if (rc) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); rc = 0; } else { ctrl->core_power = false; } } } return rc; error_ulps: mdss_dsi_bus_clk_stop(ctrl); error_bus_clk_start: if (msm_dss_enable_vreg(ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0)) pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); else ctrl->core_power = false; error: return rc; }
static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, u8 clk_type, int enable) { int rc = 0; struct mdss_panel_data *pdata; if (!ctrl) { pr_err("%s: Invalid arg\n", __func__); return -EINVAL; } pdata = &ctrl->panel_data; pr_debug("%s: ndx=%d clk_type=%08x enable=%d\n", __func__, ctrl->ndx, clk_type, enable); if (enable) { if (clk_type & DSI_BUS_CLKS) { /* enable mdss gdsc */ pr_debug("%s: Enable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 1); if (rc) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); goto error; } rc = mdss_dsi_bus_clk_start(ctrl); if (rc) { pr_err("Failed to start bus clocks. rc=%d\n", rc); goto error_vreg; } } if (clk_type & DSI_LINK_CLKS) { rc = mdss_dsi_link_clk_start(ctrl); if (rc) { pr_err("Failed to start link clocks. rc=%d\n", rc); goto error_link_clk_start; } /* Disable ULPS, if enabled */ if (ctrl->ulps) { rc = mdss_dsi_ulps_config(ctrl, 0); if (rc) { pr_err("Failed to exit ulps. rc=%d\n", rc); goto error_ulps_exit; } } } } else { if (clk_type & DSI_LINK_CLKS) { /* * If ULPS feature is enabled, enter ULPS first. * No need to enable ULPS when turning off clocks * while blanking the panel. */ if ((mdss_dsi_ulps_feature_enabled(pdata)) && (pdata->panel_info.panel_power_on)) mdss_dsi_ulps_config(ctrl, 1); mdss_dsi_link_clk_stop(ctrl); } if (clk_type & DSI_BUS_CLKS) { mdss_dsi_bus_clk_stop(ctrl); /* disable mdss gdsc */ pr_debug("%s: Disable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0); if (rc) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); rc = 0; } } } return rc; error_ulps_exit: mdss_dsi_link_clk_stop(ctrl); error_link_clk_start: if (clk_type & DSI_BUS_CLKS) mdss_dsi_bus_clk_stop(ctrl); error_vreg: if ((clk_type & DSI_BUS_CLKS) && (msm_dss_enable_vreg(ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0))) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); } error: return rc; }
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; if (!mdss_is_ready()) { pr_err("%s: MDP not probed yet!\n", __func__); return -EPROBE_DEFER; } if (!pdev->dev.of_node) { pr_err("DSI driver only supports device tree probe\n"); return -ENOTSUPP; } pan_cfg = mdss_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; } 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_name = of_get_property(pdev->dev.of_node, "label", NULL); if (!ctrl_name) pr_info("%s:%d, DSI Ctrl name not specified\n", __func__, __LINE__); else 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__); /* Parse the regulator information */ for (i = 0; i < DSI_MAX_PM; i++) { rc = mdss_dsi_get_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data[i], i); if (rc) { DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n", __func__, __mdss_dsi_pm_name(i), rc); goto error_vreg; } } /* DSI panels can be different between controllers */ rc = mdss_dsi_get_panel_cfg(panel_cfg); 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); goto error_pan_node; } 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; } rc = dsi_panel_device_register(dsi_pan_node, ctrl_pdata); if (rc) { pr_err("%s: dsi panel dev reg failed\n", __func__); goto error_pan_node; } #ifdef CONFIG_ZTEMT_LCD_ESD_TE_CHECK /*esd check faild check,mayu add*/ //printk("lcd:%s disp_te_gpio=%d\n",__func__,ctrl_pdata->disp_te_gpio); ctrl_pdata->lcd_te_irq = gpio_to_irq(ctrl_pdata->disp_te_gpio); rc = request_irq(ctrl_pdata->lcd_te_irq, zte_lcd_te_irq_handler, \ IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "LCD_TE", ctrl_pdata); if (rc < 0) { printk("lcd:%s : request_irq failed\n", __func__); } #endif pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index); return 0; error_pan_node: of_node_put(dsi_pan_node); 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 int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata, int enable) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int i = 0; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); ret = -EINVAL; goto error; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); pr_debug("%s: enable=%d\n", __func__, enable); /* * If a dynamic mode switch is pending, the regulators should not * be turned off or on. */ if (pdata->panel_info.dynamic_switch_pending) return 0; if (enable) { for (i = 0; i < DSI_MAX_PM; i++) { /* * Core power module will be enabled when the * clocks are enabled */ if (DSI_CORE_PM == i) continue; ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1); if (ret) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); goto error_enable; } } if (!pdata->panel_info.mipi.lp11_init) { if (mdss_dsi_pinctrl_set_state(ctrl_pdata, true)) pr_debug("reset enable: pinctrl not enabled\n"); ret = mdss_dsi_panel_reset(pdata, 1); if (ret) { pr_err("%s: Panel reset failed. rc=%d\n", __func__, ret); goto error_enable; } } } else { ret = mdss_dsi_panel_reset(pdata, 0); if (ret) { pr_err("%s: Panel reset failed. rc=%d\n", __func__, ret); goto error; } if (mdss_dsi_pinctrl_set_state(ctrl_pdata, false)) pr_debug("reset disable: pinctrl not enabled\n"); for (i = DSI_MAX_PM - 1; i >= 0; i--) { /* * Core power module will be disabled when the * clocks are disabled */ if (DSI_CORE_PM == i) continue; ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); if (ret) pr_err("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); } } error_enable: if (ret) { for (; i >= 0; i--) msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); } error: return ret; }
static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int i = 0; #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) bool dsi_panel_pm_ctrl = true; if (alpm_status_func(CHECK_CURRENT_STATUS)) { dsi_panel_pm_ctrl = false; pr_info("[ALPM_DEBUG] dsi_panel_pm_ctrl : %d\n", dsi_panel_pm_ctrl); } #endif if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); ret = -EINVAL; goto end; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); #if !defined(CONFIG_SEC_KCCAT6_PROJECT) #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if(dsi_panel_pm_ctrl) #endif { ret = regulator_disable( (ctrl_pdata->shared_pdata).vdd_vreg); if (ret) { pr_err("%s: Failed to disable regulator.\n", __func__); } } #endif #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if (dsi_panel_pm_ctrl && gpio_is_valid(ctrl_pdata->disp_en_gpio)){ gpio_set_value((ctrl_pdata->disp_en_gpio), 0);/* VDDR :1.5*/ pr_info("%s: disp_en_gpio set low \n", __func__); } #else if (gpio_is_valid(ctrl_pdata->disp_en_gpio)){ gpio_set_value((ctrl_pdata->disp_en_gpio), 0);/* VDDR :1.5*/ pr_info("%s: disp_en_gpio set low \n", __func__); } #endif #if defined(CONFIG_SEC_KCCAT6_PROJECT) usleep_range(1000,1000); #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if(dsi_panel_pm_ctrl) #endif { ret = regulator_disable( (ctrl_pdata->shared_pdata).vdd_vreg); if (ret) { pr_err("%s: Failed to disable regulator.\n", __func__); } } #endif usleep_range(4000, 4000); /* #if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_S6E3HA2_CMD_WQHD_PT_PANEL) || defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_S6E3HA2_CMD_WQXGA_PT_PANEL) ctrl_pdata->panel_reset(pdata, 0); #endif */ ret = mdss_dsi_panel_reset(pdata, 0); if (ret) { pr_warn("%s: Panel reset failed. rc=%d\n", __func__, ret); ret = 0; } for (i = DSI_MAX_PM - 1; i >= 0; i--) { /* * Core power module will be disabled when the * clocks are disabled */ if (DSI_CORE_PM == i) continue; #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if ((DSI_PANEL_PM == i) && !dsi_panel_pm_ctrl) continue; #endif ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); if (ret) pr_err("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); } usleep_range(4000, 4000); end: return ret; }
static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int i = 0; #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) bool dsi_panel_pm_ctrl = true; if (alpm_status_func(CHECK_PREVIOUS_STATUS)){ dsi_panel_pm_ctrl = false; pr_info("[ALPM_DEBUG] dsi_panel_pm_ctrl : %d\n", dsi_panel_pm_ctrl); } #endif if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); for (i = 0; i < DSI_MAX_PM; i++) { /* * Core power module will be enabled when the * clocks are enabled */ if (DSI_CORE_PM == i) continue; #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if ((DSI_PANEL_PM == i) && !dsi_panel_pm_ctrl) continue; #endif ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1); if (ret) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); goto error; } } i--; usleep_range(4000, 4000); #if defined(CONFIG_SEC_KCCAT6_PROJECT) #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if(dsi_panel_pm_ctrl) #endif { ret = regulator_enable( /*VDD */ (ctrl_pdata->shared_pdata).vdd_vreg); if (ret) { pr_err("%s: Failed to enable vdd regulator.\n", __func__); return ret; } } usleep_range(1000,1000); #endif #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if (dsi_panel_pm_ctrl && gpio_is_valid(ctrl_pdata->disp_en_gpio)) { pr_info("%s : Set High LCD Enable disp_en GPIO \n", __func__); gpio_set_value((ctrl_pdata->disp_en_gpio), 1); } #else if (gpio_is_valid(ctrl_pdata->disp_en_gpio)) { pr_info("%s : Set High LCD Enable disp_en GPIO \n", __func__); gpio_set_value((ctrl_pdata->disp_en_gpio), 1); } #endif #if !defined(CONFIG_SEC_KCCAT6_PROJECT) #if defined(CONFIG_FB_MSM_MDSS_SAMSUNG) if(dsi_panel_pm_ctrl) #endif { ret = regulator_enable( /*VDD */ (ctrl_pdata->shared_pdata).vdd_vreg); if (ret) { pr_err("%s: Failed to enable vdd regulator.\n", __func__); return ret; } } #endif usleep_range(4000, 4000); #if 0 /* * If continuous splash screen feature is enabled, then we need to * request all the GPIOs that have already been configured in the * bootloader. This needs to be done irresepective of whether * the lp11_init flag is set or not. */ if (pdata->panel_info.cont_splash_enabled || !pdata->panel_info.mipi.lp11_init) { ctrl_pdata->panel_reset(pdata, 1); } #endif error: if (ret) { for (; i >= 0; i--) msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); } return ret; }
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; if (!mdss_is_ready()) { pr_err("%s: MDP not probed yet!\n", __func__); return -EPROBE_DEFER; } if (!pdev->dev.of_node) { pr_err("DSI driver only supports device tree probe\n"); return -ENOTSUPP; } pan_cfg = mdss_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; } 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_name = of_get_property(pdev->dev.of_node, "label", NULL); if (!ctrl_name) pr_info("%s:%d, DSI Ctrl name not specified\n", __func__, __LINE__); else 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__); for (i = 0; i < DSI_MAX_PM; i++) { rc = mdss_dsi_get_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data[i], i); if (rc) { DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n", __func__, __mdss_dsi_pm_name(i), rc); goto error_vreg; } } rc = mdss_dsi_get_panel_cfg(panel_cfg); if (!rc) pr_warn("%s:%d:dsi specific cfg not present\n", __func__, __LINE__); 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); goto error_pan_node; } 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; } rc = dsi_panel_device_register(dsi_pan_node, ctrl_pdata); if (rc) { pr_err("%s: dsi panel dev reg failed\n", __func__); goto error_pan_node; } pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index); return 0; error_pan_node: of_node_put(dsi_pan_node); 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 int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, u8 clk_type, int enable) { int rc = 0; struct mdss_panel_data *pdata; if (!ctrl) { pr_err("%s: Invalid arg\n", __func__); return -EINVAL; } pdata = &ctrl->panel_data; pr_debug("%s: ndx=%d clk_type=%08x enable=%d\n", __func__, ctrl->ndx, clk_type, enable); if (enable) { if (clk_type & DSI_BUS_CLKS) { /* enable mdss gdsc */ pr_debug("%s: Enable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 1); if (rc) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); goto error; } rc = mdss_dsi_bus_clk_start(ctrl); if (rc) { pr_err("Failed to start bus clocks. rc=%d\n", rc); goto error_vreg; } } if (clk_type & DSI_LINK_CLKS) { if (ctrl->mmss_clamp) { mdss_dsi_phy_init(pdata); mdss_dsi_ctrl_setup(pdata); mdss_dsi_host_init(pdata); mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode, pdata); /* * ULPS Entry Request. This is needed because, after power * collapse and reset, the DSI controller resets back to * idle state and not ULPS. */ mdss_dsi_ulps_config(ctrl, 1); mdss_dsi_clamp_ctrl(ctrl, 0); } rc = mdss_dsi_link_clk_start(ctrl); if (rc) { pr_err("Failed to start link clocks. rc=%d\n", rc); goto error_link_clk_start; } /* Disable ULPS, if enabled */ if (ctrl->ulps) { rc = mdss_dsi_ulps_config(ctrl, 0); if (rc) { pr_err("Failed to exit ulps. rc=%d\n", rc); goto error_ulps_exit; } } } } else { if (clk_type & DSI_LINK_CLKS) { /* * If ULPS feature is enabled, enter ULPS first. * No need to enable ULPS when turning off clocks * while blanking the panel. */ if (((mdss_dsi_ulps_feature_enabled(pdata)) && (pdata->panel_info.panel_power_on)) || (pdata->panel_info.ulps_suspend_enabled && !pdata->panel_info.panel_power_on)) { mdss_dsi_ulps_config(ctrl, 1); mdss_dsi_link_clk_stop(ctrl); mdss_dsi_clamp_ctrl(ctrl, 1); } else { mdss_dsi_link_clk_stop(ctrl); } } if (clk_type & DSI_BUS_CLKS) { mdss_dsi_bus_clk_stop(ctrl); /* disable mdss gdsc */ pr_debug("%s: Disable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0); if (rc) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); rc = 0; } } } return rc; error_ulps_exit: mdss_dsi_link_clk_stop(ctrl); error_link_clk_start: if (clk_type & DSI_BUS_CLKS) mdss_dsi_bus_clk_stop(ctrl); error_vreg: if ((clk_type & DSI_BUS_CLKS) && (msm_dss_enable_vreg(ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0))) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); } error: return rc; }
/** * mdss_dsi_core_power_ctrl() - Enable/disable DSI core power * @ctrl: pointer to DSI controller structure * @enable: 1 to enable power, 0 to disable power * * When all DSI bus clocks are disabled, DSI core power module can be turned * off to save any leakage current. This function implements the necessary * programming sequence for the same. For command mode panels, the core power * can be turned off for idle-screen usecases, where additional programming is * needed to clamp DSI phy. */ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) { int rc = 0; struct mdss_panel_data *pdata = NULL; u32 ctrl_rev; if (!ctrl) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } pdata = &ctrl->panel_data; if (!pdata) { pr_err("%s: Invalid panel data\n", __func__); return -EINVAL; } if (enable) { if (!ctrl->core_power) { /* enable mdss gdsc */ pr_debug("%s: Enable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 1); if (rc) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); goto error; } ctrl->core_power = true; } /* * temp workaround until framework issues pertaining to LP2 * power state transitions are fixed. For now, if we intend to * send a frame update when in LP1, we have to explicitly exit * LP2 state here */ if (mdss_dsi_is_panel_on_ulp(pdata)) mdss_dsi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_LP1); rc = mdss_dsi_bus_clk_start(ctrl); if (rc) { pr_err("%s: Failed to start bus clocks. rc=%d\n", __func__, rc); goto error_bus_clk_start; } /* * Phy and controller setup is needed if coming out of idle * power collapse with clamps enabled. */ if (ctrl->mmss_clamp) { ctrl_rev = MIPI_INP(ctrl->ctrl_base); if (ctrl_rev == MDSS_DSI_HW_REV_103) mdss_dsi_20nm_phy_init(pdata); else mdss_dsi_phy_init(pdata); mdss_dsi_ctrl_setup(ctrl); } if (ctrl->ulps) { /* * ULPS Entry Request. This is needed if the lanes were * in ULPS prior to power collapse, since after * power collapse and reset, the DSI controller resets * back to idle state and not ULPS. This ulps entry * request will transition the state of the DSI * controller to ULPS which will match the state of the * DSI phy. This needs to be done prior to disabling * the DSI clamps. * * Also, reset the ulps flag so that ulps_config * function would reconfigure the controller state to * ULPS. */ ctrl->ulps = false; rc = mdss_dsi_ulps_config(ctrl, 1); if (rc) { pr_err("%s: Failed to enter ULPS. rc=%d\n", __func__, rc); goto error_ulps; } } rc = mdss_dsi_clamp_ctrl(ctrl, 0); if (rc) { pr_err("%s: Failed to disable dsi clamps. rc=%d\n", __func__, rc); goto error_ulps; } } else { /* Enable DSI clamps only if entering idle power collapse */ if (pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK) { rc = mdss_dsi_clamp_ctrl(ctrl, 1); if (rc) pr_err("%s: Failed to enable dsi clamps. rc=%d\n", __func__, rc); } else { /* * Make sure that controller is not in ULPS state when * the DSI link is not active. */ rc = mdss_dsi_ulps_config(ctrl, 0); if (rc) pr_err("%s: failed to disable ulps. rc=%d\n", __func__, rc); } /* * disable bus clocks irrespective of whether dsi phy was * successfully clamped or not */ mdss_dsi_bus_clk_stop(ctrl); /* disable mdss gdsc only if dsi phy was successfully clamped*/ if (rc) { pr_debug("%s: leaving mdss gdsc on\n", __func__); } else { pr_debug("%s: Disable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0); if (rc) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); rc = 0; } else { ctrl->core_power = false; } } /* * temp workaround until framework issues pertaining to LP2 * power state transitions are fixed. For now, we internally * transition to LP2 state whenever core power is turned off * in LP1 state */ if (mdss_dsi_is_panel_on_lp(pdata)) mdss_dsi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_LP2); } return rc; error_ulps: mdss_dsi_bus_clk_stop(ctrl); error_bus_clk_start: if (msm_dss_enable_vreg(ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0)) pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); else ctrl->core_power = false; error: return rc; }