pxafb.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /*
  2. * PXA LCD Controller
  3. *
  4. * (C) Copyright 2001-2002
  5. * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. /************************************************************************/
  26. /* ** HEADER FILES */
  27. /************************************************************************/
  28. #include <config.h>
  29. #include <common.h>
  30. #include <version.h>
  31. #include <stdarg.h>
  32. #include <linux/types.h>
  33. #include <stdio_dev.h>
  34. #include <lcd.h>
  35. #include <asm/arch/pxa-regs.h>
  36. /* #define DEBUG */
  37. #ifdef CONFIG_LCD
  38. /*----------------------------------------------------------------------*/
  39. /*
  40. * Define panel bpp, LCCR0, LCCR3 and panel_info video struct for
  41. * your display.
  42. */
  43. #ifdef CONFIG_PXA_VGA
  44. /* LCD outputs connected to a video DAC */
  45. # define LCD_BPP LCD_COLOR8
  46. /* you have to set lccr0 and lccr3 (including pcd) */
  47. # define REG_LCCR0 0x003008f8
  48. # define REG_LCCR3 0x0300FF01
  49. /* 640x480x16 @ 61 Hz */
  50. vidinfo_t panel_info = {
  51. vl_col: 640,
  52. vl_row: 480,
  53. vl_width: 640,
  54. vl_height: 480,
  55. vl_clkp: CONFIG_SYS_HIGH,
  56. vl_oep: CONFIG_SYS_HIGH,
  57. vl_hsp: CONFIG_SYS_HIGH,
  58. vl_vsp: CONFIG_SYS_HIGH,
  59. vl_dp: CONFIG_SYS_HIGH,
  60. vl_bpix: LCD_BPP,
  61. vl_lbw: 0,
  62. vl_splt: 0,
  63. vl_clor: 0,
  64. vl_tft: 1,
  65. vl_hpw: 40,
  66. vl_blw: 56,
  67. vl_elw: 56,
  68. vl_vpw: 20,
  69. vl_bfw: 8,
  70. vl_efw: 8,
  71. };
  72. #endif /* CONFIG_PXA_VIDEO */
  73. /*----------------------------------------------------------------------*/
  74. #ifdef CONFIG_SHARP_LM8V31
  75. # define LCD_BPP LCD_COLOR8
  76. # define LCD_INVERT_COLORS /* Needed for colors to be correct, but why? */
  77. /* you have to set lccr0 and lccr3 (including pcd) */
  78. # define REG_LCCR0 0x0030087C
  79. # define REG_LCCR3 0x0340FF08
  80. vidinfo_t panel_info = {
  81. vl_col: 640,
  82. vl_row: 480,
  83. vl_width: 157,
  84. vl_height: 118,
  85. vl_clkp: CONFIG_SYS_HIGH,
  86. vl_oep: CONFIG_SYS_HIGH,
  87. vl_hsp: CONFIG_SYS_HIGH,
  88. vl_vsp: CONFIG_SYS_HIGH,
  89. vl_dp: CONFIG_SYS_HIGH,
  90. vl_bpix: LCD_BPP,
  91. vl_lbw: 0,
  92. vl_splt: 1,
  93. vl_clor: 1,
  94. vl_tft: 0,
  95. vl_hpw: 1,
  96. vl_blw: 3,
  97. vl_elw: 3,
  98. vl_vpw: 1,
  99. vl_bfw: 0,
  100. vl_efw: 0,
  101. };
  102. #endif /* CONFIG_SHARP_LM8V31 */
  103. /*----------------------------------------------------------------------*/
  104. #ifdef CONFIG_VOIPAC_LCD
  105. # define LCD_BPP LCD_COLOR8
  106. # define LCD_INVERT_COLORS
  107. /* you have to set lccr0 and lccr3 (including pcd) */
  108. # define REG_LCCR0 0x043008f8
  109. # define REG_LCCR3 0x0340FF08
  110. vidinfo_t panel_info = {
  111. vl_col: 640,
  112. vl_row: 480,
  113. vl_width: 157,
  114. vl_height: 118,
  115. vl_clkp: CONFIG_SYS_HIGH,
  116. vl_oep: CONFIG_SYS_HIGH,
  117. vl_hsp: CONFIG_SYS_HIGH,
  118. vl_vsp: CONFIG_SYS_HIGH,
  119. vl_dp: CONFIG_SYS_HIGH,
  120. vl_bpix: LCD_BPP,
  121. vl_lbw: 0,
  122. vl_splt: 1,
  123. vl_clor: 1,
  124. vl_tft: 1,
  125. vl_hpw: 32,
  126. vl_blw: 144,
  127. vl_elw: 32,
  128. vl_vpw: 2,
  129. vl_bfw: 13,
  130. vl_efw: 30,
  131. };
  132. #endif /* CONFIG_VOIPAC_LCD */
  133. /*----------------------------------------------------------------------*/
  134. #ifdef CONFIG_HITACHI_SX14
  135. /* Hitachi SX14Q004-ZZA color STN LCD */
  136. #define LCD_BPP LCD_COLOR8
  137. /* you have to set lccr0 and lccr3 (including pcd) */
  138. #define REG_LCCR0 0x00301079
  139. #define REG_LCCR3 0x0340FF20
  140. vidinfo_t panel_info = {
  141. vl_col: 320,
  142. vl_row: 240,
  143. vl_width: 167,
  144. vl_height: 109,
  145. vl_clkp: CONFIG_SYS_HIGH,
  146. vl_oep: CONFIG_SYS_HIGH,
  147. vl_hsp: CONFIG_SYS_HIGH,
  148. vl_vsp: CONFIG_SYS_HIGH,
  149. vl_dp: CONFIG_SYS_HIGH,
  150. vl_bpix: LCD_BPP,
  151. vl_lbw: 1,
  152. vl_splt: 0,
  153. vl_clor: 1,
  154. vl_tft: 0,
  155. vl_hpw: 1,
  156. vl_blw: 1,
  157. vl_elw: 1,
  158. vl_vpw: 7,
  159. vl_bfw: 0,
  160. vl_efw: 0,
  161. };
  162. #endif /* CONFIG_HITACHI_SX14 */
  163. /*----------------------------------------------------------------------*/
  164. #ifdef CONFIG_LMS283GF05
  165. # define LCD_BPP LCD_COLOR8
  166. /*# define LCD_INVERT_COLORS*/
  167. /* you have to set lccr0 and lccr3 (including pcd) */
  168. # define REG_LCCR0 0x043008f8
  169. # define REG_LCCR3 0x03b00009
  170. vidinfo_t panel_info = {
  171. vl_col: 240,
  172. vl_row: 320,
  173. vl_width: 240,
  174. vl_height: 320,
  175. vl_clkp: CONFIG_SYS_HIGH,
  176. vl_oep: CONFIG_SYS_LOW,
  177. vl_hsp: CONFIG_SYS_LOW,
  178. vl_vsp: CONFIG_SYS_LOW,
  179. vl_dp: CONFIG_SYS_HIGH,
  180. vl_bpix: LCD_BPP,
  181. vl_lbw: 0,
  182. vl_splt: 1,
  183. vl_clor: 1,
  184. vl_tft: 1,
  185. vl_hpw: 4,
  186. vl_blw: 4,
  187. vl_elw: 8,
  188. vl_vpw: 4,
  189. vl_bfw: 4,
  190. vl_efw: 8,
  191. };
  192. #endif /* CONFIG_LMS283GF05 */
  193. /*----------------------------------------------------------------------*/
  194. #if LCD_BPP == LCD_COLOR8
  195. void lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue);
  196. #endif
  197. #if LCD_BPP == LCD_MONOCHROME
  198. void lcd_initcolregs (void);
  199. #endif
  200. #ifdef NOT_USED_SO_FAR
  201. void lcd_disable (void);
  202. void lcd_getcolreg (ushort regno, ushort *red, ushort *green, ushort *blue);
  203. #endif /* NOT_USED_SO_FAR */
  204. void lcd_ctrl_init (void *lcdbase);
  205. void lcd_enable (void);
  206. int lcd_line_length;
  207. int lcd_color_fg;
  208. int lcd_color_bg;
  209. void *lcd_base; /* Start of framebuffer memory */
  210. void *lcd_console_address; /* Start of console buffer */
  211. short console_col;
  212. short console_row;
  213. static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid);
  214. static void pxafb_setup_gpio (vidinfo_t *vid);
  215. static void pxafb_enable_controller (vidinfo_t *vid);
  216. static int pxafb_init (vidinfo_t *vid);
  217. /************************************************************************/
  218. /************************************************************************/
  219. /* --------------- PXA chipset specific functions ------------------- */
  220. /************************************************************************/
  221. void lcd_ctrl_init (void *lcdbase)
  222. {
  223. pxafb_init_mem(lcdbase, &panel_info);
  224. pxafb_init(&panel_info);
  225. pxafb_setup_gpio(&panel_info);
  226. pxafb_enable_controller(&panel_info);
  227. }
  228. /*----------------------------------------------------------------------*/
  229. #ifdef NOT_USED_SO_FAR
  230. void
  231. lcd_getcolreg (ushort regno, ushort *red, ushort *green, ushort *blue)
  232. {
  233. }
  234. #endif /* NOT_USED_SO_FAR */
  235. /*----------------------------------------------------------------------*/
  236. #if LCD_BPP == LCD_COLOR8
  237. void
  238. lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
  239. {
  240. struct pxafb_info *fbi = &panel_info.pxa;
  241. unsigned short *palette = (unsigned short *)fbi->palette;
  242. u_int val;
  243. if (regno < fbi->palette_size) {
  244. val = ((red << 8) & 0xf800);
  245. val |= ((green << 4) & 0x07e0);
  246. val |= (blue & 0x001f);
  247. #ifdef LCD_INVERT_COLORS
  248. palette[regno] = ~val;
  249. #else
  250. palette[regno] = val;
  251. #endif
  252. }
  253. debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %04X\n",
  254. regno, &palette[regno],
  255. red, green, blue,
  256. palette[regno]);
  257. }
  258. #endif /* LCD_COLOR8 */
  259. /*----------------------------------------------------------------------*/
  260. #if LCD_BPP == LCD_MONOCHROME
  261. void lcd_initcolregs (void)
  262. {
  263. struct pxafb_info *fbi = &panel_info.pxa;
  264. cmap = (ushort *)fbi->palette;
  265. ushort regno;
  266. for (regno = 0; regno < 16; regno++) {
  267. cmap[regno * 2] = 0;
  268. cmap[(regno * 2) + 1] = regno & 0x0f;
  269. }
  270. }
  271. #endif /* LCD_MONOCHROME */
  272. /*----------------------------------------------------------------------*/
  273. void lcd_enable (void)
  274. {
  275. }
  276. /*----------------------------------------------------------------------*/
  277. #ifdef NOT_USED_SO_FAR
  278. static void lcd_disable (void)
  279. {
  280. }
  281. #endif /* NOT_USED_SO_FAR */
  282. /*----------------------------------------------------------------------*/
  283. /************************************************************************/
  284. /* ** PXA255 specific routines */
  285. /************************************************************************/
  286. /*
  287. * Calculate fb size for VIDEOLFB_ATAG. Size returned contains fb,
  288. * descriptors and palette areas.
  289. */
  290. ulong calc_fbsize (void)
  291. {
  292. ulong size;
  293. int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
  294. size = line_length * panel_info.vl_row;
  295. size += PAGE_SIZE;
  296. return size;
  297. }
  298. static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid)
  299. {
  300. u_long palette_mem_size;
  301. struct pxafb_info *fbi = &vid->pxa;
  302. int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8;
  303. fbi->screen = (u_long)lcdbase;
  304. fbi->palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16;
  305. palette_mem_size = fbi->palette_size * sizeof(u16);
  306. debug("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
  307. /* locate palette and descs at end of page following fb */
  308. fbi->palette = (u_long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size;
  309. return 0;
  310. }
  311. #ifdef CONFIG_CPU_MONAHANS
  312. static inline void pxafb_setup_gpio (vidinfo_t *vid) {}
  313. #else
  314. static void pxafb_setup_gpio (vidinfo_t *vid)
  315. {
  316. u_long lccr0;
  317. /*
  318. * setup is based on type of panel supported
  319. */
  320. lccr0 = vid->pxa.reg_lccr0;
  321. /* 4 bit interface */
  322. if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD))
  323. {
  324. debug("Setting GPIO for 4 bit data\n");
  325. /* bits 58-61 */
  326. GPDR1 |= (0xf << 26);
  327. GAFR1_U = (GAFR1_U & ~(0xff << 20)) | (0xaa << 20);
  328. /* bits 74-77 */
  329. GPDR2 |= (0xf << 10);
  330. GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
  331. }
  332. /* 8 bit interface */
  333. else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) ||
  334. (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS)))
  335. {
  336. debug("Setting GPIO for 8 bit data\n");
  337. /* bits 58-65 */
  338. GPDR1 |= (0x3f << 26);
  339. GPDR2 |= (0x3);
  340. GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
  341. GAFR2_L = (GAFR2_L & ~0xf) | (0xa);
  342. /* bits 74-77 */
  343. GPDR2 |= (0xf << 10);
  344. GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
  345. }
  346. /* 16 bit interface */
  347. else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS)))
  348. {
  349. debug("Setting GPIO for 16 bit data\n");
  350. /* bits 58-77 */
  351. GPDR1 |= (0x3f << 26);
  352. GPDR2 |= 0x00003fff;
  353. GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
  354. GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
  355. }
  356. else
  357. {
  358. printf("pxafb_setup_gpio: unable to determine bits per pixel\n");
  359. }
  360. }
  361. #endif
  362. static void pxafb_enable_controller (vidinfo_t *vid)
  363. {
  364. debug("Enabling LCD controller\n");
  365. /* Sequence from 11.7.10 */
  366. LCCR3 = vid->pxa.reg_lccr3;
  367. LCCR2 = vid->pxa.reg_lccr2;
  368. LCCR1 = vid->pxa.reg_lccr1;
  369. LCCR0 = vid->pxa.reg_lccr0 & ~LCCR0_ENB;
  370. FDADR0 = vid->pxa.fdadr0;
  371. FDADR1 = vid->pxa.fdadr1;
  372. LCCR0 |= LCCR0_ENB;
  373. #ifdef CONFIG_CPU_MONAHANS
  374. CKENA |= CKENA_1_LCD;
  375. #else
  376. CKEN |= CKEN16_LCD;
  377. #endif
  378. debug("FDADR0 = 0x%08x\n", (unsigned int)FDADR0);
  379. debug("FDADR1 = 0x%08x\n", (unsigned int)FDADR1);
  380. debug("LCCR0 = 0x%08x\n", (unsigned int)LCCR0);
  381. debug("LCCR1 = 0x%08x\n", (unsigned int)LCCR1);
  382. debug("LCCR2 = 0x%08x\n", (unsigned int)LCCR2);
  383. debug("LCCR3 = 0x%08x\n", (unsigned int)LCCR3);
  384. }
  385. static int pxafb_init (vidinfo_t *vid)
  386. {
  387. struct pxafb_info *fbi = &vid->pxa;
  388. debug("Configuring PXA LCD\n");
  389. fbi->reg_lccr0 = REG_LCCR0;
  390. fbi->reg_lccr3 = REG_LCCR3;
  391. debug("vid: vl_col=%d hslen=%d lm=%d rm=%d\n",
  392. vid->vl_col, vid->vl_hpw,
  393. vid->vl_blw, vid->vl_elw);
  394. debug("vid: vl_row=%d vslen=%d um=%d bm=%d\n",
  395. vid->vl_row, vid->vl_vpw,
  396. vid->vl_bfw, vid->vl_efw);
  397. fbi->reg_lccr1 =
  398. LCCR1_DisWdth(vid->vl_col) +
  399. LCCR1_HorSnchWdth(vid->vl_hpw) +
  400. LCCR1_BegLnDel(vid->vl_blw) +
  401. LCCR1_EndLnDel(vid->vl_elw);
  402. fbi->reg_lccr2 =
  403. LCCR2_DisHght(vid->vl_row) +
  404. LCCR2_VrtSnchWdth(vid->vl_vpw) +
  405. LCCR2_BegFrmDel(vid->vl_bfw) +
  406. LCCR2_EndFrmDel(vid->vl_efw);
  407. fbi->reg_lccr3 = REG_LCCR3 & ~(LCCR3_HSP | LCCR3_VSP);
  408. fbi->reg_lccr3 |= (vid->vl_hsp ? LCCR3_HorSnchL : LCCR3_HorSnchH)
  409. | (vid->vl_vsp ? LCCR3_VrtSnchL : LCCR3_VrtSnchH);
  410. /* setup dma descriptors */
  411. fbi->dmadesc_fblow = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 3*16);
  412. fbi->dmadesc_fbhigh = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 2*16);
  413. fbi->dmadesc_palette = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 1*16);
  414. #define BYTES_PER_PANEL ((fbi->reg_lccr0 & LCCR0_SDS) ? \
  415. (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8 / 2) : \
  416. (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8))
  417. /* populate descriptors */
  418. fbi->dmadesc_fblow->fdadr = (u_long)fbi->dmadesc_fblow;
  419. fbi->dmadesc_fblow->fsadr = fbi->screen + BYTES_PER_PANEL;
  420. fbi->dmadesc_fblow->fidr = 0;
  421. fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL;
  422. fbi->fdadr1 = (u_long)fbi->dmadesc_fblow; /* only used in dual-panel mode */
  423. fbi->dmadesc_fbhigh->fsadr = fbi->screen;
  424. fbi->dmadesc_fbhigh->fidr = 0;
  425. fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL;
  426. fbi->dmadesc_palette->fsadr = fbi->palette;
  427. fbi->dmadesc_palette->fidr = 0;
  428. fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
  429. if( NBITS(vid->vl_bpix) < 12)
  430. {
  431. /* assume any mode with <12 bpp is palette driven */
  432. fbi->dmadesc_palette->fdadr = (u_long)fbi->dmadesc_fbhigh;
  433. fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_palette;
  434. /* flips back and forth between pal and fbhigh */
  435. fbi->fdadr0 = (u_long)fbi->dmadesc_palette;
  436. }
  437. else
  438. {
  439. /* palette shouldn't be loaded in true-color mode */
  440. fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_fbhigh;
  441. fbi->fdadr0 = (u_long)fbi->dmadesc_fbhigh; /* no pal just fbhigh */
  442. }
  443. debug("fbi->dmadesc_fblow = 0x%lx\n", (u_long)fbi->dmadesc_fblow);
  444. debug("fbi->dmadesc_fbhigh = 0x%lx\n", (u_long)fbi->dmadesc_fbhigh);
  445. debug("fbi->dmadesc_palette = 0x%lx\n", (u_long)fbi->dmadesc_palette);
  446. debug("fbi->dmadesc_fblow->fdadr = 0x%lx\n", fbi->dmadesc_fblow->fdadr);
  447. debug("fbi->dmadesc_fbhigh->fdadr = 0x%lx\n", fbi->dmadesc_fbhigh->fdadr);
  448. debug("fbi->dmadesc_palette->fdadr = 0x%lx\n", fbi->dmadesc_palette->fdadr);
  449. debug("fbi->dmadesc_fblow->fsadr = 0x%lx\n", fbi->dmadesc_fblow->fsadr);
  450. debug("fbi->dmadesc_fbhigh->fsadr = 0x%lx\n", fbi->dmadesc_fbhigh->fsadr);
  451. debug("fbi->dmadesc_palette->fsadr = 0x%lx\n", fbi->dmadesc_palette->fsadr);
  452. debug("fbi->dmadesc_fblow->ldcmd = 0x%lx\n", fbi->dmadesc_fblow->ldcmd);
  453. debug("fbi->dmadesc_fbhigh->ldcmd = 0x%lx\n", fbi->dmadesc_fbhigh->ldcmd);
  454. debug("fbi->dmadesc_palette->ldcmd = 0x%lx\n", fbi->dmadesc_palette->ldcmd);
  455. return 0;
  456. }
  457. /************************************************************************/
  458. /************************************************************************/
  459. #endif /* CONFIG_LCD */