clcd.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * arch/arm/mach-lh7a40x/clcd.c
  3. *
  4. * Copyright (C) 2004 Marc Singer
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * version 2 as published by the Free Software Foundation.
  9. *
  10. */
  11. #include <linux/init.h>
  12. #include <linux/device.h>
  13. #include <linux/dma-mapping.h>
  14. #include <linux/sysdev.h>
  15. #include <linux/interrupt.h>
  16. //#include <linux/module.h>
  17. //#include <linux/time.h>
  18. //#include <asm/hardware.h>
  19. //#include <asm/mach/time.h>
  20. #include <asm/irq.h>
  21. #include <asm/mach/irq.h>
  22. #include <asm/system.h>
  23. #include <asm/hardware.h>
  24. #include <linux/amba/bus.h>
  25. #include <linux/amba/clcd.h>
  26. #define HRTFTC_HRSETUP __REG(HRTFTC_PHYS + 0x00)
  27. #define HRTFTC_HRCON __REG(HRTFTC_PHYS + 0x04)
  28. #define HRTFTC_HRTIMING1 __REG(HRTFTC_PHYS + 0x08)
  29. #define HRTFTC_HRTIMING2 __REG(HRTFTC_PHYS + 0x0c)
  30. #define ALI_SETUP __REG(ALI_PHYS + 0x00)
  31. #define ALI_CONTROL __REG(ALI_PHYS + 0x04)
  32. #define ALI_TIMING1 __REG(ALI_PHYS + 0x08)
  33. #define ALI_TIMING2 __REG(ALI_PHYS + 0x0c)
  34. #include "lcd-panel.h"
  35. static void lh7a40x_clcd_disable (struct clcd_fb *fb)
  36. {
  37. #if defined (CONFIG_MACH_LPD7A400)
  38. CPLD_CONTROL &= ~(1<<1); /* Disable LCD Vee */
  39. #endif
  40. #if defined (CONFIG_MACH_LPD7A404)
  41. GPIO_PCD &= ~(1<<3); /* Disable LCD Vee */
  42. #endif
  43. #if defined (CONFIG_ARCH_LH7A400)
  44. HRTFTC_HRSETUP &= ~(1<<13); /* Disable HRTFT controller */
  45. #endif
  46. #if defined (CONFIG_ARCH_LH7A404)
  47. ALI_SETUP &= ~(1<<13); /* Disable ALI */
  48. #endif
  49. }
  50. static void lh7a40x_clcd_enable (struct clcd_fb *fb)
  51. {
  52. struct clcd_panel_extra* extra
  53. = (struct clcd_panel_extra*) fb->board_data;
  54. #if defined (CONFIG_MACH_LPD7A400)
  55. CPLD_CONTROL |= (1<<1); /* Enable LCD Vee */
  56. #endif
  57. #if defined (CONFIG_MACH_LPD7A404)
  58. GPIO_PCDD &= ~(1<<3); /* Enable LCD Vee */
  59. GPIO_PCD |= (1<<3);
  60. #endif
  61. #if defined (CONFIG_ARCH_LH7A400)
  62. if (extra) {
  63. HRTFTC_HRSETUP
  64. = (1 << 13)
  65. | ((fb->fb.var.xres - 1) << 4)
  66. | 0xc
  67. | (extra->hrmode ? 1 : 0);
  68. HRTFTC_HRCON
  69. = ((extra->clsen ? 1 : 0) << 1)
  70. | ((extra->spsen ? 1 : 0) << 0);
  71. HRTFTC_HRTIMING1
  72. = (extra->pcdel << 8)
  73. | (extra->revdel << 4)
  74. | (extra->lpdel << 0);
  75. HRTFTC_HRTIMING2
  76. = (extra->spldel << 9)
  77. | (extra->pc2del << 0);
  78. }
  79. else
  80. HRTFTC_HRSETUP
  81. = (1 << 13)
  82. | 0xc;
  83. #endif
  84. #if defined (CONFIG_ARCH_LH7A404)
  85. if (extra) {
  86. ALI_SETUP
  87. = (1 << 13)
  88. | ((fb->fb.var.xres - 1) << 4)
  89. | 0xc
  90. | (extra->hrmode ? 1 : 0);
  91. ALI_CONTROL
  92. = ((extra->clsen ? 1 : 0) << 1)
  93. | ((extra->spsen ? 1 : 0) << 0);
  94. ALI_TIMING1
  95. = (extra->pcdel << 8)
  96. | (extra->revdel << 4)
  97. | (extra->lpdel << 0);
  98. ALI_TIMING2
  99. = (extra->spldel << 9)
  100. | (extra->pc2del << 0);
  101. }
  102. else
  103. ALI_SETUP
  104. = (1 << 13)
  105. | 0xc;
  106. #endif
  107. }
  108. #define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
  109. static int lh7a40x_clcd_setup (struct clcd_fb *fb)
  110. {
  111. dma_addr_t dma;
  112. u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
  113. *(lcd_panel.bpp/8));
  114. fb->panel = &lcd_panel;
  115. /* Enforce the sync polarity defaults */
  116. if (!(fb->panel->tim2 & TIM2_IHS))
  117. fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
  118. if (!(fb->panel->tim2 & TIM2_IVS))
  119. fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
  120. #if defined (HAS_LCD_PANEL_EXTRA)
  121. fb->board_data = &lcd_panel_extra;
  122. #endif
  123. fb->fb.screen_base
  124. = dma_alloc_writecombine (&fb->dev->dev, len,
  125. &dma, GFP_KERNEL);
  126. printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
  127. fb->fb.screen_base, (void*) dma, len,
  128. (void*) io_p2v (CLCDC_PHYS));
  129. printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
  130. if (!fb->fb.screen_base) {
  131. printk(KERN_ERR "CLCD: unable to map framebuffer\n");
  132. return -ENOMEM;
  133. }
  134. #if defined (USE_RGB555)
  135. fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
  136. #endif
  137. fb->fb.fix.smem_start = dma;
  138. fb->fb.fix.smem_len = len;
  139. /* Drive PE4 high to prevent CPLD crash */
  140. GPIO_PEDD |= (1<<4);
  141. GPIO_PED |= (1<<4);
  142. GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
  143. // fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
  144. // fb->fb.fbops->fb_set_par (&fb->fb);
  145. return 0;
  146. }
  147. static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
  148. {
  149. return dma_mmap_writecombine(&fb->dev->dev, vma,
  150. fb->fb.screen_base,
  151. fb->fb.fix.smem_start,
  152. fb->fb.fix.smem_len);
  153. }
  154. static void lh7a40x_clcd_remove (struct clcd_fb *fb)
  155. {
  156. dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
  157. fb->fb.screen_base, fb->fb.fix.smem_start);
  158. }
  159. static struct clcd_board clcd_platform_data = {
  160. .name = "lh7a40x FB",
  161. .check = clcdfb_check,
  162. .decode = clcdfb_decode,
  163. .enable = lh7a40x_clcd_enable,
  164. .setup = lh7a40x_clcd_setup,
  165. .mmap = lh7a40x_clcd_mmap,
  166. .remove = lh7a40x_clcd_remove,
  167. .disable = lh7a40x_clcd_disable,
  168. };
  169. #define IRQ_CLCDC (IRQ_LCDINTR)
  170. #define AMBA_DEVICE(name,busid,base,plat,pid) \
  171. static struct amba_device name##_device = { \
  172. .dev = { \
  173. .coherent_dma_mask = ~0, \
  174. .bus_id = busid, \
  175. .platform_data = plat, \
  176. }, \
  177. .res = { \
  178. .start = base##_PHYS, \
  179. .end = (base##_PHYS) + (4*1024) - 1, \
  180. .flags = IORESOURCE_MEM, \
  181. }, \
  182. .dma_mask = ~0, \
  183. .irq = { IRQ_##base, }, \
  184. /* .dma = base##_DMA,*/ \
  185. .periphid = pid, \
  186. }
  187. AMBA_DEVICE(clcd, "cldc-lh7a40x", CLCDC, &clcd_platform_data, 0x41110);
  188. static struct amba_device *amba_devs[] __initdata = {
  189. &clcd_device,
  190. };
  191. void __init lh7a40x_clcd_init (void)
  192. {
  193. int i;
  194. int result;
  195. printk ("CLCD: registering amba devices\n");
  196. for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
  197. struct amba_device *d = amba_devs[i];
  198. result = amba_device_register(d, &iomem_resource);
  199. printk (" %d -> %d\n", i ,result);
  200. }
  201. }