2 * Some routines to enable the LCD in an IPAQ H3800 (and maybe others).
4 * Contains stuff taken from Linux and bootldr.
8 #include <l4/drivers/lcd.h>
12 void putstr(const char *);
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>
21 typedef unsigned short u16;
23 #define SET_ASIC1(x) \
24 do {if ( setp ) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0)
26 #define CTL_REG_READ(addr) (*(volatile unsigned long *)(addr))
27 #define CTL_REG_WRITE(addr, val) (*(volatile unsigned long *)(addr) = (val))
29 #define CTL_REG_READ_BYTE(addr) (*(volatile unsigned char *)(addr))
30 #define CTL_REG_WRITE_BYTE(addr, val) (*(volatile unsigned char *)(addr) = (val))
32 #define TIMEOUT 350000
34 static void sa_lcd_light(int on, int level)
36 (void)on; (void)level;
39 static void sa_control_egpio(enum ipaq_egpio_type x, int setp)
42 case IPAQ_EGPIO_LCD_ON:
43 SET_ASIC1( GPIO1_LCD_5V_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:
64 static void arm_lcd_h3800_disable(void)
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);
75 #define GPIO_WRITE(off, v) \
76 ((*((volatile unsigned long *)(((char*)GPIO_BASE)+(off)))) = (v))
78 #define GPIO_GAFR_WRITE(v) GPIO_WRITE(GPIO_GAFR_OFF,v)
79 #define GPIO_GPDR_WRITE(v) GPIO_WRITE(GPIO_GPDR_OFF,v)
81 static unsigned long *sa_vidmem;
83 static void arm_lcd_h3800_enable(void)
85 //arm_lcd_h3800_disable();
87 //printf("Enabling LCD controller.\n");
90 GPIO_GAFR_WRITE(0xff << 2);
91 GPIO_GPDR_WRITE(0xff << 2);
93 sa_vidmem[0] = 0x2077;
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 +
109 if (!l4dm_mem_phys_addr(sa_vidmem, 4, &phys, 1, &pnum)
112 printf("Cannot get physical address of vidmem.\n");
115 printf("Physical address of vidmem is %08lx\n", phys.addr);
123 sa_control_egpio(IPAQ_EGPIO_LCD_ON, 1);
125 CTL_REG_WRITE(GPIO_BASE+GPIO_GPDR_OFF, 0xff << 2);
126 CTL_REG_WRITE(GPIO_BASE+GPIO_GPSR_OFF, 0);
128 sa_control_egpio(IPAQ_EGPIO_LCD_ON, 1);
135 * Returns the address to the framebuffer, and does some initialisation
138 static void *arm_lcd_h3800_fb(void)
140 if (arm_driver_reserve_region(H3800_ASIC_BASE, 0x100000))
142 if (arm_driver_reserve_region(_LCCR0, 0x100000))
144 if (arm_driver_reserve_region(GPIO_BASE, 0x100000))
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)))
152 printf("Could not get video memory.\n");
155 printf("Video memory is at virtual %p\n", sa_vidmem);
157 // --------------------------------------------------------------------
159 //H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ | GPIO2_SD_DETECT | GPIO2_EAR_IN_N | GPIO2_USB_DETECT_N | GPIO2_SD_CON_SLT;
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;
167 //sa_disable_controller();
171 unsigned short* bufp = (unsigned short*)LCD_FB_IMAGE(sa_vidmem, 16);
173 for (num_pixels = LCD_NUM_PIXELS(); num_pixels; num_pixels--)
175 *bufp++ = (unsigned short)num_pixels;
180 arm_lcd_h3800_enable();
182 return LCD_FB_IMAGE(sa_vidmem, 16);
185 static unsigned int arm_lcd_h3800_video_mem_size(void)
186 { return LCD_XRES * LCD_YRES * ((LCD_BPP + 7) >> 3); }
188 static unsigned int arm_lcd_h3800_get_screen_width(void)
191 static unsigned int arm_lcd_h3800_get_screen_height(void)
194 static unsigned int arm_lcd_h3800_get_bpp(void)
197 static unsigned int arm_lcd_h3800_get_bytes_per_line(void)
198 { return LCD_XRES * ((LCD_BPP + 7) >> 3); }
200 static int get_fbinfo(l4re_fb_info_t *fbinfo)
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;
213 fbinfo->b.shift = 11;
220 static const char *arm_lcd_h3800_get_info(void)
221 { return "ARM LCD driver for IPAQ H3800 series"; }
223 static int arm_lcd_h3800_probe(const char *configstr)
226 return !l4io_lookup_device("H3800 LCD", NULL, 0, 0);
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,
239 arm_lcd_register(&arm_lcd_ops_h3800);