ili9341.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. /****************************************************************************
  2. * drivers/lcd/ili9341.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /* References: ILI9341_DS_V1.10.pdf (Rev: 1.10), "a-Si TFT LCD Single Chip
  21. * Driver 240RGBx320 Resolution and 262K color",
  22. * ILI TECHNOLOGY CORP., http://www.ilitek.com.
  23. */
  24. /****************************************************************************
  25. * Included Files
  26. ****************************************************************************/
  27. #include <nuttx/config.h>
  28. #include <sys/types.h>
  29. #include <stdint.h>
  30. #include <stdbool.h>
  31. #include <string.h>
  32. #include <assert.h>
  33. #include <errno.h>
  34. #include <debug.h>
  35. #include <nuttx/arch.h>
  36. #include <nuttx/lcd/lcd.h>
  37. #include <nuttx/lcd/ili9341.h>
  38. #include <arch/irq.h>
  39. /****************************************************************************
  40. * Pre-processor Definitions
  41. ****************************************************************************/
  42. /* This is the generic lcd driver interface for the ili9341 Single Chip LCD
  43. * driver. The driver supports multiple displays, each connected with an own
  44. * ili9341 Single Chip LCD driver. The communication with the LCD single chip
  45. * driver must be provide by a subdriver accessible through the ili9341_dev_s
  46. * structure which is platform and MCU interface specific.
  47. *
  48. * Supported MCU interfaces (planned to support)
  49. *
  50. * Interface I
  51. *
  52. * 8080 MCU 8-bit bus interface
  53. * 8080 MCU 16-bit bus interface
  54. * 8080 MCU 9-bit bus interface
  55. * 8080 MCU 18-bit bus interface
  56. * 3-wire 9-bit data serial interface
  57. * 4-wire 8-bit data serial interface
  58. *
  59. * Interface II
  60. *
  61. * 8080 MCU 8-bit bus interface
  62. * 8080 MCU 16-bit bus interface
  63. * 8080 MCU 9-bit bus interface
  64. * 8080 MCU 18-bit bus interface
  65. * 3-wire 9-bit data serial Interface
  66. * 4-wire 8-bit data serial Interface
  67. *
  68. * Note! RGB interface will not supported by the lcd driver.
  69. * It should be use with the platform specific RGB graphic controller and the
  70. * nuttx framebuffer interface.
  71. *
  72. */
  73. /* Fundamental command and parameter definition */
  74. /* Interface control (IFCTL)
  75. *
  76. *
  77. * Parameter 1: 0x0001
  78. *
  79. * MY_EOR: 0
  80. * MX_EOR: 0
  81. * MV_EOR: 0
  82. * BGR_EOR: 0
  83. * WEMODE: 1 Reset column and page if data transfer exceeds
  84. */
  85. #define ILI9341_IFCTL_MYEOR 0
  86. #define ILI9341_IFCTL_MXEOR 0
  87. #define ILI9341_IFCTL_MVEOR 0
  88. #define ILI9341_IFCTL_BGREOR 0
  89. #define ILI9341_IFCTL_WEMODE ILI9341_INTERFACE_CONTROL_WEMODE
  90. #define ILI9341_IFCTL_PARAM1 ILI9341_IFCTL_MYEOR | ILI9341_IFCTL_MXEOR | \
  91. ILI9341_IFCTL_MVEOR | ILI9341_IFCTL_BGREOR | \
  92. ILI9341_IFCTL_WEMODE
  93. /* Parameter 2: 0x0000
  94. *
  95. * EPF: 0 65k color format for RGB interface, not used set to default
  96. * MDT: 0 Display data transfer mode, not used
  97. *
  98. * Note!
  99. * If RGB666 and 16-bit 8080-I interface supported by the driver, MDT must
  100. * be defined for each selected driver instance. Leave it empty for now.
  101. */
  102. #define ILI9341_IFCTL_EPF ILI9341_INTERFACE_CONTROL_EPF(0)
  103. #define ILI9341_IFCTL_MDT ILI9341_INTERFACE_CONTROL_MDT(0)
  104. #define ILI9341_IFCTL_PARAM2 ILI9341_IFCTL_EPF | ILI9341_IFCTL_MDT
  105. /* Parameter 3: 0x0000/0x0020
  106. *
  107. * ENDIAN: 0/1 Depending on endian mode of the mcu?
  108. * DM: 0 Internal clock operation
  109. * RM: 0 System interface/VSYNC interface
  110. * RIM: 0 RGB interface mode, unimportant set to default
  111. *
  112. */
  113. #ifdef CONFIG_ENDIAN_BIG
  114. # define ILI9341_IFCTL_ENDIAN 0
  115. #else
  116. # define ILI9341_IFCTL_ENDIAN ILI9341_INTERFACE_CONTROL_ENDIAN
  117. #endif
  118. #define ILI9341_IFCTL_DM ILI9341_INTERFACE_CONTROL_DM(0)
  119. #define ILI9341_IFCTL_RM 0
  120. #define ILI9341_IFCTL_RIM 0
  121. #define ILI9341_IFCTL_PARAM3 ILI9341_IFCTL_RIM | ILI9341_IFCTL_RM | \
  122. ILI9341_IFCTL_DM | ILI9341_IFCTL_ENDIAN
  123. /* Memory access control (MADCTL) */
  124. /* Landscape: 00100000 / 00101000 / h28
  125. *
  126. * MY: 0
  127. * MX: 0
  128. * MV: 1
  129. * ML: 0
  130. * BGR: 0/1 Depending on endian mode of the mcu?
  131. * MH: 0
  132. */
  133. #define ILI9341_MADCTL_LANDSCAPE_MY 0
  134. #define ILI9341_MADCTL_LANDSCAPE_MX 0
  135. #define ILI9341_MADCTL_LANDSCAPE_MV ILI9341_MEMORY_ACCESS_CONTROL_MV
  136. #define ILI9341_MADCTL_LANDSCAPE_ML 0
  137. #ifdef CONFIG_ENDIAN_BIG
  138. # define ILI9341_MADCTL_LANDSCAPE_BGR 0
  139. #else
  140. # define ILI9341_MADCTL_LANDSCAPE_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR
  141. #endif
  142. #define ILI9341_MADCTL_LANDSCAPE_MH 0
  143. #define ILI9341_MADCTL_LANDSCAPE_PARAM1 (ILI9341_MADCTL_LANDSCAPE_MY | \
  144. ILI9341_MADCTL_LANDSCAPE_MX | \
  145. ILI9341_MADCTL_LANDSCAPE_MV | \
  146. ILI9341_MADCTL_LANDSCAPE_ML | \
  147. ILI9341_MADCTL_LANDSCAPE_BGR | \
  148. ILI9341_MADCTL_LANDSCAPE_MH)
  149. /* Portrait: 00000000 / 00001000 / h08
  150. *
  151. * MY: 0
  152. * MX: 0
  153. * MV: 0
  154. * ML: 0
  155. * BGR: 0/1 Depending on endian mode of the mcu?
  156. * MH: 0
  157. */
  158. #define ILI9341_MADCTL_PORTRAIT_MY 0
  159. #define ILI9341_MADCTL_PORTRAIT_MX ILI9341_MEMORY_ACCESS_CONTROL_MX
  160. #define ILI9341_MADCTL_PORTRAIT_MV 0
  161. #define ILI9341_MADCTL_PORTRAIT_ML ILI9341_MEMORY_ACCESS_CONTROL_ML
  162. #ifdef CONFIG_ENDIAN_BIG
  163. # define ILI9341_MADCTL_PORTRAIT_BGR 0
  164. #else
  165. # define ILI9341_MADCTL_PORTRAIT_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR
  166. #endif
  167. #define ILI9341_MADCTL_PORTRAIT_MH 0
  168. #define ILI9341_MADCTL_PORTRAIT_PARAM1 (ILI9341_MADCTL_PORTRAIT_MY | \
  169. ILI9341_MADCTL_PORTRAIT_MX | \
  170. ILI9341_MADCTL_PORTRAIT_MV | \
  171. ILI9341_MADCTL_PORTRAIT_ML | \
  172. ILI9341_MADCTL_PORTRAIT_BGR | \
  173. ILI9341_MADCTL_PORTRAIT_MH)
  174. /* RLandscape: 01100000 / 01101000 / h68
  175. *
  176. * MY: 0
  177. * MX: 1
  178. * MV: 1
  179. * ML: 0
  180. * BGR: 0/1 Depending on endian mode of the mcu?
  181. * MH: 0
  182. */
  183. #define ILI9341_MADCTL_RLANDSCAPE_MY ILI9341_MEMORY_ACCESS_CONTROL_MY
  184. #define ILI9341_MADCTL_RLANDSCAPE_MX ILI9341_MEMORY_ACCESS_CONTROL_MX
  185. #define ILI9341_MADCTL_RLANDSCAPE_MV ILI9341_MEMORY_ACCESS_CONTROL_MV
  186. #define ILI9341_MADCTL_RLANDSCAPE_ML 0
  187. #ifdef CONFIG_ENDIAN_BIG
  188. # define ILI9341_MADCTL_RLANDSCAPE_BGR 0
  189. #else
  190. # define ILI9341_MADCTL_RLANDSCAPE_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR
  191. #endif
  192. #define ILI9341_MADCTL_RLANDSCAPE_MH 0
  193. #define ILI9341_MADCTL_RLANDSCAPE_PARAM1 \
  194. (ILI9341_MADCTL_RLANDSCAPE_MY | \
  195. ILI9341_MADCTL_RLANDSCAPE_MX | \
  196. ILI9341_MADCTL_RLANDSCAPE_MV | \
  197. ILI9341_MADCTL_RLANDSCAPE_ML | \
  198. ILI9341_MADCTL_RLANDSCAPE_BGR | \
  199. ILI9341_MADCTL_RLANDSCAPE_MH)
  200. /* RPortrait: 11000000 / 11001000 / hc8
  201. *
  202. * MY: 1
  203. * MX: 1
  204. * MV: 0
  205. * ML: 0
  206. * BGR: 0/1 Depending on endian mode of the mcu?
  207. * MH: 0
  208. *
  209. */
  210. #define ILI9341_MADCTL_RPORTRAIT_MY ILI9341_MEMORY_ACCESS_CONTROL_MY
  211. #define ILI9341_MADCTL_RPORTRAIT_MX 0
  212. #define ILI9341_MADCTL_RPORTRAIT_MV 0
  213. #define ILI9341_MADCTL_RPORTRAIT_ML ILI9341_MEMORY_ACCESS_CONTROL_ML
  214. #ifdef CONFIG_ENDIAN_BIG
  215. # define ILI9341_MADCTL_RPORTRAIT_BGR 0
  216. #else
  217. # define ILI9341_MADCTL_RPORTRAIT_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR
  218. #endif
  219. #define ILI9341_MADCTL_RPORTRAIT_MH 0
  220. #define ILI9341_MADCTL_RPORTRAIT_PARAM1 (ILI9341_MADCTL_RPORTRAIT_MY | \
  221. ILI9341_MADCTL_RPORTRAIT_MX | \
  222. ILI9341_MADCTL_RPORTRAIT_MV | \
  223. ILI9341_MADCTL_RPORTRAIT_ML | \
  224. ILI9341_MADCTL_RPORTRAIT_BGR | \
  225. ILI9341_MADCTL_RPORTRAIT_MH)
  226. /* Pixel Format Set (COLMOD)
  227. *
  228. * Note! RGB interface settings (DPI) is unimportant for the MCU interface
  229. * mode but set the register to the defined state equal to the MCU interface
  230. * pixel format.
  231. *
  232. * 16 Bit MCU: 01010101 / h55
  233. *
  234. * DPI: 5 (RGB16-565 RGB interface, not used)
  235. * DBI: 5 (RGB16-565 MCU interface
  236. */
  237. #define ILI9341_PIXSET_16BITDPI ILI9341_PIXEL_FORMAT_SET_DPI(5)
  238. #define ILI9341_PIXSET_16BITDBI ILI9341_PIXEL_FORMAT_SET_DBI(5)
  239. #define ILI9341_PIXSET_16BITMCU_PARAM1 (ILI9341_PIXSET_16BITDPI | \
  240. ILI9341_PIXSET_16BITDBI)
  241. /* 18-bit MCU: 01100110 / h66 (not supported by nuttx until now)
  242. *
  243. * DPI: 6 (RGB18-666 RGB interface)
  244. * DBI: 6 (RGB18-666 MCU interface)
  245. */
  246. #define ILI9341_PIXSET_18BITDPI ILI9341_PIXEL_FORMAT_SET_DPI(6)
  247. #define ILI9341_PIXSET_18BITDBI ILI9341_PIXEL_FORMAT_SET_DBI(6)
  248. #define ILI9341_PIXSET_18BITMCU_PARAM1 (ILI9341_PIXSET_18BITDPI | \
  249. ILI9341_PIXSET_18BITDBI)
  250. /* General fix display resolution */
  251. #define ILI9341_XRES 240
  252. #define ILI9341_YRES 320
  253. /* Validate configuration */
  254. #if CONFIG_LCD_ILI9341_NINTERFACES < 1
  255. # undef CONFIG_LCD_ILI9341_IFACE0
  256. #elif CONFIG_LCD_ILI9341_NINTERFACES < 2
  257. # undef CONFIG_LCD_ILI9341_IFACE1
  258. #endif
  259. /* First LCD display */
  260. #ifdef CONFIG_LCD_ILI9341_IFACE0
  261. # if defined(CONFIG_LCD_ILI9341_IFACE0_LANDSCAPE)
  262. # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_LANDSCAPE_PARAM1
  263. # define ILI9341_IFACE0_STRIDE ILI9341_YRES
  264. # elif defined(CONFIG_LCD_ILI9341_IFACE0_PORTRAIT)
  265. # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_PORTRAIT_PARAM1
  266. # define ILI9341_IFACE0_STRIDE ILI9341_XRES
  267. # elif defined(CONFIG_LCD_ILI9341_IFACE0_RLANDSCAPE)
  268. # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_RLANDSCAPE_PARAM1
  269. # define ILI9341_IFACE0_STRIDE ILI9341_YRES
  270. # elif defined(CONFIG_LCD_ILI9341_IFACE0_RPORTRAIT)
  271. # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_RPORTRAIT_PARAM1
  272. # define ILI9341_IFACE0_STRIDE ILI9341_XRES
  273. # endif
  274. # ifdef CONFIG_LCD_ILI9341_IFACE0_RGB565
  275. # define ILI9341_IFACE0_PXFMT FB_FMT_RGB16_565
  276. # define ILI9341_IFACE0_BPP 16
  277. # define ILI9341_IFACE0_BUFFER ILI9341_IFACE0_STRIDE
  278. # else
  279. # error "undefined pixel format for lcd interface 0"
  280. # endif
  281. #endif
  282. /* Second LCD display */
  283. #ifdef CONFIG_LCD_ILI9341_IFACE1
  284. # ifdef CONFIG_LCD_ILI9341_IFACE1_LANDSCAPE
  285. # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_LANDSCAPE_PARAM1
  286. # define ILI9341_IFACE1_STRIDE ILI9341_YRES
  287. # elif CONFIG_LCD_ILI9341_IFACE1_PORTRAIT
  288. # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_PORTRAIT_PARAM1
  289. # define ILI9341_IFACE1_STRIDE ILI9341_XRES
  290. # elif CONFIG_LCD_ILI9341_IFACE1_RLANDSCAPE
  291. # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_RLANDSCAPE_PARAM1
  292. # define ILI9341_IFACE1_STRIDE ILI9341_YRES
  293. # elif CONFIG_LCD_ILI9341_IFACE1_RPORTRAIT
  294. # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_RPORTRAIT_PARAM1
  295. # define ILI9341_IFACE1_STRIDE ILI9341_XRES
  296. # endif
  297. # ifdef CONFIG_LCD_ILI9341_IFACE1_RGB565
  298. # define ILI9341_IFACE1_PXFMT FB_FMT_RGB16_565
  299. # define ILI9341_IFACE1_BPP 16
  300. # define ILI9341_IFACE1_BUFFER ILI9341_IFACE1_STRIDE
  301. # else
  302. # error "undefined pixel format for lcd interface 1"
  303. # endif
  304. #endif
  305. /****************************************************************************
  306. * Private Type Definition
  307. ****************************************************************************/
  308. /* Each single connected ili9341 LCD driver needs an own driver instance
  309. * to provide a unique getrun and putrun method. Also store fundamental
  310. * parameter in driver internal structure. This minimal overhead should be
  311. * acceptable.
  312. */
  313. struct ili9341_dev_s
  314. {
  315. /* Publicly visible device structure */
  316. struct lcd_dev_s dev;
  317. /* Private driver-specific information follows */
  318. FAR struct ili9341_lcd_s *lcd;
  319. /* Driver specific putrun function */
  320. int (*putrun)(fb_coord_t row, fb_coord_t col,
  321. FAR const uint8_t * buffer, size_t npixels);
  322. #ifndef CONFIG_LCD_NOGETRUN
  323. /* Driver specific getrun function */
  324. int (*getrun)(fb_coord_t row, fb_coord_t col,
  325. FAR uint8_t * buffer, size_t npixels);
  326. #endif
  327. /* Run buffer for the device */
  328. uint16_t *runbuffer;
  329. /* Display orientation, e.g. Landscape, Portrait */
  330. uint8_t orient;
  331. /* LCD driver pixel format */
  332. uint8_t pxfmt;
  333. /* LCD driver color depth */
  334. uint8_t bpp;
  335. /* Current power state of the device */
  336. uint8_t power;
  337. };
  338. /****************************************************************************
  339. * Private Function Protototypes
  340. ****************************************************************************/
  341. /* Internal low level helpers */
  342. static inline uint16_t ili9341_getxres(FAR struct ili9341_dev_s *dev);
  343. static inline uint16_t ili9341_getyres(FAR struct ili9341_dev_s *dev);
  344. /* lcd data transfer methods */
  345. static int ili9341_putrun(int devno, fb_coord_t row, fb_coord_t col,
  346. FAR const uint8_t * buffer, size_t npixels);
  347. #ifndef CONFIG_LCD_NOGETRUN
  348. static int ili9341_getrun(int devno, fb_coord_t row, fb_coord_t col,
  349. FAR uint8_t * buffer, size_t npixels);
  350. #endif
  351. /* Definition of the public visible getrun / putrun methods
  352. * each for a single LCD driver
  353. */
  354. #ifdef CONFIG_LCD_ILI9341_IFACE0
  355. static int ili9341_putrun0(fb_coord_t row, fb_coord_t col,
  356. FAR const uint8_t *buffer, size_t npixsels);
  357. #endif
  358. #ifdef CONFIG_LCD_ILI9341_IFACE1
  359. static int ili9341_putrun1(fb_coord_t row, fb_coord_t col,
  360. FAR const uint8_t * buffer, size_t npixsels);
  361. #endif
  362. #ifndef CONFIG_LCD_NOGETRUN
  363. # ifdef CONFIG_LCD_ILI9341_IFACE0
  364. static int ili9341_getrun0(fb_coord_t row, fb_coord_t col,
  365. FAR uint8_t * buffer, size_t npixsels);
  366. # endif
  367. # ifdef CONFIG_LCD_ILI9341_IFACE1
  368. static int ili9341_getrun1(fb_coord_t row, fb_coord_t col,
  369. FAR uint8_t * buffer, size_t npixsels);
  370. # endif
  371. #endif
  372. /* lcd configuration */
  373. static int ili9341_getvideoinfo(FAR struct lcd_dev_s *dev,
  374. FAR struct fb_videoinfo_s *vinfo);
  375. static int ili9341_getplaneinfo(FAR struct lcd_dev_s *dev,
  376. unsigned int planeno,
  377. FAR struct lcd_planeinfo_s *pinfo);
  378. /* lcd specific controls */
  379. static int ili9341_getpower(struct lcd_dev_s *dev);
  380. static int ili9341_setpower(struct lcd_dev_s *dev, int power);
  381. static int ili9341_getcontrast(struct lcd_dev_s *dev);
  382. static int ili9341_setcontrast(struct lcd_dev_s *dev, unsigned int contrast);
  383. /****************************************************************************
  384. * Private Data
  385. ****************************************************************************/
  386. /* Initialize driver instance 1 < LCD_ILI9341_NINTERFACES */
  387. #ifdef CONFIG_LCD_ILI9341_IFACE0
  388. static uint16_t g_runbuffer0[ILI9341_IFACE0_BUFFER];
  389. #endif
  390. #ifdef CONFIG_LCD_ILI9341_IFACE1
  391. static uint16_t g_runbuffer1[ILI9341_IFACE1_BUFFER];
  392. #endif
  393. static struct ili9341_dev_s g_lcddev[CONFIG_LCD_ILI9341_NINTERFACES] =
  394. {
  395. #ifdef CONFIG_LCD_ILI9341_IFACE0
  396. {
  397. .lcd = 0,
  398. .putrun = ili9341_putrun0,
  399. # ifndef CONFIG_LCD_NOGETRUN
  400. .getrun = ili9341_getrun0,
  401. # endif
  402. .runbuffer = g_runbuffer0,
  403. .orient = ILI9341_IFACE0_ORIENT,
  404. .pxfmt = ILI9341_IFACE0_PXFMT,
  405. .bpp = ILI9341_IFACE0_BPP,
  406. .power = 0,
  407. },
  408. #endif
  409. #ifdef CONFIG_LCD_ILI9341_IFACE1
  410. {
  411. .lcd = 0,
  412. .putrun = ili9341_putrun1,
  413. # ifndef CONFIG_LCD_NOGETRUN
  414. .getrun = ili9341_getrun1,
  415. # endif
  416. .runbuffer = g_runbuffer1,
  417. .orient = ILI9341_IFACE1_ORIENT,
  418. .pxfmt = ILI9341_IFACE1_PXFMT,
  419. .bpp = ILI9341_IFACE1_BPP,
  420. .power = 0,
  421. },
  422. #endif
  423. };
  424. /****************************************************************************
  425. * Private Functions
  426. ****************************************************************************/
  427. /****************************************************************************
  428. * Name: ili9341_getxres
  429. *
  430. * Description:
  431. * Get horizontal resolution of the connected LCD driver depending on the
  432. * configured display orientation.
  433. *
  434. * Input Parameters:
  435. * dev - Reference to private driver structure
  436. *
  437. * Returned Value:
  438. *
  439. * Horizontal resolution
  440. *
  441. ****************************************************************************/
  442. static inline uint16_t ili9341_getxres(FAR struct ili9341_dev_s *dev)
  443. {
  444. if (dev->orient == ILI9341_MADCTL_LANDSCAPE_PARAM1 ||
  445. dev->orient == ILI9341_MADCTL_RLANDSCAPE_PARAM1)
  446. {
  447. return ILI9341_YRES;
  448. }
  449. return ILI9341_XRES;
  450. }
  451. /****************************************************************************
  452. * Name: ili9341_getyres
  453. *
  454. * Description:
  455. * Get vertical resolution of the connected LCD driver depending on the
  456. * configured display orientation.
  457. *
  458. * Input Parameters:
  459. * dev - Reference to private driver structure
  460. *
  461. * Returned Value:
  462. *
  463. * Vertical resolution
  464. *
  465. ****************************************************************************/
  466. static inline uint16_t ili9341_getyres(FAR struct ili9341_dev_s *dev)
  467. {
  468. if (dev->orient == ILI9341_MADCTL_LANDSCAPE_PARAM1 ||
  469. dev->orient == ILI9341_MADCTL_RLANDSCAPE_PARAM1)
  470. {
  471. return ILI9341_XRES;
  472. }
  473. return ILI9341_YRES;
  474. }
  475. /****************************************************************************
  476. * Name: ili9341_selectarea
  477. *
  478. * Description:
  479. * Select the active area for displaying pixel
  480. *
  481. * Input Parameters:
  482. * lcd - Reference to private driver structure
  483. * x0 - Start x position
  484. * y0 - Start y position
  485. * x1 - End x position
  486. * y1 - End y position
  487. *
  488. ****************************************************************************/
  489. static void ili9341_selectarea(FAR struct ili9341_lcd_s *lcd,
  490. uint16_t x0, uint16_t y0,
  491. uint16_t x1, uint16_t y1)
  492. {
  493. /* Select column */
  494. lcd->sendcmd(lcd, ILI9341_COLUMN_ADDRESS_SET);
  495. lcd->sendparam(lcd, (x0 >> 8));
  496. lcd->sendparam(lcd, (x0 & 0xff));
  497. lcd->sendparam(lcd, (x1 >> 8));
  498. lcd->sendparam(lcd, (x1 & 0xff));
  499. /* Select page */
  500. lcd->sendcmd(lcd, ILI9341_PAGE_ADDRESS_SET);
  501. lcd->sendparam(lcd, (y0 >> 8));
  502. lcd->sendparam(lcd, (y0 & 0xff));
  503. lcd->sendparam(lcd, (y1 >> 8));
  504. lcd->sendparam(lcd, (y1 & 0xff));
  505. }
  506. /****************************************************************************
  507. * Name: ili9341_putrun
  508. *
  509. * Description:
  510. * Write a partial raster line to the LCD.
  511. *
  512. * Input Parameters:
  513. * devno - Number of lcd device
  514. * row - Starting row to write to (range: 0 <= row < yres)
  515. * col - Starting column to write to (range: 0 <= col <= xres-npixels)
  516. * buffer - The buffer containing the run to be written to the LCD
  517. * npixels - The number of pixels to write to the
  518. * (range: 0 < npixels <= xres-col)
  519. *
  520. * Returned Value:
  521. *
  522. * On success - OK
  523. * On error - -EINVAL
  524. *
  525. ****************************************************************************/
  526. static int ili9341_putrun(int devno, fb_coord_t row, fb_coord_t col,
  527. FAR const uint8_t * buffer, size_t npixels)
  528. {
  529. FAR struct ili9341_dev_s *dev = &g_lcddev[devno];
  530. FAR struct ili9341_lcd_s *lcd = dev->lcd;
  531. FAR const uint16_t *src = (FAR const uint16_t *)buffer;
  532. DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
  533. /* Check if position outside of area */
  534. if (col + npixels > ili9341_getxres(dev) || row > ili9341_getyres(dev))
  535. {
  536. return -EINVAL;
  537. }
  538. /* Select lcd driver */
  539. lcd->select(lcd);
  540. /* Select column and area similar to the partial raster line */
  541. ili9341_selectarea(lcd, col, row, col + npixels - 1, row);
  542. /* Send memory write cmd */
  543. lcd->sendcmd(lcd, ILI9341_MEMORY_WRITE);
  544. /* Send pixel to gram */
  545. lcd->sendgram(lcd, src, npixels);
  546. /* Deselect the lcd driver */
  547. lcd->deselect(lcd);
  548. return OK;
  549. }
  550. /****************************************************************************
  551. * Name: ili9341_getrun
  552. *
  553. * Description:
  554. * Read a partial raster line from the LCD.
  555. *
  556. * Input Parameters:
  557. * devno - Number of the lcd device
  558. * row - Starting row to read from (range: 0 <= row < yres)
  559. * col - Starting column to read read (range: 0 <= col <= xres-npixels)
  560. * buffer - The buffer in which to return the run read from the LCD
  561. * npixels - The number of pixels to read from the LCD
  562. * (range: 0 < npixels <= xres-col)
  563. *
  564. * Returned Value:
  565. *
  566. * On success - OK
  567. * On error - -EINVAL
  568. *
  569. ****************************************************************************/
  570. # ifndef CONFIG_LCD_NOGETRUN
  571. static int ili9341_getrun(int devno, fb_coord_t row, fb_coord_t col,
  572. FAR uint8_t * buffer, size_t npixels)
  573. {
  574. FAR struct ili9341_dev_s *dev = &g_lcddev[devno];
  575. FAR struct ili9341_lcd_s *lcd = dev->lcd;
  576. FAR uint16_t *dest = (FAR uint16_t *)buffer;
  577. DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
  578. /* Check if position outside of area */
  579. if (col + npixels > ili9341_getxres(dev) || row > ili9341_getyres(dev))
  580. {
  581. return -EINVAL;
  582. }
  583. /* Select lcd driver */
  584. lcd->select(lcd);
  585. /* Select column and area similar to the partial raster line */
  586. ili9341_selectarea(lcd, col, row, col + npixels - 1, row);
  587. /* Send memory read cmd */
  588. lcd->sendcmd(lcd, ILI9341_MEMORY_READ);
  589. /* Receive pixel to gram */
  590. lcd->recvgram(lcd, dest, npixels);
  591. /* Deselect the lcd driver */
  592. lcd->deselect(lcd);
  593. return OK;
  594. }
  595. #endif
  596. /****************************************************************************
  597. * Name: ili9341_hwinitialize
  598. *
  599. * Description:
  600. * Initialize and configure the ILI9341 LCD driver hardware.
  601. *
  602. * Input Parameters:
  603. * dev - A reference to the driver specific structure
  604. *
  605. * Returned Value:
  606. *
  607. * On success - OK
  608. * On error - EINVAL
  609. *
  610. ****************************************************************************/
  611. static int ili9341_hwinitialize(FAR struct ili9341_dev_s *dev)
  612. {
  613. #ifdef CONFIG_DEBUG_LCD_INFO
  614. uint8_t param;
  615. #endif
  616. FAR struct ili9341_lcd_s *lcd = dev->lcd;
  617. /* Select spi device */
  618. lcdinfo("Initialize lcd driver\n");
  619. lcd->select(lcd);
  620. #ifdef CONFIG_DEBUG_LCD_INFO
  621. /* Read display identification */
  622. lcd->sendcmd(lcd, ILI9341_READ_ID1);
  623. lcd->recvparam(lcd, &param);
  624. lcdinfo("ili9341 LCD driver: LCD modules manufacturer ID: %d\n", param);
  625. lcd->sendcmd(lcd, ILI9341_READ_ID2);
  626. lcd->recvparam(lcd, &param);
  627. lcdinfo("ili9341 LCD driver: LCD modules driver version ID: %d\n", param);
  628. lcd->sendcmd(lcd, ILI9341_READ_ID3);
  629. lcd->recvparam(lcd, &param);
  630. lcdinfo("ili9341 LCD driver: LCD modules driver ID: %d\n", param);
  631. #endif
  632. /* Reset the lcd display to the default state */
  633. lcdinfo("ili9341 LCD driver: Software Reset\n");
  634. lcd->sendcmd(lcd, ILI9341_SOFTWARE_RESET);
  635. up_mdelay(5);
  636. lcdinfo("ili9341 LCD driver: set Memory Access Control: %04x\n",
  637. dev->orient);
  638. lcd->sendcmd(lcd, ILI9341_MEMORY_ACCESS_CONTROL);
  639. lcd->sendparam(lcd, dev->orient);
  640. /* Select column and area */
  641. ili9341_selectarea(lcd, 0, 0, ILI9341_XRES, ILI9341_YRES);
  642. /* Pixel Format set */
  643. lcd->sendcmd(lcd, ILI9341_PIXEL_FORMAT_SET);
  644. /* 16 bit RGB565 */
  645. lcdinfo("ili9341 LCD driver: Set Pixel Format: %04x\n",
  646. ILI9341_PIXSET_16BITMCU_PARAM1);
  647. lcd->sendparam(lcd, ILI9341_PIXSET_16BITMCU_PARAM1);
  648. /* 18 bit RGB666, add settings here */
  649. lcdinfo("ili9341 LCD driver: Set Interface control\n");
  650. lcd->sendcmd(lcd, ILI9341_INTERFACE_CONTROL);
  651. lcd->sendparam(lcd, ILI9341_IFCTL_PARAM1);
  652. lcd->sendparam(lcd, ILI9341_IFCTL_PARAM2);
  653. lcd->sendparam(lcd, ILI9341_IFCTL_PARAM3);
  654. /* Sleep out */
  655. lcdinfo("ili9341 LCD driver: Sleep Out\n");
  656. lcd->sendcmd(lcd, ILI9341_SLEEP_OUT);
  657. up_mdelay(120);
  658. /* Deselect the device */
  659. lcd->deselect(lcd);
  660. /* Switch display off */
  661. ili9341_setpower(&dev->dev, 0);
  662. return OK;
  663. }
  664. /****************************************************************************
  665. * Public Functions
  666. ****************************************************************************/
  667. /****************************************************************************
  668. * Name: ili9341_putrunx
  669. *
  670. * Description:
  671. * Write a partial raster line to the LCD.
  672. *
  673. * Input Parameters:
  674. * row - Starting row to write to (range: 0 <= row < yres)
  675. * col - Starting column to write to (range: 0 <= col <= xres-npixels)
  676. * buffer - The buffer containing the run to be written to the LCD
  677. * npixels - The number of pixels to write to the
  678. * (range: 0 < npixels <= xres-col)
  679. *
  680. * Returned Value:
  681. *
  682. * On success - OK
  683. * On error - -EINVAL
  684. *
  685. ****************************************************************************/
  686. #ifdef CONFIG_LCD_ILI9341_IFACE0
  687. static int ili9341_putrun0(fb_coord_t row, fb_coord_t col,
  688. FAR const uint8_t * buffer, size_t npixels)
  689. {
  690. return ili9341_putrun(0, row, col, buffer, npixels);
  691. }
  692. #endif
  693. #ifdef CONFIG_LCD_ILI9341_IFACE1
  694. static int ili9341_putrun1(fb_coord_t row, fb_coord_t col,
  695. FAR const uint8_t * buffer, size_t npixels)
  696. {
  697. return ili9341_putrun(1, row, col, buffer, npixels);
  698. }
  699. #endif
  700. /****************************************************************************
  701. * Name: ili9341_getrunx
  702. *
  703. * Description:
  704. * Read a partial raster line from the LCD.
  705. *
  706. * Input Parameters:
  707. * row - Starting row to read from (range: 0 <= row < yres)
  708. * col - Starting column to read from (range: 0 <= col <= xres-npixels)
  709. * buffer - The buffer containing the run to be written to the LCD
  710. * npixels - The number of pixels to read from the
  711. * (range: 0 < npixels <= xres-col)
  712. *
  713. * Returned Value:
  714. *
  715. * On success - OK
  716. * On error - -EINVAL
  717. *
  718. ****************************************************************************/
  719. #ifndef CONFIG_LCD_NOGETRUN
  720. # ifdef CONFIG_LCD_ILI9341_IFACE0
  721. static int ili9341_getrun0(fb_coord_t row, fb_coord_t col,
  722. FAR uint8_t * buffer, size_t npixels)
  723. {
  724. return ili9341_getrun(0, row, col, buffer, npixels);
  725. }
  726. # endif
  727. # ifdef CONFIG_LCD_ILI9341_IFACE1
  728. static int ili9341_getrun1(fb_coord_t row, fb_coord_t col,
  729. FAR uint8_t * buffer, size_t npixels)
  730. {
  731. return ili9341_getrun(1, row, col, buffer, npixels);
  732. }
  733. # endif
  734. #endif
  735. /****************************************************************************
  736. * Name: ili9341_getvideoinfo
  737. *
  738. * Description:
  739. * Get information about the LCD video controller configuration.
  740. *
  741. * Input Parameters:
  742. * dev - A reference to the driver specific structure
  743. * vinfo - A reference to the videoinfo structure
  744. *
  745. * Returned Value:
  746. *
  747. * On success - OK
  748. * On error - -EINVAL
  749. *
  750. ****************************************************************************/
  751. static int ili9341_getvideoinfo(FAR struct lcd_dev_s *dev,
  752. FAR struct fb_videoinfo_s *vinfo)
  753. {
  754. if (dev && vinfo)
  755. {
  756. FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev;
  757. vinfo->fmt = priv->pxfmt;
  758. vinfo->xres = ili9341_getxres(priv);
  759. vinfo->yres = ili9341_getyres(priv);
  760. vinfo->nplanes = 1;
  761. lcdinfo("fmt: %d xres: %d yres: %d nplanes: %d\n",
  762. vinfo->fmt, vinfo->xres, vinfo->yres, vinfo->nplanes);
  763. return OK;
  764. }
  765. return -EINVAL;
  766. }
  767. /****************************************************************************
  768. * Name: ili9341_getplaneinfo
  769. *
  770. * Description:
  771. * Get information about the configuration of each LCD color plane.
  772. *
  773. * Input Parameters:
  774. * dev - A reference to the driver specific structure
  775. * planeno - The plane number
  776. * pinfo - A reference to the planeinfo structure
  777. *
  778. * Returned Value:
  779. *
  780. * On success - OK
  781. * On error - -EINVAL
  782. *
  783. ****************************************************************************/
  784. static int ili9341_getplaneinfo(FAR struct lcd_dev_s *dev,
  785. unsigned int planeno,
  786. FAR struct lcd_planeinfo_s *pinfo)
  787. {
  788. if (dev && pinfo && planeno == 0)
  789. {
  790. FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev;
  791. pinfo->putrun = priv->putrun;
  792. #ifndef CONFIG_LCD_NOGETRUN
  793. pinfo->getrun = priv->getrun;
  794. #endif
  795. pinfo->bpp = priv->bpp;
  796. pinfo->buffer = (FAR uint8_t *)priv->runbuffer; /* Run scratch buffer */
  797. lcdinfo("planeno: %d bpp: %d\n", planeno, pinfo->bpp);
  798. return OK;
  799. }
  800. return -EINVAL;
  801. }
  802. /****************************************************************************
  803. * Name: ili9341_getpower
  804. *
  805. * Description:
  806. * Get the LCD panel power status
  807. * (0: full off - CONFIG_LCD_MAXPOWER: full on.
  808. * On backlit LCDs, this setting may correspond to the backlight setting.
  809. *
  810. * Input Parameters:
  811. * dev - A reference to the driver specific structure
  812. *
  813. * Returned Value:
  814. *
  815. * On success - OK
  816. * On error - -EINVAL
  817. *
  818. ****************************************************************************/
  819. static int ili9341_getpower(FAR struct lcd_dev_s *dev)
  820. {
  821. FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev;
  822. if (priv)
  823. {
  824. lcdinfo("%d\n", priv->power);
  825. return priv->power;
  826. }
  827. return -EINVAL;
  828. }
  829. /****************************************************************************
  830. * Name: ili9341_setpower
  831. *
  832. * Description:
  833. * Enable/disable LCD panel power
  834. * (0: full off - CONFIG_LCD_MAXPOWER: full on).
  835. * On backlight LCDs, this setting may correspond to the backlight setting.
  836. *
  837. * Input Parameters:
  838. * dev - A reference to the driver specific structure
  839. * power - Value of the power
  840. *
  841. * Returned Value:
  842. *
  843. * On success - OK
  844. * On error - -EINVAL
  845. *
  846. ****************************************************************************/
  847. static int ili9341_setpower(FAR struct lcd_dev_s *dev, int power)
  848. {
  849. FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev;
  850. FAR struct ili9341_lcd_s *lcd = priv->lcd;
  851. if (dev)
  852. {
  853. lcdinfo("%d\n", power);
  854. lcd->select(lcd);
  855. if (power > 0)
  856. {
  857. /* Set backlight level */
  858. lcd->backlight(lcd, power);
  859. /* And switch LCD on */
  860. lcd->sendcmd(lcd, ILI9341_DISPLAY_ON);
  861. up_mdelay(120);
  862. }
  863. else
  864. {
  865. /* Switch LCD off */
  866. lcd->sendcmd(lcd, ILI9341_DISPLAY_OFF);
  867. }
  868. lcd->deselect(lcd);
  869. priv->power = power;
  870. return OK;
  871. }
  872. return -EINVAL;
  873. }
  874. /****************************************************************************
  875. * Name: ili9341_getcontrast
  876. *
  877. * Description:
  878. * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
  879. *
  880. * Input Parameters:
  881. * dev - A reference to the lcd driver structure
  882. *
  883. * Returned Value:
  884. *
  885. * On success - current contrast value
  886. * On error - -ENOSYS, not supported by the ili9341.
  887. *
  888. ****************************************************************************/
  889. static int ili9341_getcontrast(struct lcd_dev_s *dev)
  890. {
  891. lcdinfo("Not implemented\n");
  892. return -ENOSYS;
  893. }
  894. /****************************************************************************
  895. * Name: ili9341_setcontrast
  896. *
  897. * Description:
  898. * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
  899. *
  900. * Input Parameters:
  901. * dev - A reference to the lcd driver structure
  902. *
  903. * Returned Value:
  904. *
  905. * On success - OK
  906. * On error - -ENOSYS, not supported by the ili9341.
  907. *
  908. ****************************************************************************/
  909. static int ili9341_setcontrast(struct lcd_dev_s *dev, unsigned int contrast)
  910. {
  911. lcdinfo("contrast: %d\n", contrast);
  912. return -ENOSYS;
  913. }
  914. /****************************************************************************
  915. * Name: ili9341_initialize
  916. *
  917. * Description:
  918. * Initialize the LCD video driver internal structure. Also initialize the
  919. * lcd hardware if not done. The control of the LCD driver is depend on the
  920. * selected MCU interface and part of the platform specific subdriver (see
  921. * config/stm32f429i-disco/src/stm32_ili93414ws.c)
  922. *
  923. * Input Parameters:
  924. *
  925. * lcd - A reference to the platform specific driver instance to control
  926. * the ili9341 display driver.
  927. * devno - A value in the range of 0 through CONFIG_ILI9341_NINTERFACES-1.
  928. * This allows support for multiple LCD devices.
  929. *
  930. * Returned Value:
  931. *
  932. * On success, this function returns a reference to the LCD driver object
  933. * for the specified LCD driver. NULL is returned on any failure.
  934. *
  935. ****************************************************************************/
  936. FAR struct lcd_dev_s *
  937. ili9341_initialize(FAR struct ili9341_lcd_s *lcd, int devno)
  938. {
  939. if (lcd && devno >= 0 && devno < CONFIG_LCD_ILI9341_NINTERFACES)
  940. {
  941. FAR struct ili9341_dev_s *priv = &g_lcddev[devno];
  942. /* Check if initialized */
  943. if (!priv->lcd)
  944. {
  945. FAR struct lcd_dev_s *dev = &priv->dev;
  946. int ret;
  947. /* Initialize internal structure */
  948. dev->getvideoinfo = ili9341_getvideoinfo;
  949. dev->getplaneinfo = ili9341_getplaneinfo;
  950. dev->getpower = ili9341_getpower;
  951. dev->setpower = ili9341_setpower;
  952. dev->getcontrast = ili9341_getcontrast;
  953. dev->setcontrast = ili9341_setcontrast;
  954. priv->lcd = lcd;
  955. /* Initialize the LCD driver */
  956. ret = ili9341_hwinitialize(priv);
  957. if (ret == OK)
  958. {
  959. return &priv->dev;
  960. }
  961. }
  962. }
  963. return NULL;
  964. }
  965. /****************************************************************************
  966. * Name: ili9341_clear
  967. *
  968. * Description:
  969. * This is a non-standard LCD interface. Because of the various rotations,
  970. * clearing the display in the normal way by writing a sequences of runs
  971. * that covers the entire display can be very slow. Here the display is
  972. * cleared by simply setting all GRAM memory to the specified color.
  973. *
  974. * Input Parameters:
  975. * dev - A reference to the lcd driver structure
  976. * color - The background color
  977. *
  978. * Returned Value:
  979. *
  980. * On success - OK
  981. * On error - -EINVAL
  982. *
  983. ****************************************************************************/
  984. int ili9341_clear(FAR struct lcd_dev_s *dev, uint16_t color)
  985. {
  986. FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev;
  987. FAR struct ili9341_lcd_s *lcd = priv->lcd;
  988. uint16_t xres = ili9341_getxres(priv);
  989. uint16_t yres = ili9341_getyres(priv);
  990. uint32_t n;
  991. if (!lcd)
  992. {
  993. return -EINVAL;
  994. }
  995. /* Select lcd driver */
  996. lcd->select(lcd);
  997. /* Select column and area similar to the visible area */
  998. ili9341_selectarea(lcd, 0, 0, xres, yres);
  999. /* Send memory write cmd */
  1000. lcd->sendcmd(lcd, ILI9341_MEMORY_WRITE);
  1001. /* clear the visible area */
  1002. for (n = 0; n < xres * yres; n++)
  1003. {
  1004. /* Send pixel to gram */
  1005. lcd->sendgram(lcd, &color, 1);
  1006. }
  1007. /* Deselect the lcd driver */
  1008. lcd->deselect(lcd);
  1009. return OK;
  1010. }