tosa_bl.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * LCD / Backlight control code for Sharp SL-6000x (tosa)
  4. *
  5. * Copyright (c) 2005 Dirk Opfer
  6. * Copyright (c) 2007,2008 Dmitry Baryshkov
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/device.h>
  11. #include <linux/spi/spi.h>
  12. #include <linux/i2c.h>
  13. #include <linux/gpio/consumer.h>
  14. #include <linux/fb.h>
  15. #include <linux/backlight.h>
  16. #include <linux/slab.h>
  17. #include <asm/mach/sharpsl_param.h>
  18. #include "tosa_bl.h"
  19. #define COMADJ_DEFAULT 97
  20. #define DAC_CH1 0
  21. #define DAC_CH2 1
  22. struct tosa_bl_data {
  23. struct i2c_client *i2c;
  24. struct backlight_device *bl;
  25. struct gpio_desc *gpio;
  26. int comadj;
  27. };
  28. static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness)
  29. {
  30. struct spi_device *spi = dev_get_platdata(&data->i2c->dev);
  31. i2c_smbus_write_byte_data(data->i2c, DAC_CH1, data->comadj);
  32. /* SetBacklightDuty */
  33. i2c_smbus_write_byte_data(data->i2c, DAC_CH2, (u8)(brightness & 0xff));
  34. /* SetBacklightVR */
  35. gpiod_set_value(data->gpio, brightness & 0x100);
  36. tosa_bl_enable(spi, brightness);
  37. }
  38. static int tosa_bl_update_status(struct backlight_device *dev)
  39. {
  40. struct backlight_properties *props = &dev->props;
  41. struct tosa_bl_data *data = bl_get_data(dev);
  42. int power = max(props->power, props->fb_blank);
  43. int brightness = props->brightness;
  44. if (power)
  45. brightness = 0;
  46. tosa_bl_set_backlight(data, brightness);
  47. return 0;
  48. }
  49. static int tosa_bl_get_brightness(struct backlight_device *dev)
  50. {
  51. struct backlight_properties *props = &dev->props;
  52. return props->brightness;
  53. }
  54. static const struct backlight_ops bl_ops = {
  55. .get_brightness = tosa_bl_get_brightness,
  56. .update_status = tosa_bl_update_status,
  57. };
  58. static int tosa_bl_probe(struct i2c_client *client,
  59. const struct i2c_device_id *id)
  60. {
  61. struct backlight_properties props;
  62. struct tosa_bl_data *data;
  63. int ret = 0;
  64. data = devm_kzalloc(&client->dev, sizeof(struct tosa_bl_data),
  65. GFP_KERNEL);
  66. if (!data)
  67. return -ENOMEM;
  68. data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
  69. data->gpio = devm_gpiod_get(&client->dev, "backlight", GPIOD_OUT_LOW);
  70. ret = PTR_ERR_OR_ZERO(data->gpio);
  71. if (ret) {
  72. dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
  73. return ret;
  74. }
  75. i2c_set_clientdata(client, data);
  76. data->i2c = client;
  77. memset(&props, 0, sizeof(struct backlight_properties));
  78. props.type = BACKLIGHT_RAW;
  79. props.max_brightness = 512 - 1;
  80. data->bl = devm_backlight_device_register(&client->dev, "tosa-bl",
  81. &client->dev, data, &bl_ops,
  82. &props);
  83. if (IS_ERR(data->bl)) {
  84. ret = PTR_ERR(data->bl);
  85. goto err_reg;
  86. }
  87. data->bl->props.brightness = 69;
  88. data->bl->props.power = FB_BLANK_UNBLANK;
  89. backlight_update_status(data->bl);
  90. return 0;
  91. err_reg:
  92. data->bl = NULL;
  93. return ret;
  94. }
  95. static int tosa_bl_remove(struct i2c_client *client)
  96. {
  97. struct tosa_bl_data *data = i2c_get_clientdata(client);
  98. data->bl = NULL;
  99. return 0;
  100. }
  101. #ifdef CONFIG_PM_SLEEP
  102. static int tosa_bl_suspend(struct device *dev)
  103. {
  104. struct tosa_bl_data *data = dev_get_drvdata(dev);
  105. tosa_bl_set_backlight(data, 0);
  106. return 0;
  107. }
  108. static int tosa_bl_resume(struct device *dev)
  109. {
  110. struct tosa_bl_data *data = dev_get_drvdata(dev);
  111. backlight_update_status(data->bl);
  112. return 0;
  113. }
  114. #endif
  115. static SIMPLE_DEV_PM_OPS(tosa_bl_pm_ops, tosa_bl_suspend, tosa_bl_resume);
  116. static const struct i2c_device_id tosa_bl_id[] = {
  117. { "tosa-bl", 0 },
  118. { },
  119. };
  120. MODULE_DEVICE_TABLE(i2c, tosa_bl_id);
  121. static struct i2c_driver tosa_bl_driver = {
  122. .driver = {
  123. .name = "tosa-bl",
  124. .pm = &tosa_bl_pm_ops,
  125. },
  126. .probe = tosa_bl_probe,
  127. .remove = tosa_bl_remove,
  128. .id_table = tosa_bl_id,
  129. };
  130. module_i2c_driver(tosa_bl_driver);
  131. MODULE_AUTHOR("Dmitry Baryshkov");
  132. MODULE_LICENSE("GPL v2");
  133. MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA");