msm_cooling_device.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/err.h>
  6. #include <linux/slab.h>
  7. #include "msm_cooling_device.h"
  8. #define BRIGHTNESS_CDEV_MAX 255
  9. static int sde_cdev_get_max_brightness(struct thermal_cooling_device *cdev,
  10. unsigned long *state)
  11. {
  12. struct sde_cdev *disp_cdev = (struct sde_cdev *)cdev->devdata;
  13. *state = disp_cdev->bd->props.max_brightness / disp_cdev->cdev_sf;
  14. return 0;
  15. }
  16. static int sde_cdev_get_cur_brightness(struct thermal_cooling_device *cdev,
  17. unsigned long *state)
  18. {
  19. struct sde_cdev *disp_cdev = (struct sde_cdev *)cdev->devdata;
  20. *state = ((disp_cdev->bd->props.max_brightness -
  21. disp_cdev->thermal_state) / disp_cdev->cdev_sf);
  22. return 0;
  23. }
  24. static int sde_cdev_set_cur_brightness(struct thermal_cooling_device *cdev,
  25. unsigned long state)
  26. {
  27. struct sde_cdev *disp_cdev = (struct sde_cdev *)cdev->devdata;
  28. unsigned long brightness_lvl = 0;
  29. if (state > disp_cdev->bd->props.max_brightness / disp_cdev->cdev_sf)
  30. return -EINVAL;
  31. brightness_lvl = disp_cdev->bd->props.max_brightness -
  32. (state * disp_cdev->cdev_sf);
  33. if (brightness_lvl == disp_cdev->thermal_state)
  34. return 0;
  35. disp_cdev->thermal_state = brightness_lvl;
  36. blocking_notifier_call_chain(&disp_cdev->notifier_head,
  37. brightness_lvl, (void *)disp_cdev->bd);
  38. return 0;
  39. }
  40. static struct thermal_cooling_device_ops sde_cdev_ops = {
  41. .get_max_state = sde_cdev_get_max_brightness,
  42. .get_cur_state = sde_cdev_get_cur_brightness,
  43. .set_cur_state = sde_cdev_set_cur_brightness,
  44. };
  45. struct sde_cdev *backlight_cdev_register(struct device *dev,
  46. struct backlight_device *bd,
  47. struct notifier_block *n)
  48. {
  49. struct sde_cdev *disp_cdev = NULL;
  50. if (!dev || !bd || !n)
  51. return ERR_PTR(-EINVAL);
  52. if (!of_find_property(dev->of_node, "#cooling-cells", NULL))
  53. return ERR_PTR(-ENODEV);
  54. disp_cdev = devm_kzalloc(dev, sizeof(*disp_cdev), GFP_KERNEL);
  55. if (!disp_cdev)
  56. return ERR_PTR(-ENOMEM);
  57. disp_cdev->thermal_state = 0;
  58. disp_cdev->bd = bd;
  59. if (bd->props.max_brightness > BRIGHTNESS_CDEV_MAX)
  60. disp_cdev->cdev_sf = (bd->props.max_brightness /
  61. BRIGHTNESS_CDEV_MAX);
  62. else
  63. disp_cdev->cdev_sf = 1;
  64. disp_cdev->cdev = thermal_of_cooling_device_register(dev->of_node,
  65. (char *)dev_name(&bd->dev), disp_cdev,
  66. &sde_cdev_ops);
  67. if (IS_ERR_OR_NULL(disp_cdev->cdev)) {
  68. pr_err("cooling device register failed\n");
  69. return (void *)disp_cdev->cdev;
  70. }
  71. BLOCKING_INIT_NOTIFIER_HEAD(&disp_cdev->notifier_head);
  72. blocking_notifier_chain_register(&disp_cdev->notifier_head, n);
  73. return disp_cdev;
  74. }
  75. void backlight_cdev_unregister(struct sde_cdev *cdev)
  76. {
  77. if (!cdev)
  78. return;
  79. thermal_cooling_device_unregister(cdev->cdev);
  80. }