vfd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. * (C) Copyright 2001
  3. * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. /************************************************************************/
  24. /* ** DEBUG SETTINGS */
  25. /************************************************************************/
  26. /* #define DEBUG */
  27. /************************************************************************/
  28. /* ** HEADER FILES */
  29. /************************************************************************/
  30. #include <config.h>
  31. #include <common.h>
  32. #include <version.h>
  33. #include <stdarg.h>
  34. #include <linux/types.h>
  35. #include <devices.h>
  36. #include <s3c2400.h>
  37. #ifdef CONFIG_VFD
  38. /************************************************************************/
  39. /* ** CONFIG STUFF -- should be moved to board config file */
  40. /************************************************************************/
  41. /************************************************************************/
  42. #ifndef PAGE_SIZE
  43. #define PAGE_SIZE 4096
  44. #endif
  45. #define ROT 0x09
  46. #define BLAU 0x0C
  47. #define VIOLETT 0X0D
  48. ulong vfdbase;
  49. ulong frame_buf_size;
  50. #define frame_buf_offs 4
  51. /* taken from armboot/common/vfd.c */
  52. ulong adr_vfd_table[112][18][2][4][2];
  53. unsigned char bit_vfd_table[112][18][2][4][2];
  54. /*
  55. * initialize the values for the VFD-grid-control in the framebuffer
  56. */
  57. void init_grid_ctrl(void)
  58. {
  59. ulong adr, grid_cycle;
  60. unsigned int bit, display;
  61. unsigned char temp, bit_nr;
  62. for (adr=vfdbase; adr<=(vfdbase+7168); adr+=4) /*clear frame buffer */
  63. (*(volatile ulong*)(adr))=0;
  64. for(display=0;display<=3;display++)
  65. {
  66. for(grid_cycle=0;grid_cycle<=55;grid_cycle++)
  67. {
  68. bit = grid_cycle*256*4+(grid_cycle+200)*4+frame_buf_offs+display;
  69. /* wrap arround if offset (see manual S3C2400) */
  70. if (bit>=frame_buf_size*8)
  71. bit = bit-(frame_buf_size*8);
  72. adr = vfdbase+(bit/32)*4+(3-(bit%32)/8);
  73. bit_nr = bit%8;
  74. bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
  75. temp=(*(volatile unsigned char*)(adr));
  76. temp|=(1<<bit_nr);
  77. (*(volatile unsigned char*)(adr))=temp;
  78. if(grid_cycle<55)
  79. bit = grid_cycle*256*4+(grid_cycle+201)*4+frame_buf_offs+display;
  80. else
  81. bit = grid_cycle*256*4+200*4+frame_buf_offs+display-4; /* grid nr. 0 */
  82. /* wrap arround if offset (see manual S3C2400) */
  83. if (bit>=frame_buf_size*8)
  84. bit = bit-(frame_buf_size*8);
  85. adr = vfdbase+(bit/32)*4+(3-(bit%32)/8);
  86. bit_nr = bit%8;
  87. bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
  88. temp=(*(volatile unsigned char*)(adr));
  89. temp|=(1<<bit_nr);
  90. (*(volatile unsigned char*)(adr))=temp;
  91. }
  92. }
  93. }
  94. /*
  95. *create translation table for getting easy the right position in the
  96. *physical framebuffer for some x/y-coordinates of the VFDs
  97. */
  98. void create_vfd_table(void)
  99. {
  100. unsigned int vfd_table[112][18][2][4][2];
  101. ulong adr;
  102. unsigned int x, y, color, display, entry, pixel, bit_nr;
  103. /*
  104. * Create translation table for Noritake-T119C-VFD-specific
  105. * organized frame-buffer.
  106. * Created is the number of the bit in the framebuffer (the
  107. * first transferred pixel of each frame is bit 0).
  108. */
  109. for(y=0;y<=17;y++) /* Zeile */
  110. {
  111. for(x=0;x<=111;x++) /* Spalten */
  112. {
  113. /*Display 0 blaue Pixel Eintrag 1 */
  114. vfd_table[x][y][0][0][0]=((x%4)*4+y*16+(x/4)*2048);
  115. /*Display 0 rote Pixel Eintrag 1 */
  116. vfd_table[x][y][1][0][0]=((x%4)*4+y*16+(x/4)*2048+512);
  117. if(x<=1)
  118. {
  119. /*Display 0 blaue Pixel Eintrag 2 */
  120. vfd_table[x][y][0][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1024);
  121. /*Display 0 rote Pixel Eintrag 2 */
  122. vfd_table[x][y][1][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1024);
  123. }
  124. else
  125. {
  126. /*Display 0 blaue Pixel Eintrag 2 */
  127. vfd_table[x][y][0][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+1024);
  128. /*Display 0 rote Pixel Eintrag 2 */
  129. vfd_table[x][y][1][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1024);
  130. }
  131. /*Display 1 blaue Pixel Eintrag 1 */
  132. vfd_table[x][y][0][1][0]=((x%4)*4+y*16+(x/4)*2048+1);
  133. /*Display 1 rote Pixel Eintrag 1 */
  134. vfd_table[x][y][1][1][0]=((x%4)*4+y*16+(x/4)*2048+512+1);
  135. if(x<=1)
  136. {
  137. /*Display 1 blaue Pixel Eintrag 2 */
  138. vfd_table[x][y][0][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1+1024);
  139. /*Display 1 rote Pixel Eintrag 2 */
  140. vfd_table[x][y][1][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1+1024);
  141. }
  142. else
  143. {
  144. /*Display 1 blaue Pixel Eintrag 2 */
  145. vfd_table[x][y][0][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+1+1024);
  146. /*Display 1 rote Pixel Eintrag 2 */
  147. vfd_table[x][y][1][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1+1024);
  148. }
  149. /*Display 2 blaue Pixel Eintrag 1 */
  150. vfd_table[x][y][0][2][0]=((x%4)*4+y*16+(x/4)*2048+2);
  151. /*Display 2 rote Pixel Eintrag 1 */
  152. vfd_table[x][y][1][2][0]=((x%4)*4+y*16+(x/4)*2048+512+2);
  153. if(x<=1)
  154. {
  155. /*Display 2 blaue Pixel Eintrag 2 */
  156. vfd_table[x][y][0][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+2+1024);
  157. /*Display 2 rote Pixel Eintrag 2 */
  158. vfd_table[x][y][1][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+2+1024);
  159. }
  160. else
  161. {
  162. /*Display 2 blaue Pixel Eintrag 2 */
  163. vfd_table[x][y][0][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+2+1024);
  164. /*Display 2 rote Pixel Eintrag 2 */
  165. vfd_table[x][y][1][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+2+1024);
  166. }
  167. /*Display 3 blaue Pixel Eintrag 1 */
  168. vfd_table[x][y][0][3][0]=((x%4)*4+y*16+(x/4)*2048+3);
  169. /*Display 3 rote Pixel Eintrag 1 */
  170. vfd_table[x][y][1][3][0]=((x%4)*4+y*16+(x/4)*2048+512+3);
  171. if(x<=1)
  172. {
  173. /*Display 3 blaue Pixel Eintrag 2 */
  174. vfd_table[x][y][0][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+3+1024);
  175. /*Display 3 rote Pixel Eintrag 2 */
  176. vfd_table[x][y][1][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+3+1024);
  177. }
  178. else
  179. {
  180. /*Display 3 blaue Pixel Eintrag 2 */
  181. vfd_table[x][y][0][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+3+1024);
  182. /*Display 3 rote Pixel Eintrag 2 */
  183. vfd_table[x][y][1][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+3+1024);
  184. }
  185. }
  186. }
  187. /*
  188. * Create translation table for Noritake-T119C-VFD-specific
  189. * organized frame-buffer
  190. * Create table with entries for physical byte adresses and
  191. * bit-number within the byte
  192. * from table with bit-numbers within the total framebuffer
  193. */
  194. for(y=0;y<=17;y++)
  195. {
  196. for(x=0;x<=111;x++)
  197. {
  198. for(color=0;color<=1;color++)
  199. {
  200. for(display=0;display<=3;display++)
  201. {
  202. for(entry=0;entry<=1;entry++)
  203. {
  204. pixel = vfd_table[x][y][color][display][entry] + frame_buf_offs;
  205. /*
  206. * wrap arround if offset
  207. * (see manual S3C2400)
  208. */
  209. if (pixel>=frame_buf_size*8)
  210. pixel = pixel-(frame_buf_size*8);
  211. adr = vfdbase+(pixel/32)*4+(3-(pixel%32)/8);
  212. bit_nr = pixel%8;
  213. bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
  214. adr_vfd_table[x][y][color][display][entry] = adr;
  215. bit_vfd_table[x][y][color][display][entry] = bit_nr;
  216. }
  217. }
  218. }
  219. }
  220. }
  221. }
  222. /*
  223. * Set/clear pixel of the VFDs
  224. */
  225. void set_vfd_pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char display, unsigned char value)
  226. {
  227. ulong adr;
  228. unsigned char bit_nr, temp;
  229. if (value!=0)
  230. {
  231. /* Pixel-Eintrag Nr. 1 */
  232. adr = adr_vfd_table[x][y][color][display][0];
  233. /* Pixel-Eintrag Nr. 1 */
  234. bit_nr = bit_vfd_table[x][y][color][display][0];
  235. temp=(*(volatile unsigned char*)(adr));
  236. temp|=1<<bit_nr;
  237. (*(volatile unsigned char*)(adr))=temp;
  238. /* Pixel-Eintrag Nr. 2 */
  239. adr = adr_vfd_table[x][y][color][display][1];
  240. /* Pixel-Eintrag Nr. 2 */
  241. bit_nr = bit_vfd_table[x][y][color][display][1];
  242. temp=(*(volatile unsigned char*)(adr));
  243. temp|=1<<bit_nr;
  244. (*(volatile unsigned char*)(adr))=temp;
  245. }
  246. else
  247. {
  248. /* Pixel-Eintrag Nr. 1 */
  249. adr = adr_vfd_table[x][y][color][display][0];
  250. /* Pixel-Eintrag Nr. 1 */
  251. bit_nr = bit_vfd_table[x][y][color][display][0];
  252. temp=(*(volatile unsigned char*)(adr));
  253. temp&=~(1<<bit_nr);
  254. (*(volatile unsigned char*)(adr))=temp;
  255. /* Pixel-Eintrag Nr. 2 */
  256. adr = adr_vfd_table[x][y][color][display][1];
  257. /* Pixel-Eintrag Nr. 2 */
  258. bit_nr = bit_vfd_table[x][y][color][display][1];
  259. temp=(*(volatile unsigned char*)(adr));
  260. temp&=~(1<<bit_nr);
  261. (*(volatile unsigned char*)(adr))=temp;
  262. }
  263. }
  264. /*
  265. * transfer image from BMP-File
  266. */
  267. void transfer_pic(int display, unsigned char *adr, int height, int width)
  268. {
  269. int x, y;
  270. unsigned char temp;
  271. for (; height > 0; height -= 18)
  272. {
  273. if (height > 18)
  274. y = 18;
  275. else
  276. y = height;
  277. for (; y > 0; y--)
  278. {
  279. for (x = 0; x < width; x += 2)
  280. {
  281. temp = *adr++;
  282. set_vfd_pixel(x, y-1, 0, display, 0);
  283. set_vfd_pixel(x, y-1, 1, display, 0);
  284. if ((temp >> 4) == BLAU)
  285. set_vfd_pixel(x, y-1, 0, display, 1);
  286. else if ((temp >> 4) == ROT)
  287. set_vfd_pixel(x, y-1, 1, display, 1);
  288. else if ((temp >> 4) == VIOLETT)
  289. {
  290. set_vfd_pixel(x, y-1, 0, display, 1);
  291. set_vfd_pixel(x, y-1, 1, display, 1);
  292. }
  293. set_vfd_pixel(x+1, y-1, 0, display, 0);
  294. set_vfd_pixel(x+1, y-1, 1, display, 0);
  295. if ((temp & 0x0F) == BLAU)
  296. set_vfd_pixel(x+1, y-1, 0, display, 1);
  297. else if ((temp & 0x0F) == ROT)
  298. set_vfd_pixel(x+1, y-1, 1, display, 1);
  299. else if ((temp & 0x0F) == VIOLETT)
  300. {
  301. set_vfd_pixel(x+1, y-1, 0, display, 1);
  302. set_vfd_pixel(x+1, y-1, 1, display, 1);
  303. }
  304. }
  305. }
  306. display++;
  307. if (display > 3)
  308. display = 0;
  309. }
  310. }
  311. /*
  312. * initialize LCD-Controller of the S3C2400 for using VFDs
  313. */
  314. int drv_vfd_init(void)
  315. {
  316. ulong palette;
  317. DECLARE_GLOBAL_DATA_PTR;
  318. vfdbase = gd->fb_base;
  319. create_vfd_table();
  320. init_grid_ctrl();
  321. /*
  322. * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben
  323. * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt
  324. * das letzte angezeigte Pixel wird aus dem ersten Nibble geholt
  325. * (wrap around)
  326. * see manual S3C2400
  327. */
  328. /* frame buffer startadr */
  329. rLCDSADDR1 = vfdbase >> 1;
  330. /* frame buffer endadr */
  331. rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1;
  332. rLCDSADDR3 = ((256/4));
  333. /* Port-Pins als LCD-Ausgang */
  334. rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA;
  335. /* Port-Pins als LCD-Ausgang */
  336. rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8;
  337. #ifdef WITH_VFRAME
  338. /* mit VFRAME zum Messen */
  339. rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA;
  340. #endif
  341. rLCDCON2 = 0x000DC000;
  342. rLCDCON3 = 0x0051000A;
  343. rLCDCON4 = 0x00000001;
  344. rLCDCON5 = 0x00000440;
  345. rLCDCON1 = 0x00000B75;
  346. debug ("LCDSADDR1: %lX\n", rLCDSADDR1);
  347. debug ("LCDSADDR2: %lX\n", rLCDSADDR2);
  348. debug ("LCDSADDR3: %lX\n", rLCDSADDR3);
  349. for(palette=0;palette<=15;palette++)
  350. (*(volatile unsigned int*)(PALETTE+(palette*4)))=palette;
  351. for(palette=16;palette<=255;palette++)
  352. (*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00;
  353. return 0;
  354. }
  355. /************************************************************************/
  356. /* ** ROM capable initialization part - needed to reserve FB memory */
  357. /************************************************************************/
  358. /*
  359. * This is called early in the system initialization to grab memory
  360. * for the VFD controller.
  361. *
  362. * Note that this is running from ROM, so no write access to global data.
  363. */
  364. ulong vfd_setmem (ulong addr)
  365. {
  366. ulong size;
  367. /* MAGIC */
  368. frame_buf_size = (256*4*56)/8;
  369. /* Round up to nearest full page */
  370. size = (frame_buf_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
  371. debug ("Reserving %ldk for VFD Framebuffer at: %08lx\n", size>>10, addr);
  372. return (size);
  373. }
  374. #endif /* CONFIG_VFD */