diff options
| -rw-r--r-- | Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/Makefile | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_display.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 41 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_panel.h | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_backlight.c | 103 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_backlight.h | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_connector.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_connector.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_kms.c | 1 |
11 files changed, 193 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index 9fc942cc627d..1fffb617248a 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -538,6 +538,7 @@ Example: qcom,mdss-dsi-underflow-color = <0xff>; qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = < 15>; + qcom,mdss-brightness-max-level = <255>; qcom,mdss-dsi-interleave-mode = <0>; qcom,mdss-dsi-panel-type = "dsi_video_mode"; qcom,mdss-dsi-te-check-enable; diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 8a534316e240..f756c0c59ffa 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -41,6 +41,7 @@ msm_drm-y := \ sde/sde_kms.o \ sde/sde_plane.o \ sde/sde_connector.o \ + sde/sde_backlight.o \ sde/sde_color_processing.o \ sde/sde_vbif.o diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 825bf2dc3ec1..5a166a4bae93 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -36,6 +36,24 @@ static const struct of_device_id dsi_display_dt_match[] = { static struct dsi_display *main_display; +int dsi_display_set_backlight(void *display, u32 bl_lvl) +{ + struct dsi_display *dsi_display = display; + struct dsi_panel *panel; + int rc = 0; + + if (dsi_display == NULL) + return -EINVAL; + + panel = dsi_display->panel; + + rc = dsi_panel_set_backlight(panel, bl_lvl); + if (rc) + pr_err("unable to set backlight\n"); + + return rc; +} + static ssize_t debugfs_dump_info_read(struct file *file, char __user *buff, size_t count, diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h index 813e7e385076..b77bf268dbd1 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h @@ -332,4 +332,5 @@ int dsi_display_set_tpg_state(struct dsi_display *display, bool enable); int dsi_display_clock_gate(struct dsi_display *display, bool enable); int dsi_dispaly_static_frame(struct dsi_display *display, bool enable); +int dsi_display_set_backlight(void *display, u32 bl_lvl); #endif /* _DSI_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 6e753f08a77e..28cfa1fba6d9 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -358,6 +358,23 @@ static int dsi_panel_led_bl_register(struct dsi_panel *panel, } #endif +int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl) +{ + int rc = 0; + struct dsi_backlight_config *bl = &panel->bl_config; + + switch (bl->type) { + case DSI_BACKLIGHT_WLED: + led_trigger_event(bl->wled, bl_lvl); + break; + default: + pr_err("Backlight type(%d) not supported\n", bl->type); + rc = -ENOTSUPP; + } + + return rc; +} + static int dsi_panel_bl_register(struct dsi_panel *panel) { int rc = 0; @@ -1423,18 +1440,28 @@ static int dsi_panel_parse_bl_config(struct dsi_panel *panel, if (rc) { pr_debug("[%s] bl-min-level unspecified, defaulting to zero\n", panel->name); - panel->bl_config.min_level = 0; + panel->bl_config.bl_min_level = 0; } else { - panel->bl_config.min_level = val; + panel->bl_config.bl_min_level = val; } rc = of_property_read_u32(of_node, "qcom,mdss-dsi-bl-max-level", &val); if (rc) { - pr_debug("[%s] bl-max-level unspecified, defaulting to 255\n", + pr_debug("[%s] bl-max-level unspecified, defaulting to max level\n", + panel->name); + panel->bl_config.bl_max_level = MAX_BL_LEVEL; + } else { + panel->bl_config.bl_max_level = val; + } + + rc = of_property_read_u32(of_node, "qcom,mdss-brightness-max-level", + &val); + if (rc) { + pr_debug("[%s] brigheness-max-level unspecified, defaulting to 255\n", panel->name); - panel->bl_config.max_level = 255; + panel->bl_config.brightness_max_level = 255; } else { - panel->bl_config.max_level = val; + panel->bl_config.brightness_max_level = val; } if (panel->bl_config.type == DSI_BACKLIGHT_PWM) { @@ -1834,8 +1861,6 @@ int dsi_panel_enable(struct dsi_panel *panel) pr_err("[%s] failed to send DSI_CMD_SET_ON cmds, rc=%d\n", panel->name, rc); } - /* TODO: hack to enable backlight; */ - led_trigger_event(panel->bl_config.wled, panel->bl_config.max_level); mutex_unlock(&panel->panel_lock); return rc; } @@ -1873,8 +1898,6 @@ int dsi_panel_pre_disable(struct dsi_panel *panel) mutex_lock(&panel->panel_lock); - /* TODO: hack to disable backlight; */ - led_trigger_event(panel->bl_config.wled, 0x0); rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PRE_OFF); if (rc) { pr_err("[%s] failed to send DSI_CMD_SET_PRE_OFF cmds, rc=%d\n", diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h index 1009d94f13a1..4d21a4cf6428 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h @@ -27,6 +27,8 @@ #include "dsi_ctrl_hw.h" #include "dsi_clk_pwr.h" +#define MAX_BL_LEVEL 4096 + enum dsi_panel_rotation { DSI_PANEL_ROTATE_NONE = 0, DSI_PANEL_ROTATE_HV_FLIP, @@ -101,8 +103,9 @@ struct dsi_panel_cmd_set { struct dsi_backlight_config { enum dsi_backlight_type type; - u32 min_level; - u32 max_level; + u32 bl_min_level; + u32 bl_max_level; + u32 brightness_max_level; int en_gpio; /* PWM params */ @@ -113,6 +116,7 @@ struct dsi_backlight_config { /* WLED params */ struct led_trigger *wled; + struct backlight_device *bd; }; struct dsi_reset_seq { @@ -195,4 +199,5 @@ int dsi_panel_unprepare(struct dsi_panel *panel); int dsi_panel_post_unprepare(struct dsi_panel *panel); +int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl); #endif /* _DSI_PANEL_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_backlight.c b/drivers/gpu/drm/msm/sde/sde_backlight.c new file mode 100644 index 000000000000..9034eeb944fe --- /dev/null +++ b/drivers/gpu/drm/msm/sde/sde_backlight.c @@ -0,0 +1,103 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sde_connector.h" +#include <linux/backlight.h> +#include "dsi_drm.h" + +#define SDE_BRIGHT_TO_BL(out, v, bl_max, max_bright) do {\ + out = (2 * (v) * (bl_max) + max_bright);\ + do_div(out, 2 * max_bright);\ +} while (0) + +static int sde_backlight_device_update_status(struct backlight_device *bd) +{ + int brightness; + struct drm_connector *connector; + struct dsi_display *display; + struct sde_connector *c_conn; + int bl_lvl; + + brightness = bd->props.brightness; + + if ((bd->props.power != FB_BLANK_UNBLANK) || + (bd->props.state & BL_CORE_FBBLANK) || + (bd->props.state & BL_CORE_SUSPENDED)) + brightness = 0; + + connector = bl_get_data(bd); + c_conn = to_sde_connector(connector); + display = (struct dsi_display *) c_conn->display; + if (brightness > display->panel->bl_config.bl_max_level) + brightness = display->panel->bl_config.bl_max_level; + + /* This maps UI brightness into driver backlight level with + * rounding + */ + SDE_BRIGHT_TO_BL(bl_lvl, brightness, + display->panel->bl_config.bl_max_level, + display->panel->bl_config.brightness_max_level); + + if (!bl_lvl && brightness) + bl_lvl = 1; + + if (c_conn->ops.set_backlight) + c_conn->ops.set_backlight(c_conn->display, bl_lvl); + + return 0; +} + +static int sde_backlight_device_get_brightness(struct backlight_device *bd) +{ + return 0; +} + +static const struct backlight_ops sde_backlight_device_ops = { + .update_status = sde_backlight_device_update_status, + .get_brightness = sde_backlight_device_get_brightness, +}; + +int sde_backlight_setup(struct drm_connector *connector) +{ + struct sde_connector *c_conn; + struct backlight_device *bd; + struct backlight_properties props; + struct dsi_display *display; + struct dsi_backlight_config *bl_config; + + if (!connector) + return -EINVAL; + + c_conn = to_sde_connector(connector); + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.power = FB_BLANK_UNBLANK; + + switch (c_conn->connector_type) { + case DRM_MODE_CONNECTOR_DSI: + display = (struct dsi_display *) c_conn->display; + bl_config = &display->panel->bl_config; + props.max_brightness = bl_config->brightness_max_level; + props.brightness = bl_config->brightness_max_level; + bd = backlight_device_register("sde-backlight", + connector->kdev, + connector, + &sde_backlight_device_ops, &props); + if (IS_ERR(bd)) { + pr_err("Failed to register backlight: %ld\n", + PTR_ERR(bd)); + return -ENODEV; + } + } + + return 0; +} diff --git a/drivers/gpu/drm/msm/sde/sde_backlight.h b/drivers/gpu/drm/msm/sde/sde_backlight.h new file mode 100644 index 000000000000..1ea130592302 --- /dev/null +++ b/drivers/gpu/drm/msm/sde/sde_backlight.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SDE_BACKLIGHT_H_ +#define _SDE_BACKLIGHT_H_ + +int sde_backlight_setup(struct drm_connector *connector); + +#endif /* _SDE_BACKLIGHT_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 056cf60004f6..6bc69cb1e578 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -15,6 +15,7 @@ #include "sde_kms.h" #include "sde_connector.h" +#include "sde_backlight.h" static const struct drm_prop_enum_list e_topology_name[] = { {SDE_RM_TOPOLOGY_UNKNOWN, "sde_unknown"}, @@ -536,6 +537,14 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, goto error_unregister_conn; } + if (c_conn->ops.set_backlight) { + rc = sde_backlight_setup(&c_conn->base); + if (rc) { + pr_err("failed to setup backlight, rc=%d\n", rc); + goto error_unregister_conn; + } + } + /* create properties */ msm_property_init(&c_conn->property_info, &c_conn->base.base, dev, priv->conn_property, c_conn->property_data, diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h index cca934d52914..9580282291db 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -111,6 +111,8 @@ struct sde_connector_ops { * Returns: Zero on success */ int (*get_info)(struct msm_display_info *info, void *display); + + int (*set_backlight)(void *display, u32 bl_lvl); }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index a7c33adce36d..40a594df7c5b 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -436,6 +436,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_modes = dsi_connector_get_modes, .mode_valid = dsi_conn_mode_valid, .get_info = dsi_display_get_info, + .set_backlight = dsi_display_set_backlight }; static const struct sde_connector_ops wb_ops = { .post_init = sde_wb_connector_post_init, |
