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