summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVishnuvardhan Prodduturi <vproddut@codeaurora.org>2016-10-17 18:45:55 +0530
committerVishnuvardhan Prodduturi <vproddut@codeaurora.org>2016-11-14 10:39:22 +0530
commit2d488ea7ed4fc104f9a150de13f143dc1776d100 (patch)
tree555dd56626d1bb18c438cd50e6e136ae7c0e1509
parentbcc085a8facb1e3e32460298668d5d76c503ebd8 (diff)
drm/msm/sde: Add backlight class support for sde drm driver
Add backlight class support for sde drm driver which provides sysfs interface to userspace to control display brightness. Change-Id: I4f777618e8f2ff61e72beddb7a5bd1fa6e9dd5df Signed-off-by: Vishnuvardhan Prodduturi <vproddut@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt1
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_display.c18
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_display.h1
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_panel.c41
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_panel.h9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_backlight.c103
-rw-r--r--drivers/gpu/drm/msm/sde/sde_backlight.h18
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c1
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,