From b87a34af2cd7cd8aed83524d447b1c0e039c8554 Mon Sep 17 00:00:00 2001 From: Demon000 Date: Sun, 29 May 2022 22:47:37 +0100 Subject: [PATCH] techpack: display: Implement doze mode --- techpack/display/msm/dsi/dsi_display.c | 117 +++++++++++++++++++++++++ techpack/display/msm/dsi/dsi_panel.c | 58 ++++++++++++ techpack/display/msm/dsi/dsi_panel.h | 11 +++ 3 files changed, 186 insertions(+) diff --git a/techpack/display/msm/dsi/dsi_display.c b/techpack/display/msm/dsi/dsi_display.c index c1a7b4310e3c..d44394359338 100644 --- a/techpack/display/msm/dsi/dsi_display.c +++ b/techpack/display/msm/dsi/dsi_display.c @@ -5047,6 +5047,121 @@ error: return rc; } +static ssize_t sysfs_doze_status_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dsi_display *display; + struct dsi_panel *panel; + bool status; + + display = dev_get_drvdata(dev); + if (!display) { + pr_err("Invalid display\n"); + return -EINVAL; + } + + panel = display->panel; + + mutex_lock(&panel->panel_lock); + status = panel->doze_enabled; + mutex_unlock(&panel->panel_lock); + + return snprintf(buf, PAGE_SIZE, "%d\n", status); +} + +static ssize_t sysfs_doze_status_write(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct dsi_display *display; + struct dsi_panel *panel; + bool status; + int rc = 0; + + display = dev_get_drvdata(dev); + if (!display) { + pr_err("Invalid display\n"); + return -EINVAL; + } + + rc = kstrtobool(buf, &status); + if (rc) { + pr_err("%s: kstrtobool failed. rc=%d\n", __func__, rc); + return rc; + } + + panel = display->panel; + + mutex_lock(&panel->panel_lock); + dsi_panel_set_doze_status(panel, status); + mutex_unlock(&panel->panel_lock); + + return count; +} + +static ssize_t sysfs_doze_mode_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + enum dsi_doze_mode_type doze_mode; + struct dsi_display *display; + struct dsi_panel *panel; + + display = dev_get_drvdata(dev); + if (!display) { + pr_err("Invalid display\n"); + return -EINVAL; + } + + panel = display->panel; + + mutex_lock(&panel->panel_lock); + doze_mode = panel->doze_mode; + mutex_unlock(&panel->panel_lock); + + return snprintf(buf, PAGE_SIZE, "%d\n", doze_mode); +} + +static ssize_t sysfs_doze_mode_write(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct dsi_display *display; + struct dsi_panel *panel; + int rc = 0; + int mode; + + display = dev_get_drvdata(dev); + if (!display) { + pr_err("Invalid display\n"); + return -EINVAL; + } + + rc = kstrtoint(buf, 10, &mode); + if (rc) { + pr_err("%s: kstrtoint failed. rc=%d\n", __func__, rc); + return rc; + } + + if (mode < DSI_DOZE_LPM || mode > DSI_DOZE_HBM) { + pr_err("%s: invalid value for doze mode\n", __func__); + return -EINVAL; + } + + panel = display->panel; + + mutex_lock(&panel->panel_lock); + dsi_panel_set_doze_mode(panel, (enum dsi_doze_mode_type) mode); + mutex_unlock(&panel->panel_lock); + + return count; +} + +static DEVICE_ATTR(doze_status, 0644, + sysfs_doze_status_read, + sysfs_doze_status_write); + +static DEVICE_ATTR(doze_mode, 0644, + sysfs_doze_mode_read, + sysfs_doze_mode_write); + static ssize_t sysfs_dynamic_dsi_clk_read(struct device *dev, struct device_attribute *attr, char *buf) { @@ -5213,6 +5328,8 @@ static DEVICE_ATTR(dimlayer_exposure, 0644, #endif static struct attribute *display_fs_attrs[] = { + &dev_attr_doze_status.attr, + &dev_attr_doze_mode.attr, &dev_attr_fod_ui.attr, #ifdef CONFIG_DRM_SDE_EXPO &dev_attr_dimlayer_exposure.attr, diff --git a/techpack/display/msm/dsi/dsi_panel.c b/techpack/display/msm/dsi/dsi_panel.c index b40667096de6..1b121c58e3bc 100644 --- a/techpack/display/msm/dsi/dsi_panel.c +++ b/techpack/display/msm/dsi/dsi_panel.c @@ -785,6 +785,50 @@ error: return rc; } +int dsi_panel_update_doze(struct dsi_panel *panel) { + int rc = 0; + + if (panel->doze_enabled && panel->doze_mode == DSI_DOZE_HBM) { + rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_MI_DOZE_HBM); + if (rc) + pr_err("[%s] failed to send DSI_CMD_SET_DOZE_HBM cmd, rc=%d\n", + panel->name, rc); + } else if (panel->doze_enabled && panel->doze_mode == DSI_DOZE_LPM) { + rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_MI_DOZE_LBM); + if (rc) + pr_err("[%s] failed to send DSI_CMD_SET_DOZE_LBM cmd, rc=%d\n", + panel->name, rc); + } else if (!panel->doze_enabled) { + rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_NOLP); + if (rc) + pr_err("[%s] failed to send DSI_CMD_SET_NOLP cmd, rc=%d\n", + panel->name, rc); + } + + return rc; +} + +int dsi_panel_set_doze_status(struct dsi_panel *panel, bool status) { + if (panel->doze_enabled == status) + return 0; + + panel->doze_enabled = status; + + return dsi_panel_update_doze(panel); +} + +int dsi_panel_set_doze_mode(struct dsi_panel *panel, enum dsi_doze_mode_type mode) { + if (panel->doze_mode == mode) + return 0; + + panel->doze_mode = mode; + + if (!panel->doze_enabled) + return 0; + + return dsi_panel_update_doze(panel); +} + bool dc_skip_set_backlight(struct dsi_panel *panel, u32 bl_lvl) { struct dsi_panel_mi_cfg *mi_cfg = &panel->mi_cfg; @@ -3867,6 +3911,9 @@ struct dsi_panel *dsi_panel_get(struct device *parent, if (rc) DSI_DEBUG("failed to parse mi config, rc=%d\n", rc); + panel->doze_mode = DSI_DOZE_LPM; + panel->doze_enabled = false; + panel->power_mode = SDE_MODE_DPMS_OFF; drm_panel_init(&panel->drm_panel); panel->drm_panel.dev = &panel->mipi_device.dev; @@ -4484,6 +4531,9 @@ int dsi_panel_set_lp1(struct dsi_panel *panel) DSI_ERR("[%s] failed to send DSI_CMD_SET_LP1 cmd, rc=%d\n", panel->name, rc); + rc = dsi_panel_set_doze_status(panel, true); + if (rc) + pr_err("unable to set doze on\n"); exit: mutex_unlock(&panel->panel_lock); display_utc_time_marker("DSI_CMD_SET_LP1"); @@ -4511,6 +4561,9 @@ int dsi_panel_set_lp2(struct dsi_panel *panel) DSI_ERR("[%s] failed to send DSI_CMD_SET_LP2 cmd, rc=%d\n", panel->name, rc); + rc = dsi_panel_set_doze_status(panel, true); + if (rc) + pr_err("unable to set doze on\n"); exit: mutex_unlock(&panel->panel_lock); display_utc_time_marker("DSI_CMD_SET_LP2"); @@ -4554,6 +4607,10 @@ int dsi_panel_set_nolp(struct dsi_panel *panel) DSI_ERR("[%s] failed to send DSI_CMD_SET_NOLP cmd, rc=%d\n", panel->name, rc); + rc = dsi_panel_set_doze_status(panel, false); + if (rc) + pr_err("unable to set doze on\n"); + mi_cfg->dimming_state = STATE_DIM_RESTORE; if (mi_cfg->dc_type == 0 && mi_cfg->dc_enable) { @@ -5179,6 +5236,7 @@ int dsi_panel_disable(struct dsi_panel *panel) } panel->panel_initialized = false; panel->power_mode = SDE_MODE_DPMS_OFF; + panel->doze_enabled = false; host = panel->host; if (host && mi_cfg->fod_hbm_enabled) { diff --git a/techpack/display/msm/dsi/dsi_panel.h b/techpack/display/msm/dsi/dsi_panel.h index d2bd856ee496..072432952372 100644 --- a/techpack/display/msm/dsi/dsi_panel.h +++ b/techpack/display/msm/dsi/dsi_panel.h @@ -52,6 +52,11 @@ enum dsi_backlight_type { DSI_BACKLIGHT_MAX, }; +enum dsi_doze_mode_type { + DSI_DOZE_LPM = 0, + DSI_DOZE_HBM, +}; + enum bl_update_flag { BL_UPDATE_DELAY_UNTIL_FIRST_FRAME, BL_UPDATE_NONE, @@ -235,6 +240,9 @@ struct dsi_panel { int power_mode; enum dsi_panel_physical_type panel_type; + bool doze_enabled; + enum dsi_doze_mode_type doze_mode; + struct brightness_alpha_pair *fod_dim_lut; u32 fod_dim_lut_count; #ifdef CONFIG_DRM_SDE_EXPO @@ -380,4 +388,7 @@ int dsi_panel_set_fod_hbm(struct dsi_panel *panel, bool status); u32 dsi_panel_get_fod_dim_alpha(struct dsi_panel *panel); +int dsi_panel_set_doze_status(struct dsi_panel *panel, bool status); + +int dsi_panel_set_doze_mode(struct dsi_panel *panel, enum dsi_doze_mode_type mode); #endif /* _DSI_PANEL_H_ */