lpm013m091a.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. /****************************************************************************
  2. * drivers/lcd/lpm013m091a.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. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <sys/types.h>
  25. #include <stdint.h>
  26. #include <stdbool.h>
  27. #include <string.h>
  28. #include <assert.h>
  29. #include <errno.h>
  30. #include <debug.h>
  31. #include <nuttx/arch.h>
  32. #include <nuttx/lcd/lcd.h>
  33. #include <nuttx/lcd/lpm013m091a.h>
  34. /****************************************************************************
  35. * Pre-processor Definitions
  36. ****************************************************************************/
  37. /* Display resolution */
  38. #define LPM013M091A_XRES 320
  39. #define LPM013M091A_YRES 300
  40. /* TODO: Stride should be configurable by LCD orientation */
  41. #define LPM013M091A_STRIDE LPM013M091A_XRES
  42. /* Dolor depth and format */
  43. #define LPM013M091A_BPP 16
  44. #define LPM013M091A_COLORFMT FB_FMT_RGB16_565
  45. /****************************************************************************
  46. * Private types
  47. ****************************************************************************/
  48. struct lpm013m091a_dev_s
  49. {
  50. /* Publicly visible device structure */
  51. struct lcd_dev_s dev;
  52. /* Private lcd-specific information follows */
  53. struct lpm013m091a_lcd_s *lcd;
  54. uint8_t power; /* Current power setting */
  55. };
  56. /****************************************************************************
  57. * Private Function Protototypes
  58. ****************************************************************************/
  59. static void lpm013m091a_selectarea(FAR struct lpm013m091a_lcd_s *lcd,
  60. uint16_t x0, int16_t y0,
  61. uint16_t x1, int16_t y1);
  62. static int lpm013m091a_hwinitialize(FAR struct lpm013m091a_dev_s *dev);
  63. /* lcd data transfer methods */
  64. static int lpm013m091a_putrun(fb_coord_t row, fb_coord_t col,
  65. FAR const uint8_t *buffer, size_t npixels);
  66. #ifndef CONFIG_LCD_NOGETRUN
  67. static int lpm013m091a_getrun(fb_coord_t row, fb_coord_t col,
  68. FAR uint8_t *buffer,
  69. size_t npixels);
  70. #endif
  71. /* lcd configuration */
  72. static int lpm013m091a_getvideoinfo(FAR struct lcd_dev_s *dev,
  73. FAR struct fb_videoinfo_s *vinfo);
  74. static int lpm013m091a_getplaneinfo(FAR struct lcd_dev_s *dev,
  75. unsigned int planeno,
  76. FAR struct lcd_planeinfo_s *pinfo);
  77. /* lcd specific controls */
  78. static int lpm013m091a_getpower(FAR struct lcd_dev_s *dev);
  79. static int lpm013m091a_setpower(FAR struct lcd_dev_s *dev, int power);
  80. static int lpm013m091a_getcontrast(FAR struct lcd_dev_s *dev);
  81. static int lpm013m091a_setcontrast(FAR struct lcd_dev_s *dev,
  82. unsigned int contrast);
  83. /****************************************************************************
  84. * Private Data
  85. ****************************************************************************/
  86. static uint16_t g_runbuffer[LPM013M091A_STRIDE];
  87. /* This structure describes the overall lcd video controller */
  88. static const struct fb_videoinfo_s g_videoinfo =
  89. {
  90. .fmt = LPM013M091A_COLORFMT, /* Color format: rgb16-565: rrrr rggg gggb bbbb */
  91. .xres = LPM013M091A_XRES, /* Horizontal resolution in pixel columns */
  92. .yres = LPM013M091A_YRES, /* Vertical resolution in pixel rows */
  93. .nplanes = 1, /* Number of color planes supported */
  94. };
  95. /* This is the standard, nuttx plane information object */
  96. static const struct lcd_planeinfo_s g_planeinfo =
  97. {
  98. .putrun = lpm013m091a_putrun, /* Put a run into lcd memory */
  99. #ifndef CONFIG_LCD_NOGETRUN
  100. .getrun = lpm013m091a_getrun, /* Get a run from lcd memory */
  101. #endif
  102. .buffer = (uint8_t *) g_runbuffer, /* Run scratch buffer */
  103. .bpp = LPM013M091A_BPP, /* Bits-per-pixel */
  104. };
  105. static struct lpm013m091a_dev_s g_lpm013m091a_dev =
  106. {
  107. .dev =
  108. {
  109. /* lcd configuration */
  110. .getvideoinfo = lpm013m091a_getvideoinfo,
  111. .getplaneinfo = lpm013m091a_getplaneinfo,
  112. /* lcd specific controls */
  113. .getpower = lpm013m091a_getpower,
  114. .setpower = lpm013m091a_setpower,
  115. .getcontrast = lpm013m091a_getcontrast,
  116. .setcontrast = lpm013m091a_setcontrast,
  117. },
  118. .lcd = 0,
  119. };
  120. /****************************************************************************
  121. * Private Functions
  122. ****************************************************************************/
  123. /****************************************************************************
  124. * Name: lpm013m091a_selectarea
  125. *
  126. * Description:
  127. * Select the active area for displaying pixel
  128. *
  129. * Parameter:
  130. * lcd - Reference to private driver structure
  131. * x0 - Start x position
  132. * y0 - Start y position
  133. * x1 - End x position
  134. * y1 - End y position
  135. *
  136. ****************************************************************************/
  137. static void lpm013m091a_selectarea(FAR struct lpm013m091a_lcd_s *lcd,
  138. uint16_t x0, int16_t y0,
  139. uint16_t x1, int16_t y1)
  140. {
  141. lcd->sendcmd(lcd, LPM013M091A_CASET);
  142. lcd->sendparam(lcd, x0 >> 8);
  143. lcd->sendparam(lcd, x0 & 0xff);
  144. lcd->sendparam(lcd, x1 >> 8);
  145. lcd->sendparam(lcd, x1 & 0xff);
  146. lcd->sendcmd(lcd, LPM013M091A_PASET);
  147. lcd->sendparam(lcd, y0 >> 8);
  148. lcd->sendparam(lcd, y0 & 0xff);
  149. lcd->sendparam(lcd, y1 >> 8);
  150. lcd->sendparam(lcd, y1 & 0xff);
  151. }
  152. /****************************************************************************
  153. * Name: lpm013m091a_hwinitialize
  154. *
  155. * Description:
  156. * Initialize and configure the LPM013M091A LCD driver hardware.
  157. *
  158. * Parameter:
  159. * dev - A reference to the driver specific structure
  160. *
  161. * Returned Value:
  162. *
  163. * On success - OK
  164. * On error - EINVAL
  165. *
  166. ****************************************************************************/
  167. static int lpm013m091a_hwinitialize(FAR struct lpm013m091a_dev_s *dev)
  168. {
  169. FAR struct lpm013m091a_lcd_s *lcd = dev->lcd;
  170. /* Soft reset */
  171. lcd->sendcmd(lcd, LPM013M091A_SWRESET);
  172. up_mdelay(10);
  173. /* Analog mode */
  174. lcd->sendcmd(lcd, 0xb3);
  175. lcd->sendparam(lcd, 0x02);
  176. /* Set Display Mode */
  177. lcd->sendcmd(lcd, 0xbb);
  178. lcd->sendparam(lcd, 0x10);
  179. /* SPI GRAM access enable */
  180. lcd->sendcmd(lcd, 0xf3);
  181. lcd->sendparam(lcd, 0x02);
  182. /* Bright Level Max */
  183. lcd->sendcmd(lcd, 0x51);
  184. lcd->sendparam(lcd, 0xff);
  185. /* Backlight ON */
  186. lcd->sendcmd(lcd, 0x53);
  187. lcd->sendparam(lcd, 0x24);
  188. /* Frame rate 60Hz */
  189. lcd->sendcmd(lcd, 0xff);
  190. lcd->sendparam(lcd, 0x24);
  191. lcd->sendcmd(lcd, 0xd8);
  192. lcd->sendparam(lcd, 0x41);
  193. lcd->sendcmd(lcd, 0xd9);
  194. lcd->sendparam(lcd, 0x1e);
  195. lcd->sendcmd(lcd, 0xff);
  196. lcd->sendparam(lcd, 0x10);
  197. /* Set the color format (18bit:0x06, 16bit:0x05) */
  198. lcd->sendcmd(lcd, LPM013M091A_PIXFMT);
  199. lcd->sendparam(lcd, 0x05);
  200. /* Sleep out */
  201. lcd->sendcmd(lcd, LPM013M091A_SLPOUT);
  202. up_mdelay(10);
  203. /* Display on */
  204. lcd->sendcmd(lcd, LPM013M091A_DISPON);
  205. up_mdelay(120);
  206. return OK;
  207. }
  208. /****************************************************************************
  209. * Name: lpm013m091a_putrun
  210. *
  211. * Description:
  212. * Write a partial raster line to the LCD.
  213. *
  214. * Parameters:
  215. * devno - Number of lcd device
  216. * row - Starting row to write to (range: 0 <= row < yres)
  217. * col - Starting column to write to (range: 0 <= col <= xres-npixels)
  218. * buffer - The buffer containing the run to be written to the LCD
  219. * npixels - The number of pixels to write to the
  220. * (range: 0 < npixels <= xres-col)
  221. *
  222. * Returned Value:
  223. *
  224. * On success - OK
  225. * On error - -EINVAL
  226. *
  227. ****************************************************************************/
  228. static int lpm013m091a_putrun(fb_coord_t row, fb_coord_t col,
  229. FAR const uint8_t *buffer, size_t npixels)
  230. {
  231. FAR struct lpm013m091a_dev_s *dev = (FAR struct lpm013m091a_dev_s *)
  232. &g_lpm013m091a_dev;
  233. FAR struct lpm013m091a_lcd_s *lcd = dev->lcd;
  234. FAR const uint16_t *src = (FAR const uint16_t *)buffer;
  235. DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
  236. /* Check if position outside of area */
  237. if (col + npixels > LPM013M091A_XRES || row > LPM013M091A_YRES)
  238. {
  239. return -EINVAL;
  240. }
  241. /* Select lcd driver */
  242. lcd->select(lcd);
  243. /* Select column and area similar to the partial raster line */
  244. lpm013m091a_selectarea(lcd, col, row, col + npixels - 1, row);
  245. /* Send memory write cmd */
  246. lcd->sendcmd(lcd, LPM013M091A_RAMWR);
  247. /* Send pixel to gram */
  248. lcd->sendgram(lcd, src, npixels);
  249. /* Deselect the lcd driver */
  250. lcd->deselect(lcd);
  251. return OK;
  252. }
  253. /****************************************************************************
  254. * Name: lpm013m091a_getrun
  255. *
  256. * Description:
  257. * Read a partial raster line from the LCD.
  258. *
  259. * Parameter:
  260. * devno - Number of the lcd device
  261. * row - Starting row to read from (range: 0 <= row < yres)
  262. * col - Starting column to read read (range: 0 <= col <= xres-npixels)
  263. * buffer - The buffer in which to return the run read from the LCD
  264. * npixels - The number of pixels to read from the LCD
  265. * (range: 0 < npixels <= xres-col)
  266. *
  267. * Returned Value:
  268. *
  269. * On success - OK
  270. * On error - -EINVAL
  271. *
  272. ****************************************************************************/
  273. #ifndef CONFIG_LCD_NOGETRUN
  274. int lpm013m091a_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t * buffer,
  275. size_t npixels)
  276. {
  277. lcderr("getrun is not supported for now.\n");
  278. return -ENOSYS;
  279. }
  280. #endif
  281. /****************************************************************************
  282. * Name: lpm013m091a_getvideoinfo
  283. *
  284. * Description:
  285. * Get information about the LCD video controller configuration.
  286. *
  287. * Parameter:
  288. * dev - A reference to the driver specific structure
  289. * vinfo - A reference to the videoinfo structure
  290. *
  291. * Returned Value:
  292. *
  293. * On success - OK
  294. * On error - -EINVAL
  295. *
  296. ****************************************************************************/
  297. static int lpm013m091a_getvideoinfo(FAR struct lcd_dev_s *dev,
  298. FAR struct fb_videoinfo_s *vinfo)
  299. {
  300. if (dev && vinfo)
  301. {
  302. memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s));
  303. lcdinfo("fmt: %d xres: %d yres: %d nplanes: %d\n",
  304. vinfo->fmt, vinfo->xres, vinfo->yres, vinfo->nplanes);
  305. return OK;
  306. }
  307. return -EINVAL;
  308. }
  309. /****************************************************************************
  310. * Name: lpm013m091a_getplaneinfo
  311. *
  312. * Description:
  313. * Get information about the configuration of each LCD color plane.
  314. *
  315. * Parameter:
  316. * dev - A reference to the driver specific structure
  317. * planeno - The plane number
  318. * pinfo - A reference to the planeinfo structure
  319. *
  320. * Returned Value:
  321. *
  322. * On success - OK
  323. * On error - -EINVAL
  324. *
  325. ****************************************************************************/
  326. static int lpm013m091a_getplaneinfo(FAR struct lcd_dev_s *dev,
  327. unsigned int planeno,
  328. FAR struct lcd_planeinfo_s *pinfo)
  329. {
  330. if (dev && pinfo && planeno == 0)
  331. {
  332. memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s));
  333. lcdinfo("planeno: %d bpp: %d\n", planeno, pinfo->bpp);
  334. return OK;
  335. }
  336. return -EINVAL;
  337. }
  338. /****************************************************************************
  339. * Name: lpm013m091a_getpower
  340. *
  341. * Description:
  342. * Get the LCD panel power status
  343. * 0: full off - CONFIG_LCD_MAXPOWER: full on.
  344. * On backlit LCDs, this setting may correspond to the backlight setting.
  345. *
  346. * Parameter:
  347. * dev - A reference to the driver specific structure
  348. *
  349. * Returned Value:
  350. *
  351. * On success - OK
  352. * On error - -EINVAL
  353. *
  354. ****************************************************************************/
  355. static int lpm013m091a_getpower(FAR struct lcd_dev_s *dev)
  356. {
  357. FAR struct lpm013m091a_dev_s *priv = (FAR struct lpm013m091a_dev_s *)dev;
  358. lcdinfo("%d\n", priv->power);
  359. return priv->power;
  360. }
  361. /****************************************************************************
  362. * Name: lpm013m091a_setpower
  363. *
  364. * Description:
  365. * Enable/disable LCD panel power
  366. * (0: full off - CONFIG_LCD_MAXPOWER: full on).
  367. * On backlight LCDs, this setting may correspond to the backlight setting.
  368. *
  369. * Parameter:
  370. * dev - A reference to the driver specific structure
  371. * power - Value of the power
  372. *
  373. * Returned Value:
  374. *
  375. * On success - OK
  376. * On error - -EINVAL
  377. *
  378. ****************************************************************************/
  379. static int lpm013m091a_setpower(FAR struct lcd_dev_s *dev, int power)
  380. {
  381. FAR struct lpm013m091a_dev_s *priv = (FAR struct lpm013m091a_dev_s *)dev;
  382. FAR struct lpm013m091a_lcd_s *lcd = priv->lcd;
  383. if (!dev)
  384. {
  385. return -EINVAL;
  386. }
  387. lcdinfo("%d\n", power);
  388. lcd->select(lcd);
  389. if (power > 0)
  390. {
  391. lcd->backlight(lcd, power);
  392. lcd->sendcmd(lcd, LPM013M091A_DISPON);
  393. up_mdelay(120);
  394. }
  395. else
  396. {
  397. lcd->sendcmd(lcd, LPM013M091A_DISPOFF);
  398. }
  399. lcd->deselect(lcd);
  400. priv->power = power;
  401. return OK;
  402. }
  403. /****************************************************************************
  404. * Name: ili9340_getcontrast
  405. *
  406. * Description:
  407. * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
  408. *
  409. * Parameter:
  410. * dev - A reference to the lcd driver structure
  411. *
  412. * Returned Value:
  413. *
  414. * On success - current contrast value
  415. * On error - -ENOSYS, not supported by the ili9340.
  416. *
  417. ****************************************************************************/
  418. static int lpm013m091a_getcontrast(FAR struct lcd_dev_s *dev)
  419. {
  420. lcdinfo("Not implemented\n");
  421. return -ENOSYS;
  422. }
  423. /****************************************************************************
  424. * Name: ili9340_setcontrast
  425. *
  426. * Description:
  427. * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
  428. *
  429. * Parameter:
  430. * dev - A reference to the lcd driver structure
  431. *
  432. * Returned Value:
  433. *
  434. * On success - OK
  435. * On error - -ENOSYS, not supported by the ili9340.
  436. *
  437. ****************************************************************************/
  438. static int lpm013m091a_setcontrast(FAR struct lcd_dev_s *dev,
  439. unsigned int contrast)
  440. {
  441. lcdinfo("Not implemented\n");
  442. return -ENOSYS;
  443. }
  444. /****************************************************************************
  445. * Public Functions
  446. ****************************************************************************/
  447. /****************************************************************************
  448. * Initialize LCD
  449. ****************************************************************************/
  450. FAR struct lcd_dev_s *
  451. lpm013m091a_initialize(FAR struct lpm013m091a_lcd_s *lcd, int devno)
  452. {
  453. FAR struct lpm013m091a_dev_s *priv = &g_lpm013m091a_dev;
  454. if (lcd && devno == 0)
  455. {
  456. if (!priv->lcd)
  457. {
  458. FAR struct lcd_dev_s *dev = &priv->dev;
  459. int ret;
  460. /* Initialize internal structure */
  461. dev->getvideoinfo = lpm013m091a_getvideoinfo;
  462. dev->getplaneinfo = lpm013m091a_getplaneinfo;
  463. dev->getpower = lpm013m091a_getpower;
  464. dev->setpower = lpm013m091a_setpower;
  465. dev->getcontrast = lpm013m091a_getcontrast;
  466. dev->setcontrast = lpm013m091a_setcontrast;
  467. priv->lcd = lcd;
  468. /* Initialize the LCD driver */
  469. ret = lpm013m091a_hwinitialize(priv);
  470. if (ret == OK)
  471. {
  472. return &priv->dev;
  473. }
  474. }
  475. }
  476. return NULL;
  477. }