diff --git a/msm/Makefile b/msm/Makefile index 952746f5f5da..959fe7c5d9e5 100644 --- a/msm/Makefile +++ b/msm/Makefile @@ -127,6 +127,7 @@ msm_drm-$(CONFIG_DRM_MSM) += \ msm_gem_prime.o \ msm_gem_vma.o \ msm_smmu.o \ + msm_cooling_device.o \ msm_prop.o msm_drm-$(CONFIG_HDCP_QSEECOM) += ../hdcp/msm_hdcp.o \ diff --git a/msm/msm_cooling_device.c b/msm/msm_cooling_device.c new file mode 100644 index 000000000000..73ce8f200737 --- /dev/null +++ b/msm/msm_cooling_device.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ +#include +#include +#include "msm_cooling_device.h" + +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; + + 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; + + 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) + return -EINVAL; + + brightness_lvl = disp_cdev->bd->props.max_brightness - state; + 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; + 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); +} diff --git a/msm/msm_cooling_device.h b/msm/msm_cooling_device.h new file mode 100644 index 000000000000..b95bf45c3449 --- /dev/null +++ b/msm/msm_cooling_device.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __SDE_THERMAL_CORE_H__ +#define __SDE_THERMAL_CORE_H__ + +#include +#include +#include +#include + +struct sde_cdev { + struct blocking_notifier_head notifier_head; + struct thermal_cooling_device *cdev; + struct backlight_device *bd; + unsigned long thermal_state; +}; + +#ifdef CONFIG_THERMAL_OF +struct sde_cdev *backlight_cdev_register(struct device *dev, + struct backlight_device *bd, + struct notifier_block *n); +void backlight_cdev_unregister(struct sde_cdev *cdev); +#else +static inline struct sde_cdev * +backlight_cdev_register(struct device *dev, + struct backlight_device *bd, struct notifier_block *n) +{ + return NULL; +} +static inline void backlight_cdev_unregister(struct sde_cdev *cdev) +{ } +#endif + +#endif