Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ccd2a35f authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: fix backlight node for multi display" into msm-4.9

parents 6f9f8541 7cdd666b
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@ 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 \
	sde_dbg.o \
+0 −103
Original line number Diff line number Diff line
/* 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;
}
+0 −18
Original line number Diff line number Diff line
/* 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_ */
+88 −7
Original line number Diff line number Diff line
@@ -15,7 +15,10 @@

#include "sde_kms.h"
#include "sde_connector.h"
#include "sde_backlight.h"
#include <linux/backlight.h>
#include "dsi_drm.h"

#define BL_NODE_NAME_SIZE 32

static const struct drm_prop_enum_list e_topology_name[] = {
	{SDE_RM_TOPOLOGY_UNKNOWN,	"sde_unknown"},
@@ -32,6 +35,86 @@ static const struct drm_prop_enum_list e_topology_control[] = {
	{SDE_RM_TOPCTL_PPSPLIT,		"ppsplit"}
};

static int sde_backlight_device_update_status(struct backlight_device *bd)
{
	int brightness;
	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;

	c_conn = bl_get_data(bd);
	display = (struct dsi_display *) c_conn->display;
	if (brightness > display->panel->bl_config.bl_max_level)
		brightness = display->panel->bl_config.bl_max_level;

	/* map UI brightness into driver backlight level with rounding */
	bl_lvl = mult_frac(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,
};

static int sde_backlight_setup(struct sde_connector *c_conn)
{
	struct backlight_device *bl_device;
	struct backlight_properties props;
	struct dsi_display *display;
	struct dsi_backlight_config *bl_config;
	static int display_count;
	char bl_node_name[BL_NODE_NAME_SIZE];

	if (!c_conn) {
		SDE_ERROR("invalid param\n");
		return -EINVAL;
	} else if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) {
		return 0;
	}

	memset(&props, 0, sizeof(props));
	props.type = BACKLIGHT_RAW;
	props.power = FB_BLANK_UNBLANK;

	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;
	snprintf(bl_node_name, BL_NODE_NAME_SIZE, "panel%u-backlight",
							display_count);
	bl_device = backlight_device_register(bl_node_name, c_conn->base.kdev,
			c_conn, &sde_backlight_device_ops, &props);
	if (IS_ERR_OR_NULL(bl_device)) {
		SDE_ERROR("Failed to register backlight: %ld\n",
				    PTR_ERR(bl_device));
		return -ENODEV;
	}
	display_count++;

	return 0;
}

int sde_connector_get_info(struct drm_connector *connector,
		struct msm_display_info *info)
{
@@ -532,13 +615,11 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
		goto error_cleanup_fence;
	}

	if (c_conn->ops.set_backlight) {
		rc = sde_backlight_setup(&c_conn->base);
	rc = sde_backlight_setup(c_conn);
	if (rc) {
			pr_err("failed to setup backlight, rc=%d\n", rc);
		SDE_ERROR("failed to setup backlight, rc=%d\n", rc);
		goto error_cleanup_fence;
	}
	}

	/* create properties */
	msm_property_init(&c_conn->property_info, &c_conn->base.base, dev,