pxafb.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  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 <devices.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_HITACHI_SX14
  105. /* Hitachi SX14Q004-ZZA color STN LCD */
  106. #define LCD_BPP LCD_COLOR8
  107. /* you have to set lccr0 and lccr3 (including pcd) */
  108. #define REG_LCCR0 0x00301079
  109. #define REG_LCCR3 0x0340FF20
  110. vidinfo_t panel_info = {
  111. vl_col: 320,
  112. vl_row: 240,
  113. vl_width: 167,
  114. vl_height: 109,
  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: 1,
  122. vl_splt: 0,
  123. vl_clor: 1,
  124. vl_tft: 0,
  125. vl_hpw: 1,
  126. vl_blw: 1,
  127. vl_elw: 1,
  128. vl_vpw: 7,
  129. vl_bfw: 0,
  130. vl_efw: 0,
  131. };
  132. #endif /* CONFIG_HITACHI_SX14 */
  133. /*----------------------------------------------------------------------*/
  134. #if LCD_BPP == LCD_COLOR8
  135. void lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue);
  136. #endif
  137. #if LCD_BPP == LCD_MONOCHROME
  138. void lcd_initcolregs (void);
  139. #endif
  140. #ifdef NOT_USED_SO_FAR
  141. void lcd_disable (void);
  142. void lcd_getcolreg (ushort regno, ushort *red, ushort *green, ushort *blue);
  143. #endif /* NOT_USED_SO_FAR */
  144. void lcd_ctrl_init (void *lcdbase);
  145. void lcd_enable (void);
  146. int lcd_line_length;
  147. int lcd_color_fg;
  148. int lcd_color_bg;
  149. void *lcd_base; /* Start of framebuffer memory */
  150. void *lcd_console_address; /* Start of console buffer */
  151. short console_col;
  152. short console_row;
  153. static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid);
  154. static void pxafb_setup_gpio (vidinfo_t *vid);
  155. static void pxafb_enable_controller (vidinfo_t *vid);
  156. static int pxafb_init (vidinfo_t *vid);
  157. /************************************************************************/
  158. /************************************************************************/
  159. /* --------------- PXA chipset specific functions ------------------- */
  160. /************************************************************************/
  161. void lcd_ctrl_init (void *lcdbase)
  162. {
  163. pxafb_init_mem(lcdbase, &panel_info);
  164. pxafb_init(&panel_info);
  165. pxafb_setup_gpio(&panel_info);
  166. pxafb_enable_controller(&panel_info);
  167. }
  168. /*----------------------------------------------------------------------*/
  169. #ifdef NOT_USED_SO_FAR
  170. void
  171. lcd_getcolreg (ushort regno, ushort *red, ushort *green, ushort *blue)
  172. {
  173. }
  174. #endif /* NOT_USED_SO_FAR */
  175. /*----------------------------------------------------------------------*/
  176. #if LCD_BPP == LCD_COLOR8
  177. void
  178. lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
  179. {
  180. struct pxafb_info *fbi = &panel_info.pxa;
  181. unsigned short *palette = (unsigned short *)fbi->palette;
  182. u_int val;
  183. if (regno < fbi->palette_size) {
  184. val = ((red << 8) & 0xf800);
  185. val |= ((green << 4) & 0x07e0);
  186. val |= (blue & 0x001f);
  187. #ifdef LCD_INVERT_COLORS
  188. palette[regno] = ~val;
  189. #else
  190. palette[regno] = val;
  191. #endif
  192. }
  193. debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %04X\n",
  194. regno, &palette[regno],
  195. red, green, blue,
  196. palette[regno]);
  197. }
  198. #endif /* LCD_COLOR8 */
  199. /*----------------------------------------------------------------------*/
  200. #if LCD_BPP == LCD_MONOCHROME
  201. void lcd_initcolregs (void)
  202. {
  203. struct pxafb_info *fbi = &panel_info.pxa;
  204. cmap = (ushort *)fbi->palette;
  205. ushort regno;
  206. for (regno = 0; regno < 16; regno++) {
  207. cmap[regno * 2] = 0;
  208. cmap[(regno * 2) + 1] = regno & 0x0f;
  209. }
  210. }
  211. #endif /* LCD_MONOCHROME */
  212. /*----------------------------------------------------------------------*/
  213. void lcd_enable (void)
  214. {
  215. }
  216. /*----------------------------------------------------------------------*/
  217. #ifdef NOT_USED_SO_FAR
  218. static void lcd_disable (void)
  219. {
  220. }
  221. #endif /* NOT_USED_SO_FAR */
  222. /*----------------------------------------------------------------------*/
  223. /************************************************************************/
  224. /* ** PXA255 specific routines */
  225. /************************************************************************/
  226. /*
  227. * Calculate fb size for VIDEOLFB_ATAG. Size returned contains fb,
  228. * descriptors and palette areas.
  229. */
  230. ulong calc_fbsize (void)
  231. {
  232. ulong size;
  233. int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
  234. size = line_length * panel_info.vl_row;
  235. size += PAGE_SIZE;
  236. return size;
  237. }
  238. static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid)
  239. {
  240. u_long palette_mem_size;
  241. struct pxafb_info *fbi = &vid->pxa;
  242. int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8;
  243. fbi->screen = (u_long)lcdbase;
  244. fbi->palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16;
  245. palette_mem_size = fbi->palette_size * sizeof(u16);
  246. debug("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
  247. /* locate palette and descs at end of page following fb */
  248. fbi->palette = (u_long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size;
  249. return 0;
  250. }
  251. static void pxafb_setup_gpio (vidinfo_t *vid)
  252. {
  253. u_long lccr0;
  254. /*
  255. * setup is based on type of panel supported
  256. */
  257. lccr0 = vid->pxa.reg_lccr0;
  258. /* 4 bit interface */
  259. if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD))
  260. {
  261. debug("Setting GPIO for 4 bit data\n");
  262. /* bits 58-61 */
  263. GPDR1 |= (0xf << 26);
  264. GAFR1_U = (GAFR1_U & ~(0xff << 20)) | (0xaa << 20);
  265. /* bits 74-77 */
  266. GPDR2 |= (0xf << 10);
  267. GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
  268. }
  269. /* 8 bit interface */
  270. else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) ||
  271. (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS)))
  272. {
  273. debug("Setting GPIO for 8 bit data\n");
  274. /* bits 58-65 */
  275. GPDR1 |= (0x3f << 26);
  276. GPDR2 |= (0x3);
  277. GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
  278. GAFR2_L = (GAFR2_L & ~0xf) | (0xa);
  279. /* bits 74-77 */
  280. GPDR2 |= (0xf << 10);
  281. GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
  282. }
  283. /* 16 bit interface */
  284. else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS)))
  285. {
  286. debug("Setting GPIO for 16 bit data\n");
  287. /* bits 58-77 */
  288. GPDR1 |= (0x3f << 26);
  289. GPDR2 |= 0x00003fff;
  290. GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
  291. GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
  292. }
  293. else
  294. {
  295. printf("pxafb_setup_gpio: unable to determine bits per pixel\n");
  296. }
  297. }
  298. static void pxafb_enable_controller (vidinfo_t *vid)
  299. {
  300. debug("Enabling LCD controller\n");
  301. /* Sequence from 11.7.10 */
  302. LCCR3 = vid->pxa.reg_lccr3;
  303. LCCR2 = vid->pxa.reg_lccr2;
  304. LCCR1 = vid->pxa.reg_lccr1;
  305. LCCR0 = vid->pxa.reg_lccr0 & ~LCCR0_ENB;
  306. FDADR0 = vid->pxa.fdadr0;
  307. FDADR1 = vid->pxa.fdadr1;
  308. LCCR0 |= LCCR0_ENB;
  309. CKEN |= CKEN16_LCD;
  310. debug("FDADR0 = 0x%08x\n", (unsigned int)FDADR0);
  311. debug("FDADR1 = 0x%08x\n", (unsigned int)FDADR1);
  312. debug("LCCR0 = 0x%08x\n", (unsigned int)LCCR0);
  313. debug("LCCR1 = 0x%08x\n", (unsigned int)LCCR1);
  314. debug("LCCR2 = 0x%08x\n", (unsigned int)LCCR2);
  315. debug("LCCR3 = 0x%08x\n", (unsigned int)LCCR3);
  316. }
  317. static int pxafb_init (vidinfo_t *vid)
  318. {
  319. struct pxafb_info *fbi = &vid->pxa;
  320. debug("Configuring PXA LCD\n");
  321. fbi->reg_lccr0 = REG_LCCR0;
  322. fbi->reg_lccr3 = REG_LCCR3;
  323. debug("vid: vl_col=%d hslen=%d lm=%d rm=%d\n",
  324. vid->vl_col, vid->vl_hpw,
  325. vid->vl_blw, vid->vl_elw);
  326. debug("vid: vl_row=%d vslen=%d um=%d bm=%d\n",
  327. vid->vl_row, vid->vl_vpw,
  328. vid->vl_bfw, vid->vl_efw);
  329. fbi->reg_lccr1 =
  330. LCCR1_DisWdth(vid->vl_col) +
  331. LCCR1_HorSnchWdth(vid->vl_hpw) +
  332. LCCR1_BegLnDel(vid->vl_blw) +
  333. LCCR1_EndLnDel(vid->vl_elw);
  334. fbi->reg_lccr2 =
  335. LCCR2_DisHght(vid->vl_row) +
  336. LCCR2_VrtSnchWdth(vid->vl_vpw) +
  337. LCCR2_BegFrmDel(vid->vl_bfw) +
  338. LCCR2_EndFrmDel(vid->vl_efw);
  339. fbi->reg_lccr3 = REG_LCCR3 & ~(LCCR3_HSP | LCCR3_VSP);
  340. fbi->reg_lccr3 |= (vid->vl_hsp ? LCCR3_HorSnchL : LCCR3_HorSnchH)
  341. | (vid->vl_vsp ? LCCR3_VrtSnchL : LCCR3_VrtSnchH);
  342. /* setup dma descriptors */
  343. fbi->dmadesc_fblow = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 3*16);
  344. fbi->dmadesc_fbhigh = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 2*16);
  345. fbi->dmadesc_palette = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 1*16);
  346. #define BYTES_PER_PANEL ((fbi->reg_lccr0 & LCCR0_SDS) ? \
  347. (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8 / 2) : \
  348. (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8))
  349. /* populate descriptors */
  350. fbi->dmadesc_fblow->fdadr = (u_long)fbi->dmadesc_fblow;
  351. fbi->dmadesc_fblow->fsadr = fbi->screen + BYTES_PER_PANEL;
  352. fbi->dmadesc_fblow->fidr = 0;
  353. fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL;
  354. fbi->fdadr1 = (u_long)fbi->dmadesc_fblow; /* only used in dual-panel mode */
  355. fbi->dmadesc_fbhigh->fsadr = fbi->screen;
  356. fbi->dmadesc_fbhigh->fidr = 0;
  357. fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL;
  358. fbi->dmadesc_palette->fsadr = fbi->palette;
  359. fbi->dmadesc_palette->fidr = 0;
  360. fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
  361. if( NBITS(vid->vl_bpix) < 12)
  362. {
  363. /* assume any mode with <12 bpp is palette driven */
  364. fbi->dmadesc_palette->fdadr = (u_long)fbi->dmadesc_fbhigh;
  365. fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_palette;
  366. /* flips back and forth between pal and fbhigh */
  367. fbi->fdadr0 = (u_long)fbi->dmadesc_palette;
  368. }
  369. else
  370. {
  371. /* palette shouldn't be loaded in true-color mode */
  372. fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_fbhigh;
  373. fbi->fdadr0 = (u_long)fbi->dmadesc_fbhigh; /* no pal just fbhigh */
  374. }
  375. debug("fbi->dmadesc_fblow = 0x%lx\n", (u_long)fbi->dmadesc_fblow);
  376. debug("fbi->dmadesc_fbhigh = 0x%lx\n", (u_long)fbi->dmadesc_fbhigh);
  377. debug("fbi->dmadesc_palette = 0x%lx\n", (u_long)fbi->dmadesc_palette);
  378. debug("fbi->dmadesc_fblow->fdadr = 0x%lx\n", fbi->dmadesc_fblow->fdadr);
  379. debug("fbi->dmadesc_fbhigh->fdadr = 0x%lx\n", fbi->dmadesc_fbhigh->fdadr);
  380. debug("fbi->dmadesc_palette->fdadr = 0x%lx\n", fbi->dmadesc_palette->fdadr);
  381. debug("fbi->dmadesc_fblow->fsadr = 0x%lx\n", fbi->dmadesc_fblow->fsadr);
  382. debug("fbi->dmadesc_fbhigh->fsadr = 0x%lx\n", fbi->dmadesc_fbhigh->fsadr);
  383. debug("fbi->dmadesc_palette->fsadr = 0x%lx\n", fbi->dmadesc_palette->fsadr);
  384. debug("fbi->dmadesc_fblow->ldcmd = 0x%lx\n", fbi->dmadesc_fblow->ldcmd);
  385. debug("fbi->dmadesc_fbhigh->ldcmd = 0x%lx\n", fbi->dmadesc_fbhigh->ldcmd);
  386. debug("fbi->dmadesc_palette->ldcmd = 0x%lx\n", fbi->dmadesc_palette->ldcmd);
  387. return 0;
  388. }
  389. /************************************************************************/
  390. /************************************************************************/
  391. #endif /* CONFIG_LCD */