006-Add-ili8960-lcd-driver.patch 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. From 8741ead92bc93e66740237e51b88b8690ebcbba3 Mon Sep 17 00:00:00 2001
  2. From: Lars-Peter Clausen <lars@metafoo.de>
  3. Date: Sun, 1 Aug 2010 21:19:40 +0200
  4. Subject: [PATCH 6/7] Add ili8960 lcd driver
  5. Includes the following changes from the jz-3.5 branch:
  6. - Use module_spi_driver
  7. - Use devm_kzalloc
  8. - Use kstrtoul
  9. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
  10. ---
  11. drivers/video/backlight/Kconfig | 7 +
  12. drivers/video/backlight/Makefile | 1 +
  13. drivers/video/backlight/ili8960.c | 262 +++++++++++++++++++++++++++++++++++++
  14. 3 files changed, 270 insertions(+)
  15. create mode 100644 drivers/video/backlight/ili8960.c
  16. --- a/drivers/video/backlight/Kconfig
  17. +++ b/drivers/video/backlight/Kconfig
  18. @@ -59,6 +59,13 @@ config LCD_LTV350QV
  19. The LTV350QV panel is present on all ATSTK1000 boards.
  20. +config LCD_ILI8960
  21. + tristate "Ilitek ili8960 LCD driver"
  22. + depends on LCD_CLASS_DEVICE && SPI
  23. + default n
  24. + help
  25. + Driver for the Ilitek ili8960 LCD controller chip.
  26. +
  27. config LCD_ILI922X
  28. tristate "ILI Technology ILI9221/ILI9222 support"
  29. depends on SPI
  30. --- a/drivers/video/backlight/Makefile
  31. +++ b/drivers/video/backlight/Makefile
  32. @@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
  33. obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
  34. obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
  35. obj-$(CONFIG_LCD_HX8357) += hx8357.o
  36. +obj-$(CONFIG_LCD_ILI8960) += ili8960.o
  37. obj-$(CONFIG_LCD_ILI922X) += ili922x.o
  38. obj-$(CONFIG_LCD_ILI9320) += ili9320.o
  39. obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o
  40. --- /dev/null
  41. +++ b/drivers/video/backlight/ili8960.c
  42. @@ -0,0 +1,262 @@
  43. +/*
  44. + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
  45. + * Driver for Ilitek ili8960 LCD
  46. + *
  47. + * This program is free software; you can redistribute it and/or modify it
  48. + * under the terms of the GNU General Public License as published by the
  49. + * Free Software Foundation; either version 2 of the License, or (at your
  50. + * option) any later version.
  51. + *
  52. + * You should have received a copy of the GNU General Public License along
  53. + * with this program; if not, write to the Free Software Foundation, Inc.,
  54. + * 675 Mass Ave, Cambridge, MA 02139, USA.
  55. + *
  56. + */
  57. +
  58. +#include <linux/module.h>
  59. +#include <linux/spi/spi.h>
  60. +#include <linux/lcd.h>
  61. +#include <linux/delay.h>
  62. +
  63. +struct ili8960 {
  64. + struct spi_device *spi;
  65. + struct lcd_device *lcd;
  66. + bool enabled;
  67. + unsigned int brightness;
  68. +};
  69. +
  70. +#define ILI8960_REG_BRIGHTNESS 0x03
  71. +#define ILI8960_REG_POWER 0x05
  72. +#define ILI8960_REG_CONTRAST 0x0d
  73. +
  74. +static int ili8960_write_reg(struct spi_device *spi, uint8_t reg,
  75. + uint8_t data)
  76. +{
  77. + uint8_t buf[2];
  78. + buf[0] = ((reg & 0x40) << 1) | (reg & 0x3f);
  79. + buf[1] = data;
  80. +
  81. + return spi_write(spi, buf, sizeof(buf));
  82. +}
  83. +
  84. +static int ili8960_programm_power(struct spi_device *spi, bool enabled)
  85. +{
  86. + int ret;
  87. +
  88. + if (enabled)
  89. + mdelay(20);
  90. +
  91. + ret = ili8960_write_reg(spi, ILI8960_REG_POWER, enabled ? 0xc7 : 0xc6);
  92. +
  93. + if (!enabled)
  94. + mdelay(20);
  95. +
  96. + return ret;
  97. +}
  98. +
  99. +static int ili8960_set_power(struct lcd_device *lcd, int power)
  100. +{
  101. + struct ili8960 *ili8960 = lcd_get_data(lcd);
  102. +
  103. + switch (power) {
  104. + case FB_BLANK_UNBLANK:
  105. + ili8960->enabled = true;
  106. + break;
  107. + default:
  108. + return 0;
  109. + }
  110. +
  111. + return ili8960_programm_power(ili8960->spi, ili8960->enabled);
  112. +}
  113. +
  114. +static int ili8960_early_set_power(struct lcd_device *lcd, int power)
  115. +{
  116. + struct ili8960 *ili8960 = lcd_get_data(lcd);
  117. +
  118. + switch (power) {
  119. + case FB_BLANK_UNBLANK:
  120. + return 0;
  121. + default:
  122. + ili8960->enabled = false;
  123. + break;
  124. + }
  125. +
  126. + return ili8960_programm_power(ili8960->spi, ili8960->enabled);
  127. +}
  128. +
  129. +static int ili8960_get_power(struct lcd_device *lcd)
  130. +{
  131. + struct ili8960 *ili8960 = lcd_get_data(lcd);
  132. + return ili8960->enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
  133. +}
  134. +
  135. +static int ili8960_set_contrast(struct lcd_device *lcd, int contrast)
  136. +{
  137. + struct ili8960 *ili8960 = lcd_get_data(lcd);
  138. +
  139. + return ili8960_write_reg(ili8960->spi, ILI8960_REG_CONTRAST, contrast);
  140. +}
  141. +
  142. +static int ili8960_set_mode(struct lcd_device *lcd, struct fb_videomode *mode)
  143. +{
  144. + if (mode->xres != 320 && mode->yres != 240)
  145. + return -EINVAL;
  146. +
  147. + return 0;
  148. +}
  149. +
  150. +static int ili8960_set_brightness(struct ili8960 *ili8960, int brightness)
  151. +{
  152. + int ret;
  153. +
  154. + ret = ili8960_write_reg(ili8960->spi, ILI8960_REG_BRIGHTNESS, brightness);
  155. +
  156. + if (ret == 0)
  157. + ili8960->brightness = brightness;
  158. +
  159. + return ret;
  160. +}
  161. +
  162. +static ssize_t ili8960_show_brightness(struct device *dev,
  163. + struct device_attribute *attr, char *buf)
  164. +{
  165. + struct lcd_device *ld = to_lcd_device(dev);
  166. + struct ili8960 *ili8960 = lcd_get_data(ld);
  167. +
  168. + return sprintf(buf, "%u\n", ili8960->brightness);
  169. +}
  170. +
  171. +static ssize_t ili8960_store_brightness(struct device *dev,
  172. + struct device_attribute *attr, const char *buf, size_t count)
  173. +{
  174. + struct lcd_device *ld = to_lcd_device(dev);
  175. + struct ili8960 *ili8960 = lcd_get_data(ld);
  176. + unsigned long brightness;
  177. + int ret;
  178. +
  179. + ret = kstrtoul(buf, 0, &brightness);
  180. + if (ret)
  181. + return ret;
  182. +
  183. + if (brightness > 255)
  184. + return -EINVAL;
  185. +
  186. + ili8960_set_brightness(ili8960, brightness);
  187. +
  188. + return count;
  189. +}
  190. +
  191. +
  192. +static DEVICE_ATTR(brightness, 0644, ili8960_show_brightness,
  193. + ili8960_store_brightness);
  194. +
  195. +static struct lcd_ops ili8960_lcd_ops = {
  196. + .set_power = ili8960_set_power,
  197. + .early_set_power = ili8960_early_set_power,
  198. + .get_power = ili8960_get_power,
  199. + .set_contrast = ili8960_set_contrast,
  200. + .set_mode = ili8960_set_mode,
  201. +};
  202. +
  203. +static int ili8960_probe(struct spi_device *spi)
  204. +{
  205. + int ret;
  206. + struct ili8960 *ili8960;
  207. +
  208. + ili8960 = devm_kzalloc(&spi->dev, sizeof(*ili8960), GFP_KERNEL);
  209. + if (!ili8960)
  210. + return -ENOMEM;
  211. +
  212. + spi->bits_per_word = 8;
  213. + spi->mode = SPI_MODE_3;
  214. +
  215. + ret = spi_setup(spi);
  216. + if (ret) {
  217. + dev_err(&spi->dev, "Failed to setup spi\n");
  218. + return ret;
  219. + }
  220. +
  221. + ili8960->spi = spi;
  222. +
  223. + ili8960->lcd = lcd_device_register("ili8960-lcd", &spi->dev, ili8960,
  224. + &ili8960_lcd_ops);
  225. +
  226. + if (IS_ERR(ili8960->lcd)) {
  227. + ret = PTR_ERR(ili8960->lcd);
  228. + dev_err(&spi->dev, "Failed to register lcd device: %d\n", ret);
  229. + return ret;
  230. + }
  231. +
  232. + ili8960->lcd->props.max_contrast = 255;
  233. +
  234. + ret = device_create_file(&ili8960->lcd->dev, &dev_attr_brightness);
  235. + if (ret)
  236. + goto err_unregister_lcd;
  237. +
  238. + ili8960_programm_power(ili8960->spi, true);
  239. + ili8960->enabled = true;
  240. +
  241. + spi_set_drvdata(spi, ili8960);
  242. +
  243. + ili8960_write_reg(spi, 0x13, 0x01);
  244. +
  245. + return 0;
  246. +err_unregister_lcd:
  247. + lcd_device_unregister(ili8960->lcd);
  248. + return ret;
  249. +}
  250. +
  251. +static int ili8960_remove(struct spi_device *spi)
  252. +{
  253. + struct ili8960 *ili8960 = spi_get_drvdata(spi);
  254. +
  255. + device_remove_file(&ili8960->lcd->dev, &dev_attr_brightness);
  256. + lcd_device_unregister(ili8960->lcd);
  257. +
  258. + spi_set_drvdata(spi, NULL);
  259. + return 0;
  260. +}
  261. +
  262. +#ifdef CONFIG_PM
  263. +
  264. +static int ili8960_suspend(struct spi_device *spi, pm_message_t state)
  265. +{
  266. + struct ili8960 *ili8960 = spi_get_drvdata(spi);
  267. +
  268. + if (ili8960->enabled)
  269. + ili8960_programm_power(ili8960->spi, false);
  270. +
  271. + return 0;
  272. +}
  273. +
  274. +static int ili8960_resume(struct spi_device *spi)
  275. +{
  276. + struct ili8960 *ili8960 = spi_get_drvdata(spi);
  277. +
  278. + if (ili8960->enabled)
  279. + ili8960_programm_power(ili8960->spi, true);
  280. +
  281. + return 0;
  282. +}
  283. +
  284. +#else
  285. +#define ili8960_suspend NULL
  286. +#define ili8960_resume NULL
  287. +#endif
  288. +
  289. +static struct spi_driver ili8960_driver = {
  290. + .driver = {
  291. + .name = "ili8960",
  292. + .owner = THIS_MODULE,
  293. + },
  294. + .probe = ili8960_probe,
  295. + .remove = ili8960_remove,
  296. + .suspend = ili8960_suspend,
  297. + .resume = ili8960_resume,
  298. +};
  299. +module_spi_driver(ili8960_driver);
  300. +
  301. +MODULE_AUTHOR("Lars-Peter Clausen");
  302. +MODULE_LICENSE("GPL");
  303. +MODULE_DESCRIPTION("LCD driver for Ilitek ili8960");
  304. +MODULE_ALIAS("spi:ili8960");