]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/arm_drivers/lcd/src/lcd-h3800.c
update
[l4.git] / l4 / pkg / arm_drivers / lcd / src / lcd-h3800.c
1 /*
2  * Some routines to enable the LCD in an IPAQ H3800 (and maybe others).
3  *
4  * Contains stuff taken from Linux and bootldr.
5  *
6  */
7
8 #include <l4/arm_drivers/lcd.h>
9 #include <stdio.h>
10
11 /* Gnah... */
12 void putstr(const char *);
13
14 #define CONFIG_MACH_IPAQ 1
15 #include <arch-sa1100/sa1100.h>
16 #include <arch-sa1100/sa1100-lcd.h>
17 #define __SERIAL_H__ /* don't include serial.h */
18 #include <arch-sa1100/h3600.h>
19 #include <arch-sa1100/h3600_asic.h>
20
21 typedef unsigned short u16;
22
23 #define SET_ASIC1(x) \
24    do {if ( setp ) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0)
25
26 #define CTL_REG_READ(addr)          (*(volatile unsigned long *)(addr))
27 #define CTL_REG_WRITE(addr, val)    (*(volatile unsigned long *)(addr) = (val))
28
29 #define CTL_REG_READ_BYTE(addr)     (*(volatile unsigned char *)(addr))
30 #define CTL_REG_WRITE_BYTE(addr, val)    (*(volatile unsigned char *)(addr) = (val))
31
32 #define TIMEOUT        350000
33
34 static void sa_lcd_light(int on, int level)
35 {
36   (void)on; (void)level;
37 }
38
39 static void sa_control_egpio(enum ipaq_egpio_type x, int setp)
40 {
41   switch (x) {
42     case IPAQ_EGPIO_LCD_ON:
43       SET_ASIC1( GPIO1_LCD_5V_ON
44                  | GPIO1_LCD_ON
45                  | GPIO1_LCD_PCI
46                  | GPIO1_VGH_ON
47                  | GPIO1_VGL_ON);
48     case IPAQ_EGPIO_CODEC_NRESET:
49     case IPAQ_EGPIO_AUDIO_ON:
50     case IPAQ_EGPIO_QMUTE:
51     case IPAQ_EGPIO_OPT_NVRAM_ON:
52     case IPAQ_EGPIO_OPT_ON:
53     case IPAQ_EGPIO_CARD_RESET:
54     case IPAQ_EGPIO_OPT_RESET:
55     case IPAQ_EGPIO_IR_ON:
56     case IPAQ_EGPIO_IR_FSEL:
57     case IPAQ_EGPIO_RS232_ON:
58     case IPAQ_EGPIO_VPP_ON:
59     case IPAQ_EGPIO_COM_DSR:
60       break;
61   }
62 }
63
64 static void arm_lcd_h3800_disable(void)
65 {
66   sa_lcd_light(0, 0);
67
68   LCSR = 0;   /* Clear LCD Status Register */
69   LCCR0 &= ~(LCCR0_LDM);      /* Enable LCD Disable Done Interrupt */
70   LCCR0 &= ~(LCCR0_LEN);      /* Disable LCD Controller */
71   CTL_REG_WRITE(GPIO_BASE+GPIO_GPCR_OFF, 0 /*params->gpio*/);
72   sa_control_egpio(IPAQ_EGPIO_LCD_ON, 0);
73 }
74
75 #define GPIO_WRITE(off, v)  \
76     ((*((volatile unsigned long *)(((char*)GPIO_BASE)+(off)))) = (v))
77
78 #define GPIO_GAFR_WRITE(v)   GPIO_WRITE(GPIO_GAFR_OFF,v)
79 #define GPIO_GPDR_WRITE(v)   GPIO_WRITE(GPIO_GPDR_OFF,v)
80
81 static unsigned long *sa_vidmem;
82
83 static void arm_lcd_h3800_enable(void)
84 {
85   //arm_lcd_h3800_disable();
86
87   //printf("Enabling LCD controller.\n");
88
89 #if 0
90   GPIO_GAFR_WRITE(0xff << 2);
91   GPIO_GPDR_WRITE(0xff << 2);
92
93   sa_vidmem[0] = 0x2077;
94
95   LCCR3 = 0x10 | LCCR3_VrtSnchL | LCCR3_HorSnchL;
96   LCCR2 = LCCR2_DisHght(VESA_YRES + 1) + LCCR2_VrtSnchWdth(3)
97           + LCCR2_BegFrmDel(10) + LCCR2_EndFrmDel(1);
98   LCCR1 = LCCR1_DisWdth(VESA_XRES) + LCCR1_HorSnchWdth(4) +
99           LCCR1_BegLnDel(0xC) + LCCR1_EndLnDel(0x11);
100   LCCR0 = (LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
101            LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
102            LCCR0_DMADel(0))
103           & ~LCCR0_LEN;
104
105 #endif
106   {
107     l4_size_t phys_size;
108
109     if (!l4dm_mem_phys_addr(sa_vidmem, 4, &phys, 1, &pnum)
110         || !pnum)
111       {
112         printf("Cannot get physical address of vidmem.\n");
113         return;
114       }
115     printf("Physical address of vidmem is %08lx\n", phys.addr);
116
117     DBAR1 = phys.addr;
118   }
119
120 #if 0
121   LCCR0 |= LCCR0_LEN;
122
123   sa_control_egpio(IPAQ_EGPIO_LCD_ON, 1);
124
125   CTL_REG_WRITE(GPIO_BASE+GPIO_GPDR_OFF, 0xff << 2);
126   CTL_REG_WRITE(GPIO_BASE+GPIO_GPSR_OFF, 0);
127
128   sa_control_egpio(IPAQ_EGPIO_LCD_ON, 1);
129
130 #endif
131   sa_lcd_light(1, 5);
132 }
133
134 /*
135  * Returns the address to the framebuffer, and does some initialisation
136  * stuff.
137  */
138 static void *arm_lcd_h3800_fb(void)
139 {
140   if (arm_driver_reserve_region(H3800_ASIC_BASE, 0x100000))
141     return NULL;
142   if (arm_driver_reserve_region(_LCCR0, 0x100000))
143     return NULL;
144   if (arm_driver_reserve_region(GPIO_BASE, 0x100000))
145     return NULL;
146
147   // get some frame buffer memory
148   if (!(sa_vidmem = l4dm_mem_allocate(0x100000,
149                                       L4DM_PINNED | L4DM_CONTIGUOUS |
150                                       L4RM_MAP | L4RM_LOG2_ALLOC)))
151     {
152       printf("Could not get video memory.\n");
153       return NULL;
154     }
155   printf("Video memory is at virtual %p\n", sa_vidmem);
156
157   // --------------------------------------------------------------------
158
159   //H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ | GPIO2_SD_DETECT | GPIO2_EAR_IN_N | GPIO2_USB_DETECT_N | GPIO2_SD_CON_SLT;
160
161   // This is all for the H3800 display
162   //*((unsigned short *) H3800_ASIC1_GPIO_MASK_ADDR) = H3800_ASIC1_GPIO_MASK_INIT;
163   //*((unsigned short *) H3800_ASIC1_GPIO_OUT_ADDR) = H3800_ASIC1_GPIO_OUT_INIT;
164   //*((unsigned short *) H3800_ASIC1_GPIO_DIR_ADDR) = H3800_ASIC1_GPIO_DIR_INIT;
165   //*((unsigned short *) H3800_ASIC1_GPIO_OUT_ADDR) = H3800_ASIC1_GPIO_OUT_INIT;
166
167   //sa_disable_controller();
168
169   {
170     int num_pixels;
171     unsigned short* bufp = (unsigned short*)LCD_FB_IMAGE(sa_vidmem, 16);
172
173     for (num_pixels = LCD_NUM_PIXELS(); num_pixels; num_pixels--)
174       {
175         *bufp++ = (unsigned short)num_pixels;
176       }
177   }
178
179
180   arm_lcd_h3800_enable();
181
182   return LCD_FB_IMAGE(sa_vidmem, 16);
183 }
184
185 static unsigned int arm_lcd_h3800_video_mem_size(void)
186 { return LCD_XRES * LCD_YRES * ((LCD_BPP + 7) >> 3); }
187
188 static unsigned int arm_lcd_h3800_get_screen_width(void)
189 { return LCD_XRES; }
190
191 static unsigned int arm_lcd_h3800_get_screen_height(void)
192 { return LCD_YRES; }
193
194 static unsigned int arm_lcd_h3800_get_bpp(void)
195 { return LCD_BPP; }
196
197 static unsigned int arm_lcd_h3800_get_bytes_per_line(void)
198 { return LCD_XRES * ((LCD_BPP + 7) >> 3); }
199
200 static int get_fbinfo(l4re_fb_info_t *fbinfo)
201 {
202
203   fbinfo->x_res               = LCD_XRES;
204   fbinfo->y_res               = LCD_YRES;
205   fbinfo->bits_per_pixel      = LCD_BPP;
206   fbinfo->bytes_per_pixel     = (LCD_BPP + 7) >> 3;
207   fbinfo->bytes_per_scan_line = ((LCD_BPP + 7) >> 3) * fbinfo->x_res;
208
209   fbinfo->r.shift = 0;
210   fbinfo->r.size  = 5;
211   fbinfo->g.shift = 5;
212   fbinfo->g.size  = 6;
213   fbinfo->b.shift = 11;
214   fbinfo->b.size  = 5;
215
216   return 0;
217 }
218
219
220 static const char *arm_lcd_h3800_get_info(void)
221 { return "ARM LCD driver for IPAQ H3800 series"; }
222
223 static int arm_lcd_h3800_probe(const char *configstr)
224 {
225   (void)configstr;
226   return !l4io_lookup_device("H3800 LCD", NULL, 0, 0);
227 }
228
229 struct arm_lcd_ops arm_lcd_ops_h3800 = {
230   .probe              = arm_lcd_h3800_probe,
231   .get_fb             = arm_lcd_h3800_fb,
232   .get_fbinfo         = get_fbinfo,
233   .get_video_mem_size = arm_lcd_h3800_video_mem_size,
234   .get_info           = arm_lcd_h3800_get_info,
235   .enable             = arm_lcd_h3800_enable,
236   .disable            = arm_lcd_h3800_disable,
237 };
238
239 arm_lcd_register(&arm_lcd_ops_h3800);