ssd1289.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  1. /****************************************************************************
  2. * drivers/lcd/ssd1289.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. /* Generic LCD driver for LCDs based on the Solomon Systech SSD1289 LCD
  21. * controller.
  22. * Think of this as a template for an LCD driver that you will probably have
  23. * to customize for any particular LCD hardware.
  24. *
  25. * References: SSD1289, Rev 1.3, Apr 2007, Solomon Systech Limited
  26. */
  27. /****************************************************************************
  28. * Included Files
  29. ****************************************************************************/
  30. #include <nuttx/config.h>
  31. #include <sys/types.h>
  32. #include <stdint.h>
  33. #include <stdbool.h>
  34. #include <string.h>
  35. #include <assert.h>
  36. #include <errno.h>
  37. #include <debug.h>
  38. #include <nuttx/arch.h>
  39. #include <nuttx/spi/spi.h>
  40. #include <nuttx/lcd/lcd.h>
  41. #include <nuttx/lcd/ssd1289.h>
  42. #include "ssd1289.h"
  43. #ifdef CONFIG_LCD_SSD1289
  44. /****************************************************************************
  45. * Pre-processor Definitions
  46. ****************************************************************************/
  47. /* Configuration ************************************************************/
  48. /* Check contrast selection */
  49. #if !defined(CONFIG_LCD_MAXCONTRAST)
  50. # define CONFIG_LCD_MAXCONTRAST 1
  51. #endif
  52. /* Check power setting */
  53. #if !defined(CONFIG_LCD_MAXPOWER) || CONFIG_LCD_MAXPOWER < 1
  54. # define CONFIG_LCD_MAXPOWER 1
  55. #endif
  56. #if CONFIG_LCD_MAXPOWER > 255
  57. # error "CONFIG_LCD_MAXPOWER must be less than 256 to fit in uint8_t"
  58. #endif
  59. /* Check orientation */
  60. #if defined(CONFIG_LCD_PORTRAIT)
  61. # if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) || defined(CONFIG_LCD_RPORTRAIT)
  62. # error "Cannot define both portrait and any other orientations"
  63. # endif
  64. #elif defined(CONFIG_LCD_RPORTRAIT)
  65. # if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
  66. # error "Cannot define both rportrait and any other orientations"
  67. # endif
  68. #elif defined(CONFIG_LCD_LANDSCAPE)
  69. # ifdef CONFIG_LCD_RLANDSCAPE
  70. # error "Cannot define both landscape and any other orientations"
  71. # endif
  72. #elif !defined(CONFIG_LCD_RLANDSCAPE)
  73. # define CONFIG_LCD_LANDSCAPE 1
  74. #endif
  75. /* Display/Color Properties *************************************************/
  76. /* Display Resolution */
  77. #if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
  78. # define SSD1289_XRES 320
  79. # define SSD1289_YRES 240
  80. #else
  81. # define SSD1289_XRES 240
  82. # define SSD1289_YRES 320
  83. #endif
  84. /* Color depth and format */
  85. #define SSD1289_BPP 16
  86. #define SSD1289_COLORFMT FB_FMT_RGB16_565
  87. /* LCD Profiles *************************************************************/
  88. /* Many details of the controller initialization must, unfortunately, vary
  89. * from LCD to LCD. I have looked at the spec and at three different drivers
  90. * for LCDs that have SSD1289 controllers.
  91. * I have tried to summarize these differences as "LCD profiles"
  92. *
  93. * Most of the differences between LCDs are nothing more than a few minor bit
  94. * settings. The most significant difference between LCD drivers in is the
  95. * manner in which the LCD is powered up and in how the power controls are
  96. * set.
  97. * My suggestion is that if you have working LCD initialization code, you
  98. * should simply replace the code in ssd1289_hwinitialize with your working
  99. * code.
  100. */
  101. #if defined (CONFIG_SSD1289_PROFILE2)
  102. # undef SSD1289_USE_SIMPLE_INIT
  103. /* PWRCTRL1: AP=smalll-to-medium, DC=Flinex24, BT=+5/-4, DCT=Flinex24 */
  104. # define PWRCTRL1_SETTING \
  105. (SSD1289_PWRCTRL1_AP_SMMED | SSD1289_PWRCTRL1_DC_FLINEx24 | \
  106. SSD1289_PWRCTRL1_BT_p5m4 | SSD1289_PWRCTRL1_DCT_FLINEx24)
  107. /* PWRCTRL2: 5.1v */
  108. # define PWRCTRL2_SETTING SSD1289_PWRCTRL2_VRC_5p1V
  109. /* PWRCTRL3: x 2.165
  110. * NOTE:
  111. * Many drivers have bit 8 set which is not defined in the SSD1289 spec.
  112. */
  113. # define PWRCTRL3_SETTING SSD1289_PWRCTRL3_VRH_x2p165
  114. /* PWRCTRL4: VDV=9 + VCOMG */
  115. # define PWRCTRL4_SETTING (SSD1289_PWRCTRL4_VDV(9) | SSD1289_PWRCTRL4_VCOMG)
  116. /* PWRCTRL5: VCM=56 + NOTP */
  117. # define PWRCTRL5_SETTING (SSD1289_PWRCTRL5_VCM(56) | SSD1289_PWRCTRL5_NOTP)
  118. #elif defined (CONFIG_SSD1289_PROFILE3)
  119. # undef SSD1289_USE_SIMPLE_INIT
  120. /* PWRCTRL1: AP=smalll-to-medium, DC=Flinex24, BT=+5/-4, DCT=Flinex24 */
  121. # define PWRCTRL1_SETTING \
  122. (SSD1289_PWRCTRL1_AP_SMMED | SSD1289_PWRCTRL1_DC_FLINEx24 | \
  123. SSD1289_PWRCTRL1_BT_p5m4 | SSD1289_PWRCTRL1_DCT_FLINEx24)
  124. /* PWRCTRL2: 5.1v */
  125. # define PWRCTRL2_SETTING SSD1289_PWRCTRL2_VRC_5p1V
  126. /* PWRCTRL3: x 2.165
  127. * NOTE:
  128. * Many drivers have bit 8 set which is not defined in the SSD1289 spec.
  129. */
  130. # define PWRCTRL3_SETTING SSD1289_PWRCTRL3_VRH_x2p165
  131. /* PWRCTRL4: VDV=9 + VCOMG */
  132. # define PWRCTRL4_SETTING (SSD1289_PWRCTRL4_VDV(9) | SSD1289_PWRCTRL4_VCOMG)
  133. /* PWRCTRL5: VCM=56 + NOTP */
  134. # define PWRCTRL5_SETTING (SSD1289_PWRCTRL5_VCM(56) | SSD1289_PWRCTRL5_NOTP)
  135. #else /* if defined (CONFIG_SSD1289_PROFILE1) */
  136. # undef SSD1289_USE_SIMPLE_INIT
  137. # define SSD1289_USE_SIMPLE_INIT 1
  138. /* PWRCTRL1: AP=medium-to-large, DC=Fosc/4, BT=+5/-4, DCT=Fosc/4 */
  139. # define PWRCTRL1_SETTING \
  140. (SSD1289_PWRCTRL1_AP_MEDLG | SSD1289_PWRCTRL1_DC_FOSd4 | \
  141. SSD1289_PWRCTRL1_BT_p5m4 | SSD1289_PWRCTRL1_DCT_FOSd4)
  142. /* PWRCTRL2: 5.3v */
  143. # define PWRCTRL2_SETTING SSD1289_PWRCTRL2_VRC_5p3V
  144. /* PWRCTRL3: x 2.570
  145. * NOTE:
  146. * Many drivers have bit 8 set which is not defined in the SSD1289 spec.
  147. */
  148. # define PWRCTRL3_SETTING SSD1289_PWRCTRL3_VRH_x2p570
  149. /* PWRCTRL4: VDV=12 + VCOMG */
  150. # define PWRCTRL4_SETTING (SSD1289_PWRCTRL4_VDV(12) | SSD1289_PWRCTRL4_VCOMG)
  151. /* PWRCTRL5: VCM=60 + NOTP */
  152. # define PWRCTRL5_SETTING (SSD1289_PWRCTRL5_VCM(60) | SSD1289_PWRCTRL5_NOTP)
  153. #endif
  154. /****************************************************************************
  155. * Private Type Definition
  156. ****************************************************************************/
  157. /* This structure describes the state of this driver */
  158. struct ssd1289_dev_s
  159. {
  160. /* Publicly visible device structure */
  161. struct lcd_dev_s dev;
  162. /* Private LCD-specific information follows */
  163. FAR struct ssd1289_lcd_s *lcd; /* The contained platform-specific, LCD interface */
  164. uint8_t power; /* Current power setting */
  165. /* These fields simplify and reduce debug output */
  166. #ifdef CONFIG_DEBUG_LCD
  167. bool put; /* Last raster operation was a putrun */
  168. fb_coord_t firstrow; /* First row of the run */
  169. fb_coord_t lastrow; /* Last row of the run */
  170. fb_coord_t col; /* Column of the run */
  171. size_t npixels; /* Length of the run */
  172. #endif
  173. /* This is working memory allocated by the LCD driver for each LCD device
  174. * and for each color plane. This memory will hold one raster line of
  175. * data.
  176. * The size of the allocated run buffer must therefore be at least
  177. * (bpp * xres / 8). Actual alignment of the buffer must conform to the
  178. * bitwidth of the underlying pixel type.
  179. *
  180. * If there are multiple planes, they may share the same working buffer
  181. * because different planes will not be operate on concurrently. However,
  182. * if there are multiple LCD devices, they must each have unique run
  183. * buffers.
  184. */
  185. uint16_t runbuffer[SSD1289_XRES];
  186. };
  187. /****************************************************************************
  188. * Private Function Protototypes
  189. ****************************************************************************/
  190. /* Low Level LCD access */
  191. static void ssd1289_putreg(FAR struct ssd1289_lcd_s *lcd,
  192. uint8_t regaddr,
  193. uint16_t regval);
  194. #ifndef CONFIG_LCD_NOGETRUN
  195. static uint16_t ssd1289_readreg(FAR struct ssd1289_lcd_s *lcd,
  196. uint8_t regaddr);
  197. #endif
  198. static inline void ssd1289_gramwrite(FAR struct ssd1289_lcd_s *lcd,
  199. uint16_t rgbcolor);
  200. #ifndef CONFIG_LCD_NOGETRUN
  201. static inline void ssd1289_readsetup(FAR struct ssd1289_lcd_s *lcd,
  202. FAR uint16_t *accum);
  203. static inline uint16_t ssd1289_gramread(FAR struct ssd1289_lcd_s *lcd,
  204. FAR uint16_t *accum);
  205. #endif
  206. static void ssd1289_setcursor(FAR struct ssd1289_lcd_s *lcd,
  207. uint16_t column,
  208. uint16_t row);
  209. /* LCD Data Transfer Methods */
  210. #if 0 /* Sometimes useful */
  211. static void ssd1289_dumprun(FAR const char *msg, FAR uint16_t *run,
  212. size_t npixels);
  213. #else
  214. # define ssd1289_dumprun(m,r,n)
  215. #endif
  216. #ifdef CONFIG_DEBUG_LCD
  217. static void ssd1289_showrun(FAR struct ssd1289_dev_s *priv, fb_coord_t row,
  218. fb_coord_t col, size_t npixels, bool put);
  219. #else
  220. # define ssd1289_showrun(p,r,c,n,b)
  221. #endif
  222. static int ssd1289_putrun(fb_coord_t row, fb_coord_t col,
  223. FAR const uint8_t *buffer,
  224. size_t npixels);
  225. static int ssd1289_getrun(fb_coord_t row, fb_coord_t col,
  226. FAR uint8_t *buffer,
  227. size_t npixels);
  228. /* LCD Configuration */
  229. static int ssd1289_getvideoinfo(FAR struct lcd_dev_s *dev,
  230. FAR struct fb_videoinfo_s *vinfo);
  231. static int ssd1289_getplaneinfo(FAR struct lcd_dev_s *dev,
  232. unsigned int planeno,
  233. FAR struct lcd_planeinfo_s *pinfo);
  234. /* LCD RGB Mapping */
  235. #ifdef CONFIG_FB_CMAP
  236. # error "RGB color mapping not supported by this driver"
  237. #endif
  238. /* Cursor Controls */
  239. #ifdef CONFIG_FB_HWCURSOR
  240. # error "Cursor control not supported by this driver"
  241. #endif
  242. /* LCD Specific Controls */
  243. static int ssd1289_getpower(FAR struct lcd_dev_s *dev);
  244. static int ssd1289_setpower(FAR struct lcd_dev_s *dev, int power);
  245. static int ssd1289_getcontrast(FAR struct lcd_dev_s *dev);
  246. static int ssd1289_setcontrast(FAR struct lcd_dev_s *dev,
  247. unsigned int contrast);
  248. /* Initialization */
  249. static inline int ssd1289_hwinitialize(FAR struct ssd1289_dev_s *priv);
  250. /****************************************************************************
  251. * Private Data
  252. ****************************************************************************/
  253. /* This driver can support only a signal SSD1289 device. This is due to an
  254. * unfortunate decision made whent he getrun and putrun methods were
  255. * designed. The following is the single SSD1289 driver state instance:
  256. */
  257. static struct ssd1289_dev_s g_lcddev;
  258. /****************************************************************************
  259. * Private Functions
  260. ****************************************************************************/
  261. /****************************************************************************
  262. * Name: ssd1289_putreg(lcd,
  263. *
  264. * Description:
  265. * Write to an LCD register
  266. *
  267. ****************************************************************************/
  268. static void ssd1289_putreg(FAR struct ssd1289_lcd_s *lcd,
  269. uint8_t regaddr, uint16_t regval)
  270. {
  271. /* Set the index register to the register address and write the register
  272. * contents
  273. */
  274. lcd->index(lcd, regaddr);
  275. lcd->write(lcd, regval);
  276. }
  277. /****************************************************************************
  278. * Name: ssd1289_readreg
  279. *
  280. * Description:
  281. * Read from an LCD register
  282. *
  283. ****************************************************************************/
  284. #ifndef CONFIG_LCD_NOGETRUN
  285. static uint16_t ssd1289_readreg(FAR struct ssd1289_lcd_s *lcd,
  286. uint8_t regaddr)
  287. {
  288. /* Set the index register to the register address and read the register
  289. * contents
  290. */
  291. lcd->index(lcd, regaddr);
  292. return lcd->read(lcd);
  293. }
  294. #endif
  295. /****************************************************************************
  296. * Name: ssd1289_gramselect
  297. *
  298. * Description:
  299. * Setup to read or write multiple pixels to the GRAM memory
  300. *
  301. ****************************************************************************/
  302. static inline void ssd1289_gramselect(FAR struct ssd1289_lcd_s *lcd)
  303. {
  304. lcd->index(lcd, SSD1289_DATA);
  305. }
  306. /****************************************************************************
  307. * Name: ssd1289_gramwrite
  308. *
  309. * Description:
  310. * Setup to read or write multiple pixels to the GRAM memory
  311. *
  312. ****************************************************************************/
  313. static inline void ssd1289_gramwrite(FAR struct ssd1289_lcd_s *lcd,
  314. uint16_t data)
  315. {
  316. lcd->write(lcd, data);
  317. }
  318. /****************************************************************************
  319. * Name: ssd1289_readsetup
  320. *
  321. * Description:
  322. * Prime the operation by reading one pixel from the GRAM memory if
  323. * necessary for this LCD type. When reading 16-bit gram data, there
  324. * may be some shifts in the returned data:
  325. *
  326. * - ILI932x: Discard first dummy read; no shift in the return data
  327. *
  328. ****************************************************************************/
  329. #ifndef CONFIG_LCD_NOGETRUN
  330. static inline void ssd1289_readsetup(FAR struct ssd1289_lcd_s *lcd,
  331. FAR uint16_t *accum)
  332. {
  333. /* Read-ahead one pixel */
  334. *accum = lcd->read(lcd);
  335. }
  336. #endif
  337. /****************************************************************************
  338. * Name: ssd1289_gramread
  339. *
  340. * Description:
  341. * Read one correctly aligned pixel from the GRAM memory.
  342. * Possibly shifting the data and possibly swapping red and green
  343. * components.
  344. *
  345. * - ILI932x: Unknown -- assuming colors are in the color order
  346. *
  347. ****************************************************************************/
  348. #ifndef CONFIG_LCD_NOGETRUN
  349. static inline uint16_t ssd1289_gramread(FAR struct ssd1289_lcd_s *lcd,
  350. FAR uint16_t *accum)
  351. {
  352. /* Read the value (GRAM register already selected) */
  353. return lcd->read(lcd);
  354. }
  355. #endif
  356. /****************************************************************************
  357. * Name: ssd1289_setcursor
  358. *
  359. * Description:
  360. * Set the cursor position.
  361. * In landscape mode, the "column" is actually the physical
  362. * Y position and the "row" is the physical X position.
  363. *
  364. ****************************************************************************/
  365. static void ssd1289_setcursor(FAR struct ssd1289_lcd_s *lcd,
  366. uint16_t column, uint16_t row)
  367. {
  368. #if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT)
  369. ssd1289_putreg(lcd, SSD1289_XADDR, column); /* 0-239 */
  370. ssd1289_putreg(lcd, SSD1289_YADDR, row); /* 0-319 */
  371. #elif defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
  372. ssd1289_putreg(lcd, SSD1289_XADDR, row); /* 0-239 */
  373. ssd1289_putreg(lcd, SSD1289_YADDR, column); /* 0-319 */
  374. #endif
  375. }
  376. /****************************************************************************
  377. * Name: ssd1289_dumprun
  378. *
  379. * Description:
  380. * Dump the contexts of the run buffer:
  381. *
  382. * run - The buffer in containing the run read to be dumped
  383. * npixels - The number of pixels to dump
  384. *
  385. ****************************************************************************/
  386. #if 0 /* Sometimes useful */
  387. static void ssd1289_dumprun(FAR const char *msg,
  388. FAR uint16_t *run, size_t npixels)
  389. {
  390. int i;
  391. int j;
  392. syslog(LOG_INFO, "\n%s:\n", msg);
  393. for (i = 0; i < npixels; i += 16)
  394. {
  395. up_putc(' ');
  396. syslog(LOG_INFO, " ");
  397. for (j = 0; j < 16; j++)
  398. {
  399. syslog(LOG_INFO, " %04x", *run++);
  400. }
  401. up_putc('\n');
  402. }
  403. }
  404. #endif
  405. /****************************************************************************
  406. * Name: ssd1289_showrun
  407. *
  408. * Description:
  409. * When LCD debug is enabled, try to reduce then amount of output data
  410. * generated by ssd1289_putrun and ssd1289_getrun
  411. *
  412. ****************************************************************************/
  413. #ifdef CONFIG_DEBUG_LCD
  414. static void ssd1289_showrun(FAR struct ssd1289_dev_s *priv, fb_coord_t row,
  415. fb_coord_t col, size_t npixels, bool put)
  416. {
  417. fb_coord_t nextrow = priv->lastrow + 1;
  418. /* Has anything changed
  419. * (other than the row is the next row in the sequence)?
  420. */
  421. if (put == priv->put && row == nextrow && col == priv->col &&
  422. npixels == priv->npixels)
  423. {
  424. /* No, just update the last row */
  425. priv->lastrow = nextrow;
  426. }
  427. else
  428. {
  429. /* Yes... then this is the end of the preceding sequence.
  430. * Output the last run
  431. * (if there were more than one run in the sequence).
  432. */
  433. if (priv->firstrow != priv->lastrow)
  434. {
  435. lcdinfo("...\n");
  436. lcdinfo("%s row: %d col: %d npixels: %d\n",
  437. priv->put ? "PUT" : "GET",
  438. priv->lastrow, priv->col, priv->npixels);
  439. }
  440. /* And we are starting a new sequence. Output the first run of the
  441. * new sequence
  442. */
  443. lcdinfo("%s row: %d col: %d npixels: %d\n",
  444. put ? "PUT" : "GET", row, col, npixels);
  445. /* And save information about the run so that we can detect
  446. * continuations of the sequence.
  447. */
  448. priv->put = put;
  449. priv->firstrow = row;
  450. priv->lastrow = row;
  451. priv->col = col;
  452. priv->npixels = npixels;
  453. }
  454. }
  455. #endif
  456. /****************************************************************************
  457. * Name: ssd1289_putrun
  458. *
  459. * Description:
  460. * This method can be used to write a partial raster line to the LCD:
  461. *
  462. * row - Starting row to write to (range: 0 <= row < yres)
  463. * col - Starting column to write to (range: 0 <= col <= xres-npixels)
  464. * buffer - The buffer containing the run to be written to the LCD
  465. * npixels - The number of pixels to write to the LCD
  466. * (range: 0 < npixels <= xres-col)
  467. *
  468. ****************************************************************************/
  469. static int ssd1289_putrun(fb_coord_t row, fb_coord_t col,
  470. FAR const uint8_t *buffer,
  471. size_t npixels)
  472. {
  473. FAR struct ssd1289_dev_s *priv = &g_lcddev;
  474. FAR struct ssd1289_lcd_s *lcd = priv->lcd;
  475. FAR const uint16_t *src = (FAR const uint16_t *)buffer;
  476. int i;
  477. /* Buffer must be provided and aligned to a 16-bit address boundary */
  478. ssd1289_showrun(priv, row, col, npixels, true);
  479. DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
  480. /* Select the LCD */
  481. lcd->select(lcd);
  482. /* Write the run to GRAM. */
  483. #ifdef CONFIG_LCD_LANDSCAPE
  484. /* Convert coordinates -- Here the edge away from the row of buttons on
  485. * the STM3240G-EVAL is used as the top.
  486. */
  487. /* Write the GRAM data, manually incrementing X */
  488. for (i = 0; i < npixels; i++)
  489. {
  490. /* Write the next pixel to this position */
  491. ssd1289_setcursor(lcd, col, row);
  492. ssd1289_gramselect(lcd);
  493. ssd1289_gramwrite(lcd, *src);
  494. /* Increment to the next column */
  495. src++;
  496. col++;
  497. }
  498. #elif defined(CONFIG_LCD_RLANDSCAPE)
  499. /* Convert coordinates -- Here the edge next to the row of buttons on
  500. * the STM3240G-EVAL is used as the top.
  501. */
  502. col = (SSD1289_XRES - 1) - col;
  503. row = (SSD1289_YRES - 1) - row;
  504. /* Set the cursor position */
  505. ssd1289_setcursor(lcd, col, row);
  506. /* Then write the GRAM data, auto-decrementing X */
  507. ssd1289_gramselect(lcd);
  508. for (i = 0; i < npixels; i++)
  509. {
  510. /* Write the next pixel to this position
  511. * (auto-decrements to the next column)
  512. */
  513. ssd1289_gramwrite(lcd, *src);
  514. src++;
  515. }
  516. #elif defined(CONFIG_LCD_PORTRAIT)
  517. /* Convert coordinates.
  518. * In this configuration, the top of the display is to the left
  519. * of the buttons (if the board is held so that the buttons are
  520. * at the bottom of the board).
  521. */
  522. col = (SSD1289_XRES - 1) - col;
  523. /* Then write the GRAM data, manually incrementing Y (which is col) */
  524. for (i = 0; i < npixels; i++)
  525. {
  526. /* Write the next pixel to this position */
  527. ssd1289_setcursor(lcd, row, col);
  528. ssd1289_gramselect(lcd);
  529. ssd1289_gramwrite(lcd, *src);
  530. /* Increment to the next column */
  531. src++;
  532. col--;
  533. }
  534. #else /* CONFIG_LCD_RPORTRAIT */
  535. /* Convert coordinates. In this configuration, the top of the display is to the right
  536. * of the buttons (if the board is held so that the buttons are at the bottom of the
  537. * board).
  538. */
  539. row = (SSD1289_YRES - 1) - row;
  540. /* Then write the GRAM data, manually incrementing Y (which is col) */
  541. for (i = 0; i < npixels; i++)
  542. {
  543. /* Write the next pixel to this position */
  544. ssd1289_setcursor(lcd, row, col);
  545. ssd1289_gramselect(lcd);
  546. ssd1289_gramwrite(lcd, *src);
  547. /* Decrement to the next column */
  548. src++;
  549. col++;
  550. }
  551. #endif
  552. /* De-select the LCD */
  553. lcd->deselect(lcd);
  554. return OK;
  555. }
  556. /****************************************************************************
  557. * Name: ssd1289_getrun
  558. *
  559. * Description:
  560. * This method can be used to read a partial raster line from the LCD:
  561. *
  562. * row - Starting row to read from (range: 0 <= row < yres)
  563. * col - Starting column to read read (range: 0 <= col <= xres-npixels)
  564. * buffer - The buffer in which to return the run read from the LCD
  565. * npixels - The number of pixels to read from the LCD
  566. * (range: 0 < npixels <= xres-col)
  567. *
  568. ****************************************************************************/
  569. static int ssd1289_getrun(fb_coord_t row, fb_coord_t col,
  570. FAR uint8_t *buffer,
  571. size_t npixels)
  572. {
  573. #ifndef CONFIG_LCD_NOGETRUN
  574. FAR struct ssd1289_dev_s *priv = &g_lcddev;
  575. FAR struct ssd1289_lcd_s *lcd = priv->lcd;
  576. FAR uint16_t *dest = (FAR uint16_t *)buffer;
  577. uint16_t accum;
  578. int i;
  579. /* Buffer must be provided and aligned to a 16-bit address boundary */
  580. ssd1289_showrun(priv, row, col, npixels, false);
  581. DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
  582. /* Select the LCD */
  583. lcd->select(lcd);
  584. /* Read the run from GRAM. */
  585. #ifdef CONFIG_LCD_LANDSCAPE
  586. /* Convert coordinates -- Here the edge away from the row of buttons on
  587. * the STM3240G-EVAL is used as the top.
  588. */
  589. for (i = 0; i < npixels; i++)
  590. {
  591. /* Read the next pixel from this position */
  592. ssd1289_setcursor(lcd, row, col);
  593. ssd1289_gramselect(lcd);
  594. ssd1289_readsetup(lcd, &accum);
  595. *dest++ = ssd1289_gramread(lcd, &accum);
  596. /* Increment to the next column */
  597. col++;
  598. }
  599. #elif defined(CONFIG_LCD_RLANDSCAPE)
  600. /* Convert coordinates -- Here the edge next to the row of buttons on
  601. * the STM3240G-EVAL is used as the top.
  602. */
  603. col = (SSD1289_XRES - 1) - col;
  604. row = (SSD1289_YRES - 1) - row;
  605. /* Set the cursor position */
  606. ssd1289_setcursor(lcd, col, row);
  607. /* Then read the GRAM data, auto-decrementing Y */
  608. ssd1289_gramselect(lcd);
  609. /* Prime the pump for unaligned read data */
  610. ssd1289_readsetup(lcd, &accum);
  611. for (i = 0; i < npixels; i++)
  612. {
  613. /* Read the next pixel from this position
  614. * (autoincrements to the next row)
  615. */
  616. *dest++ = ssd1289_gramread(lcd, &accum);
  617. }
  618. #elif defined(CONFIG_LCD_PORTRAIT)
  619. /* Convert coordinates. In this configuration, the top of the display is
  620. * to the left of the buttons (if the board is held so that the buttons
  621. * are at the bottom of the board).
  622. */
  623. col = (SSD1289_XRES - 1) - col;
  624. /* Then read the GRAM data, manually incrementing Y (which is col) */
  625. for (i = 0; i < npixels; i++)
  626. {
  627. /* Read the next pixel from this position */
  628. ssd1289_setcursor(lcd, row, col);
  629. ssd1289_gramselect(lcd);
  630. ssd1289_readsetup(lcd, &accum);
  631. *dest++ = ssd1289_gramread(lcd, &accum);
  632. /* Increment to the next column */
  633. col--;
  634. }
  635. #else /* CONFIG_LCD_RPORTRAIT */
  636. /* Convert coordinates. In this configuration, the top of the display is to the right
  637. * of the buttons (if the board is held so that the buttons are at the bottom of the
  638. * board).
  639. */
  640. row = (SSD1289_YRES - 1) - row;
  641. /* Then write the GRAM data, manually incrementing Y (which is col) */
  642. for (i = 0; i < npixels; i++)
  643. {
  644. /* Write the next pixel to this position */
  645. ssd1289_setcursor(lcd, row, col);
  646. ssd1289_gramselect(lcd);
  647. ssd1289_readsetup(lcd, &accum);
  648. *dest++ = ssd1289_gramread(lcd, &accum);
  649. /* Decrement to the next column */
  650. col++;
  651. }
  652. #endif
  653. /* De-select the LCD */
  654. lcd->deselect(lcd);
  655. return OK;
  656. #else
  657. return -ENOSYS;
  658. #endif
  659. }
  660. /****************************************************************************
  661. * Name: ssd1289_getvideoinfo
  662. *
  663. * Description:
  664. * Get information about the LCD video controller configuration.
  665. *
  666. ****************************************************************************/
  667. static int ssd1289_getvideoinfo(FAR struct lcd_dev_s *dev,
  668. FAR struct fb_videoinfo_s *vinfo)
  669. {
  670. DEBUGASSERT(dev && vinfo);
  671. lcdinfo("fmt: %d xres: %d yres: %d nplanes: 1\n",
  672. SSD1289_COLORFMT, SSD1289_XRES, SSD1289_YRES);
  673. vinfo->fmt = SSD1289_COLORFMT; /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */
  674. vinfo->xres = SSD1289_XRES; /* Horizontal resolution in pixel columns */
  675. vinfo->yres = SSD1289_YRES; /* Vertical resolution in pixel rows */
  676. vinfo->nplanes = 1; /* Number of color planes supported */
  677. return OK;
  678. }
  679. /****************************************************************************
  680. * Name: ssd1289_getplaneinfo
  681. *
  682. * Description:
  683. * Get information about the configuration of each LCD color plane.
  684. *
  685. ****************************************************************************/
  686. static int ssd1289_getplaneinfo(FAR struct lcd_dev_s *dev,
  687. unsigned int planeno,
  688. FAR struct lcd_planeinfo_s *pinfo)
  689. {
  690. FAR struct ssd1289_dev_s *priv = (FAR struct ssd1289_dev_s *)dev;
  691. DEBUGASSERT(dev && pinfo && planeno == 0);
  692. lcdinfo("planeno: %d bpp: %d\n", planeno, SSD1289_BPP);
  693. pinfo->putrun = ssd1289_putrun; /* Put a run into LCD memory */
  694. pinfo->getrun = ssd1289_getrun; /* Get a run from LCD memory */
  695. pinfo->buffer = (FAR uint8_t *)priv->runbuffer; /* Run scratch buffer */
  696. pinfo->bpp = SSD1289_BPP; /* Bits-per-pixel */
  697. return OK;
  698. }
  699. /****************************************************************************
  700. * Name: ssd1289_getpower
  701. *
  702. * Description:
  703. * Get the LCD panel power status
  704. * (0: full off - CONFIG_LCD_MAXPOWER: full on).
  705. * On backlit LCDs, this setting may correspond to the backlight setting.
  706. *
  707. ****************************************************************************/
  708. static int ssd1289_getpower(FAR struct lcd_dev_s *dev)
  709. {
  710. lcdinfo("power: %d\n", 0);
  711. return g_lcddev.power;
  712. }
  713. /****************************************************************************
  714. * Name: ssd1289_poweroff
  715. *
  716. * Description:
  717. * Enable/disable LCD panel power
  718. * (0: full off - CONFIG_LCD_MAXPOWER: full on).
  719. * On backlit LCDs, this setting may correspond to the backlight setting.
  720. *
  721. ****************************************************************************/
  722. static int ssd1289_poweroff(FAR struct ssd1289_lcd_s *lcd)
  723. {
  724. /* Set the backlight off */
  725. lcd->backlight(lcd, 0);
  726. /* Turn the display off */
  727. ssd1289_putreg(lcd, SSD1289_DSPCTRL, 0);
  728. /* Remember the power off state */
  729. g_lcddev.power = 0;
  730. return OK;
  731. }
  732. /****************************************************************************
  733. * Name: ssd1289_setpower
  734. *
  735. * Description:
  736. * Enable/disable LCD panel power
  737. * (0: full off - CONFIG_LCD_MAXPOWER: full on).
  738. * On backlit LCDs, this setting may correspond to the backlight setting.
  739. *
  740. ****************************************************************************/
  741. static int ssd1289_setpower(FAR struct lcd_dev_s *dev, int power)
  742. {
  743. FAR struct ssd1289_dev_s *priv = (FAR struct ssd1289_dev_s *)dev;
  744. FAR struct ssd1289_lcd_s *lcd = priv->lcd;
  745. lcdinfo("power: %d\n", power);
  746. DEBUGASSERT((unsigned)power <= CONFIG_LCD_MAXPOWER);
  747. /* Set new power level */
  748. if (power > 0)
  749. {
  750. /* Set the backlight level */
  751. lcd->backlight(lcd, power);
  752. /* Then turn the display on:
  753. * D=ON(3) CM=0 DTE=1 GON=1 SPT=0 VLE=0 PT=0
  754. */
  755. ssd1289_putreg(lcd, SSD1289_DSPCTRL,
  756. (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_GON |
  757. SSD1289_DSPCTRL_DTE | SSD1289_DSPCTRL_VLE(0)));
  758. g_lcddev.power = power;
  759. }
  760. else
  761. {
  762. /* Turn the display off */
  763. ssd1289_poweroff(lcd);
  764. }
  765. return OK;
  766. }
  767. /****************************************************************************
  768. * Name: ssd1289_getcontrast
  769. *
  770. * Description:
  771. * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
  772. *
  773. ****************************************************************************/
  774. static int ssd1289_getcontrast(FAR struct lcd_dev_s *dev)
  775. {
  776. lcdinfo("Not implemented\n");
  777. return -ENOSYS;
  778. }
  779. /****************************************************************************
  780. * Name: ssd1289_setcontrast
  781. *
  782. * Description:
  783. * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
  784. *
  785. ****************************************************************************/
  786. static int ssd1289_setcontrast(FAR struct lcd_dev_s *dev,
  787. unsigned int contrast)
  788. {
  789. lcdinfo("contrast: %d\n", contrast);
  790. return -ENOSYS;
  791. }
  792. /****************************************************************************
  793. * Name: ssd1289_hwinitialize
  794. *
  795. * Description:
  796. * Initialize the LCD hardware.
  797. *
  798. ****************************************************************************/
  799. static inline int ssd1289_hwinitialize(FAR struct ssd1289_dev_s *priv)
  800. {
  801. FAR struct ssd1289_lcd_s *lcd = priv->lcd;
  802. #ifndef CONFIG_LCD_NOGETRUN
  803. uint16_t id;
  804. #endif
  805. int ret;
  806. /* Select the LCD */
  807. lcd->select(lcd);
  808. /* Read the device ID. Skip verification of the device ID is the LCD is
  809. * write-only. What choice do we have?
  810. */
  811. #ifndef CONFIG_LCD_NOGETRUN
  812. id = ssd1289_readreg(lcd, SSD1289_DEVCODE);
  813. if (id != 0)
  814. {
  815. lcdinfo("LCD ID: %04x\n", id);
  816. }
  817. /* If we could not get the ID, then let's just assume that this is an
  818. * SSD1289. Perhaps we have some early register access issues.
  819. * This seems to happen.
  820. * But then perhaps we should not even bother to read the device ID at all?
  821. */
  822. else
  823. {
  824. lcdwarn("WARNING: No LCD ID, assuming SSD1289\n");
  825. id = SSD1289_DEVCODE_VALUE;
  826. }
  827. /* Check if the ID is for the SSD1289 */
  828. if (id == SSD1289_DEVCODE_VALUE)
  829. #endif
  830. {
  831. /* LCD controller configuration.
  832. * Many details of the controller initialization must, unfortunately,
  833. * vary from LCD to LCD. I have looked at the spec and at three
  834. * different drivers for LCDs that have SSD1289 controllers. I have
  835. * tried to summarize these differences as profiles (defined above).
  836. * Some other alternatives are noted below.
  837. *
  838. * Most of the differences between LCDs are nothing more than a few
  839. * minor bit settings. The most significant difference between LCD
  840. * drivers in is the manner in which the LCD is powered up and in how
  841. * the power controls are set.
  842. * My suggestion is that if you have working LCD initialization code,
  843. * you should simply replace the following guesses with your working
  844. * code.
  845. */
  846. /* Most drivers just enable the oscillator */
  847. #ifdef SSD1289_USE_SIMPLE_INIT
  848. ssd1289_putreg(lcd, SSD1289_OSCSTART, SSD1289_OSCSTART_OSCEN);
  849. #else
  850. /* But one goes through a more complex start-up sequence.
  851. * Something like the following:
  852. *
  853. * First, put the display in INTERNAL operation:
  854. * D=INTERNAL(1) CM=0 DTE=0 GON=1 SPT=0 VLE=0 PT=0
  855. */
  856. ssd1289_putreg(lcd, SSD1289_DSPCTRL,
  857. (SSD1289_DSPCTRL_INTERNAL | SSD1289_DSPCTRL_GON |
  858. SSD1289_DSPCTRL_VLE(0)));
  859. /* Then enable the oscillator */
  860. ssd1289_putreg(lcd, SSD1289_OSCSTART, SSD1289_OSCSTART_OSCEN);
  861. /* Turn the display on:
  862. * D=ON(3) CM=0 DTE=0 GON=1 SPT=0 VLE=0 PT=0
  863. */
  864. ssd1289_putreg(lcd, SSD1289_DSPCTRL,
  865. (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_GON |
  866. SSD1289_DSPCTRL_VLE(0)));
  867. /* Take the LCD out of sleep mode */
  868. ssd1289_putreg(lcd, SSD1289_SLEEP, 0);
  869. up_mdelay(30);
  870. /* Turn the display on:
  871. * D=INTERNAL(1) CM=0 DTE=1 GON=1 SPT=0 VLE=0 PT=0
  872. */
  873. ssd1289_putreg(lcd, SSD1289_DSPCTRL,
  874. (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_DTE |
  875. SSD1289_DSPCTRL_GON | SSD1289_DSPCTRL_VLE(0)));
  876. #endif
  877. /* Set up power control registers. There is a lot of variability
  878. * from LCD-to-LCD in how the power registers are configured.
  879. */
  880. ssd1289_putreg(lcd, SSD1289_PWRCTRL1, PWRCTRL1_SETTING);
  881. ssd1289_putreg(lcd, SSD1289_PWRCTRL2, PWRCTRL2_SETTING);
  882. /* One driver adds a delay here.. I doubt that this is really
  883. * necessary.
  884. */
  885. /* up_mdelay(15); */
  886. ssd1289_putreg(lcd, SSD1289_PWRCTRL3, PWRCTRL3_SETTING);
  887. ssd1289_putreg(lcd, SSD1289_PWRCTRL4, PWRCTRL4_SETTING);
  888. ssd1289_putreg(lcd, SSD1289_PWRCTRL5, PWRCTRL5_SETTING);
  889. /* One driver does an odd setting of the driver output control.
  890. * No idea why.
  891. */
  892. #if 0
  893. ssd1289_putreg(lcd, SSD1289_OUTCTRL,
  894. (SSD1289_OUTCTRL_MUX(12) | SSD1289_OUTCTRL_TB |
  895. SSD1289_OUTCTRL_BGR | SSD1289_OUTCTRL_CAD));
  896. /* The same driver does another small delay here */
  897. up_mdelay(15);
  898. #endif
  899. /* After this point, the drivers differ only in some varying register
  900. * bit settings.
  901. */
  902. /* Set the driver output control.
  903. * PORTRAIT MODES:
  904. * MUX=319, TB=1, SM=0, BGR=1, CAD=0, REV=1, RL=0
  905. * LANDSCAPE MODES:
  906. * MUX=319, TB=0, SM=0, BGR=1, CAD=0, REV=1, RL=0
  907. */
  908. #if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT)
  909. ssd1289_putreg(lcd, SSD1289_OUTCTRL,
  910. (SSD1289_OUTCTRL_MUX(319) | SSD1289_OUTCTRL_TB |
  911. SSD1289_OUTCTRL_BGR | SSD1289_OUTCTRL_REV));
  912. #else
  913. ssd1289_putreg(lcd, SSD1289_OUTCTRL,
  914. (SSD1289_OUTCTRL_MUX(319) | SSD1289_OUTCTRL_BGR |
  915. SSD1289_OUTCTRL_REV));
  916. #endif
  917. /* Set the LCD driving AC waveform
  918. * NW=0, WSMD=0, EOR=1, BC=1, ENWD=0, FLD=0
  919. */
  920. ssd1289_putreg(lcd, SSD1289_ACCTRL,
  921. (SSD1289_ACCTRL_EOR | SSD1289_ACCTRL_BC));
  922. /* Take the LCD out of sleep mode (isn't this redundant in the
  923. * non-simple case?)
  924. */
  925. ssd1289_putreg(lcd, SSD1289_SLEEP, 0);
  926. /* Set entry mode */
  927. #if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT)
  928. /* LG=0, AM=0, ID=3, TY=2, DMODE=0, WMODE=0, OEDEF=0, TRANS=0, DRM=3
  929. * Alternative TY=2 (But TY only applies in 262K color mode anyway)
  930. */
  931. ssd1289_putreg(lcd, SSD1289_ENTRY,
  932. (SSD1289_ENTRY_ID_HINCVINC | SSD1289_ENTRY_TY_C |
  933. SSD1289_ENTRY_DMODE_RAM | SSD1289_ENTRY_DFM_65K));
  934. #else
  935. /* LG=0, AM=1, ID=3, TY=2, DMODE=0, WMODE=0, OEDEF=0, TRANS=0, DRM=3 */
  936. /* Alternative TY=2 (But TY only applies in 262K color mode anyway) */
  937. ssd1289_putreg(lcd, SSD1289_ENTRY,
  938. (SSD1289_ENTRY_AM | SSD1289_ENTRY_ID_HINCVINC |
  939. SSD1289_ENTRY_TY_C | SSD1289_ENTRY_DMODE_RAM |
  940. SSD1289_ENTRY_DFM_65K));
  941. #endif
  942. /* Clear compare registers */
  943. ssd1289_putreg(lcd, SSD1289_CMP1, 0);
  944. ssd1289_putreg(lcd, SSD1289_CMP2, 0);
  945. /* One driver puts a huge, 100 millisecond delay here */
  946. /* up_mdelay(100); */
  947. /* Set Horizontal and vertical porch.
  948. * Horizontal porch: 239 pixels per line, delay=28
  949. * Vertical porch: VBP=3, XFP=0
  950. */
  951. ssd1289_putreg(lcd, SSD1289_HPORCH,
  952. (28 << SSD1289_HPORCH_HBP_SHIFT) |
  953. (239 << SSD1289_HPORCH_XL_SHIFT));
  954. ssd1289_putreg(lcd, SSD1289_VPORCH,
  955. (3 << SSD1289_VPORCH_VBP_SHIFT) |
  956. (0 << SSD1289_VPORCH_XFP_SHIFT));
  957. /* Set display control.
  958. * D=ON(3), CM=0 (not 8-color), DTE=1, GON=1, SPT=0, VLE=1 PT=0
  959. */
  960. ssd1289_putreg(lcd, SSD1289_DSPCTRL,
  961. (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_DTE |
  962. SSD1289_DSPCTRL_GON | SSD1289_DSPCTRL_VLE(1)));
  963. /* Frame cycle control. Alternative: SSD1289_FCYCCTRL_DIV8 */
  964. ssd1289_putreg(lcd, SSD1289_FCYCCTRL, 0);
  965. /* Gate scan start position = 0 */
  966. ssd1289_putreg(lcd, SSD1289_GSTART, 0);
  967. /* Clear vertical scrolling */
  968. ssd1289_putreg(lcd, SSD1289_VSCROLL1, 0);
  969. ssd1289_putreg(lcd, SSD1289_VSCROLL2, 0);
  970. /* Setup window 1 (0-319) */
  971. ssd1289_putreg(lcd, SSD1289_W1START, 0);
  972. ssd1289_putreg(lcd, SSD1289_W1END, 319);
  973. /* Disable window 2 (0-0) */
  974. ssd1289_putreg(lcd, SSD1289_W2START, 0);
  975. ssd1289_putreg(lcd, SSD1289_W2END, 0);
  976. /* Horizontal start and end (0-239) */
  977. ssd1289_putreg(lcd, SSD1289_HADDR,
  978. (0 << SSD1289_HADDR_HSA_SHIFT) |
  979. (239 << SSD1289_HADDR_HEA_SHIFT));
  980. /* Vertical start and end (0-319) */
  981. ssd1289_putreg(lcd, SSD1289_VSTART, 0);
  982. ssd1289_putreg(lcd, SSD1289_VEND, 319);
  983. /* Gamma controls */
  984. ssd1289_putreg(lcd, SSD1289_GAMMA1, 0x0707);
  985. ssd1289_putreg(lcd, SSD1289_GAMMA2, 0x0204); /* Alternative: 0x0704 */
  986. ssd1289_putreg(lcd, SSD1289_GAMMA3, 0x0204);
  987. ssd1289_putreg(lcd, SSD1289_GAMMA4, 0x0502);
  988. ssd1289_putreg(lcd, SSD1289_GAMMA5, 0x0507);
  989. ssd1289_putreg(lcd, SSD1289_GAMMA6, 0x0204);
  990. ssd1289_putreg(lcd, SSD1289_GAMMA7, 0x0204);
  991. ssd1289_putreg(lcd, SSD1289_GAMMA8, 0x0502);
  992. ssd1289_putreg(lcd, SSD1289_GAMMA9, 0x0302);
  993. ssd1289_putreg(lcd, SSD1289_GAMMA10, 0x0302); /* Alternative: 0x1f00 */
  994. /* Clear write mask */
  995. ssd1289_putreg(lcd, SSD1289_WRMASK1, 0);
  996. ssd1289_putreg(lcd, SSD1289_WRMASK2, 0);
  997. /* Set frame frequency = 65Hz (This should not be necessary since this
  998. * is the default POR value)
  999. */
  1000. ssd1289_putreg(lcd, SSD1289_FFREQ, SSD1289_FFREQ_OSC_FF65);
  1001. /* Set the cursor at the home position and set the index register to
  1002. * the gram data register (I can't imagine these are necessary).
  1003. */
  1004. ssd1289_setcursor(lcd, 0, 0);
  1005. ssd1289_gramselect(lcd);
  1006. /* One driver has a 50 msec delay here */
  1007. /* up_mdelay(50); */
  1008. ret = OK;
  1009. }
  1010. #ifndef CONFIG_LCD_NOGETRUN
  1011. else
  1012. {
  1013. lcderr("ERROR: Unsupported LCD type\n");
  1014. ret = -ENODEV;
  1015. }
  1016. #endif
  1017. /* De-select the LCD */
  1018. lcd->deselect(lcd);
  1019. return ret;
  1020. }
  1021. /****************************************************************************
  1022. * Public Functions
  1023. ****************************************************************************/
  1024. /****************************************************************************
  1025. * Name: ssd1289_lcdinitialize
  1026. *
  1027. * Description:
  1028. * Initialize the LCD video hardware.
  1029. * The initial state of the LCD is fully initialized, display memory
  1030. * cleared, and the LCD ready to use, but with the power setting at 0
  1031. * (full off).
  1032. *
  1033. ****************************************************************************/
  1034. FAR struct lcd_dev_s *ssd1289_lcdinitialize(FAR struct ssd1289_lcd_s *lcd)
  1035. {
  1036. int ret;
  1037. lcdinfo("Initializing\n");
  1038. /* If we ccould support multiple SSD1289 devices, this is where we would
  1039. * allocate a new driver data structure... but we can't.
  1040. * Why not? Because of a bad should the form of the getrun() and
  1041. * putrun methods.
  1042. */
  1043. FAR struct ssd1289_dev_s *priv = &g_lcddev;
  1044. /* Initialize the driver data structure */
  1045. priv->dev.getvideoinfo = ssd1289_getvideoinfo;
  1046. priv->dev.getplaneinfo = ssd1289_getplaneinfo;
  1047. priv->dev.getpower = ssd1289_getpower;
  1048. priv->dev.setpower = ssd1289_setpower;
  1049. priv->dev.getcontrast = ssd1289_getcontrast;
  1050. priv->dev.setcontrast = ssd1289_setcontrast;
  1051. priv->lcd = lcd;
  1052. /* Configure and enable LCD */
  1053. ret = ssd1289_hwinitialize(priv);
  1054. if (ret == OK)
  1055. {
  1056. /* Clear the display (setting it to the color 0=black) */
  1057. ssd1289_clear(&priv->dev, 0);
  1058. /* Turn the display off */
  1059. ssd1289_poweroff(lcd);
  1060. return &g_lcddev.dev;
  1061. }
  1062. return NULL;
  1063. }
  1064. /****************************************************************************
  1065. * Name: ssd1289_clear
  1066. *
  1067. * Description:
  1068. * This is a non-standard LCD interface just for the stm3240g-EVAL board.
  1069. * Because of the various rotations, clearing the display in the normal way
  1070. * by writing a sequences of runs that covers the entire display can be
  1071. * very slow. Here the display is cleared by simply setting all GRAM
  1072. * memory to the specified color.
  1073. *
  1074. ****************************************************************************/
  1075. void ssd1289_clear(FAR struct lcd_dev_s *dev, uint16_t color)
  1076. {
  1077. FAR struct ssd1289_dev_s *priv = (FAR struct ssd1289_dev_s *)dev;
  1078. FAR struct ssd1289_lcd_s *lcd = priv->lcd;
  1079. uint32_t i;
  1080. /* Select the LCD and home the cursor position */
  1081. lcd->select(lcd);
  1082. ssd1289_setcursor(lcd, 0, 0);
  1083. /* Prepare to write GRAM data */
  1084. ssd1289_gramselect(lcd);
  1085. /* Copy color into all of GRAM.
  1086. * Orientation does not matter in this case.
  1087. */
  1088. for (i = 0; i < SSD1289_XRES * SSD1289_YRES; i++)
  1089. {
  1090. ssd1289_gramwrite(lcd, color);
  1091. }
  1092. /* De-select the LCD */
  1093. lcd->deselect(lcd);
  1094. }
  1095. #endif /* CONFIG_LCD_SSD1289 */