
Based on panel hardware support, display brightness levels can be very high value. This high value display brightness cooling device levels can cause exceeding PAGE_SIZE for cooling device stat buffer. It leads to buffer failure for cooling device stat feature. Limit display panel mitigation level max to 255. If hardware supports more than 255, then scale brightness levels fit into above limit. Change-Id: Ieeee4ff2aa5cd884819b30b4fd9839e48ac4d804 Signed-off-by: Manaf Meethalavalappu Pallikunhi <manafm@codeaurora.org>
101 lines
2.7 KiB
C
101 lines
2.7 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
|
|
*/
|
|
#include <linux/err.h>
|
|
#include <linux/slab.h>
|
|
#include "msm_cooling_device.h"
|
|
|
|
#define BRIGHTNESS_CDEV_MAX 255
|
|
|
|
static int sde_cdev_get_max_brightness(struct thermal_cooling_device *cdev,
|
|
unsigned long *state)
|
|
{
|
|
struct sde_cdev *disp_cdev = (struct sde_cdev *)cdev->devdata;
|
|
|
|
*state = disp_cdev->bd->props.max_brightness / disp_cdev->cdev_sf;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sde_cdev_get_cur_brightness(struct thermal_cooling_device *cdev,
|
|
unsigned long *state)
|
|
{
|
|
struct sde_cdev *disp_cdev = (struct sde_cdev *)cdev->devdata;
|
|
|
|
*state = ((disp_cdev->bd->props.max_brightness -
|
|
disp_cdev->thermal_state) / disp_cdev->cdev_sf);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sde_cdev_set_cur_brightness(struct thermal_cooling_device *cdev,
|
|
unsigned long state)
|
|
{
|
|
struct sde_cdev *disp_cdev = (struct sde_cdev *)cdev->devdata;
|
|
unsigned long brightness_lvl = 0;
|
|
|
|
if (state > disp_cdev->bd->props.max_brightness / disp_cdev->cdev_sf)
|
|
return -EINVAL;
|
|
|
|
brightness_lvl = disp_cdev->bd->props.max_brightness -
|
|
(state * disp_cdev->cdev_sf);
|
|
if (brightness_lvl == disp_cdev->thermal_state)
|
|
return 0;
|
|
disp_cdev->thermal_state = brightness_lvl;
|
|
blocking_notifier_call_chain(&disp_cdev->notifier_head,
|
|
brightness_lvl, (void *)disp_cdev->bd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct thermal_cooling_device_ops sde_cdev_ops = {
|
|
.get_max_state = sde_cdev_get_max_brightness,
|
|
.get_cur_state = sde_cdev_get_cur_brightness,
|
|
.set_cur_state = sde_cdev_set_cur_brightness,
|
|
};
|
|
|
|
struct sde_cdev *backlight_cdev_register(struct device *dev,
|
|
struct backlight_device *bd,
|
|
struct notifier_block *n)
|
|
{
|
|
struct sde_cdev *disp_cdev = NULL;
|
|
|
|
if (!dev || !bd || !n)
|
|
return ERR_PTR(-EINVAL);
|
|
if (!of_find_property(dev->of_node, "#cooling-cells", NULL))
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
disp_cdev = devm_kzalloc(dev, sizeof(*disp_cdev), GFP_KERNEL);
|
|
if (!disp_cdev)
|
|
return ERR_PTR(-ENOMEM);
|
|
disp_cdev->thermal_state = 0;
|
|
disp_cdev->bd = bd;
|
|
|
|
if (bd->props.max_brightness > BRIGHTNESS_CDEV_MAX)
|
|
disp_cdev->cdev_sf = (bd->props.max_brightness /
|
|
BRIGHTNESS_CDEV_MAX);
|
|
else
|
|
disp_cdev->cdev_sf = 1;
|
|
|
|
disp_cdev->cdev = thermal_of_cooling_device_register(dev->of_node,
|
|
(char *)dev_name(&bd->dev), disp_cdev,
|
|
&sde_cdev_ops);
|
|
if (IS_ERR_OR_NULL(disp_cdev->cdev)) {
|
|
pr_err("cooling device register failed\n");
|
|
return (void *)disp_cdev->cdev;
|
|
}
|
|
BLOCKING_INIT_NOTIFIER_HEAD(&disp_cdev->notifier_head);
|
|
blocking_notifier_chain_register(&disp_cdev->notifier_head, n);
|
|
|
|
return disp_cdev;
|
|
}
|
|
|
|
void backlight_cdev_unregister(struct sde_cdev *cdev)
|
|
{
|
|
if (!cdev)
|
|
return;
|
|
|
|
thermal_cooling_device_unregister(cdev->cdev);
|
|
}
|