2 * AMBA CLCD PL110 driver
5 #include <l4/arm_drivers/lcd.h>
6 #include <l4/arm_drivers/amba.h>
7 #include <l4/arm_drivers/io.h>
12 #include <l4/re/c/dataspace.h>
13 #include <l4/re/c/util/cap_alloc.h>
14 #include <l4/re/c/mem_alloc.h>
15 #include <l4/re/c/rm.h>
21 int config_request_xga;
26 UNINITIALIZED, PL110, PL111, PL_UNKNOWN
29 static enum pl11x_type type;
30 static void *fb_vaddr;
31 static l4_addr_t fb_paddr;
36 static void config(const char *c)
38 // this driver scans for the following:
39 // 1024: XGA mode, VGA mode otherwise
40 // BGR: do bgr mode instead of rgb
41 // 565: mode (if PL111 available)
45 config_request_xga = strcasestr(c, "1024") != NULL;
46 config_do_bgr = strcasestr(c, "bgr") != NULL;
47 config_use_565 = strcasestr(c, "565") != NULL;
52 static void set_colors(l4re_video_view_info_t *vinfo,
53 int wr, int wg, int wb,
54 int sr, int sg, int sb)
56 vinfo->pixel_info.r.shift = sr;
57 vinfo->pixel_info.r.size = wr;
58 vinfo->pixel_info.g.shift = sg;
59 vinfo->pixel_info.g.size = wg;
60 vinfo->pixel_info.b.shift = sb;
61 vinfo->pixel_info.b.size = wb;
63 printf("Color mode: %d:%d:%d %d:%d:%d\n", sr, sg, sb, wr, wg, wb);
66 static int get_fbinfo(l4re_video_view_info_t *vinfo)
69 vinfo->width = use_xga ? 1024 : 640;
70 vinfo->height = use_xga ? 768 : 480;
71 vinfo->pixel_info.bytes_per_pixel = 2;
72 vinfo->bytes_per_line = 2 * vinfo->width;
74 if ((config_use_565 && type == PL111) || (is_qemu && type == PL110))
77 set_colors(vinfo, 5, 6, 5, 11, 5, 0);
79 set_colors(vinfo, 5, 6, 5, 0, 5, 11);
84 set_colors(vinfo, 5, 5, 5, 10, 5, 0);
86 set_colors(vinfo, 5, 5, 5, 0, 5, 10);
92 static int probe(const char *c)
96 return !l4io_lookup_device("AMBA PL110", NULL, 0, 0);
99 static unsigned int fbmem_size(void)
100 { return use_xga ? (1024 * 768 * 2) : (480 * 640 * 2); }
102 unsigned long amba_pl110_lcd_control_virt_base;
103 unsigned long amba_pl110_sys_base_virt;
105 static void setup_type(void)
107 uint32_t cellid, periphid;
109 amba_read_id(amba_pl110_lcd_control_virt_base + 0xfe0, &periphid, &cellid);
111 if (periphid == 0x00041111 && cellid == 0xb105f00d)
113 else if (periphid == 0x00041110 && cellid == 0xb105f00d)
119 static const char *arm_lcd_get_info(void)
121 return "ARM AMBA PrimeCell 11x";
125 l4_umword_t read_sys_reg(unsigned reg)
127 return io_read_mword(amba_pl110_sys_base_virt + reg);
131 void write_sys_reg(unsigned reg, l4_umword_t val)
133 io_write_mword(amba_pl110_sys_base_virt + reg, val);
137 void set_clcd_clock(l4_umword_t val)
139 write_sys_reg(Reg_sys_lock, Sys_lock_unlock);
140 write_sys_reg(Reg_sys_osc4, val);
141 write_sys_reg(Reg_sys_lock, Sys_lock_lock);
145 l4_umword_t read_clcd_reg(unsigned reg)
147 return *((volatile l4_umword_t *)(amba_pl110_lcd_control_virt_base + reg));
151 void write_clcd_reg(unsigned reg, l4_umword_t val)
153 *((volatile l4_umword_t *)(amba_pl110_lcd_control_virt_base + reg)) = val;
157 int init(unsigned long fb_phys_addr)
161 id = read_sys_reg(Reg_sys_clcd) & Sys_clcd_idmask;
165 case Sys_clcd_idmask:
166 case 0x1000: // (strange?) qemu value, should be 0x100, or did they think BE?
167 printf("Configure 8.4 CLCD\n");
170 set_clcd_clock(Sys_osc4_xga);
171 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_84_xga);
172 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_84_xga);
173 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_84_xga);
174 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_84_xga);
178 set_clcd_clock(Sys_osc4_25mhz);
179 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_84_vga);
180 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_84_vga);
181 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_84_vga);
182 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_84_vga);
187 printf("Configure 3.8 CLCD\n");
188 set_clcd_clock(Sys_osc4_10mhz);
189 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_38);
190 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_38);
191 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_38);
192 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_38);
196 printf("Configure 2.5 CLCD\n");
197 set_clcd_clock(Sys_osc4_5p4mhz);
198 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_25);
199 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_25);
200 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_25);
201 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_25);
203 // Turn the backlight on
204 //write_ib2_reg(Reg_ib2_ctrl, read_ib2_reg(Reg_ib2_ctrl) | 0x01);
208 printf("Error: Unknown display type (ID: %lx)\n", id >> 8);
212 // Set physical framebuffer address
213 write_clcd_reg(Reg_clcd_ubas, fb_phys_addr);
214 write_clcd_reg(Reg_clcd_lbas, 0);
215 write_clcd_reg(Reg_clcd_ienb, 0);
217 // Switch power off and configure
218 write_clcd_reg(Reg_clcd_cntl,
219 ((type == PL111 && config_use_565 && !is_qemu)
220 ? Clcd_cntl_lcdbpp16_pl111_565
221 : Clcd_cntl_lcdbpp16)
222 | Clcd_cntl_lcden | Clcd_cntl_lcdbw
223 | Clcd_cntl_lcdtft | Clcd_cntl_lcdvcomp
224 | (config_do_bgr ? Clcd_cntl_lcdbgr : 0));
227 write_clcd_reg(Reg_clcd_cntl, read_clcd_reg(Reg_clcd_cntl) | Clcd_cntl_lcdpwr);
232 static void setup_memory(void)
235 l4io_device_handle_t dh;
236 l4io_resource_handle_t hdl;
241 if (l4io_lookup_device("System Control", &dh, 0, &hdl))
243 printf("Could not get system controller space\n");
247 /* System controller -- XXX Wrong Place XXX */
248 amba_pl110_sys_base_virt
249 = l4io_request_resource_iomem(dh, &hdl);
250 if (amba_pl110_sys_base_virt == 0)
252 printf("Could not map system controller space\n");
256 if (l4io_lookup_device("AMBA PL110", &dh, 0, &hdl))
258 printf("Could not get PL110 LCD device\n");
262 amba_pl110_lcd_control_virt_base
263 = l4io_request_resource_iomem(dh, &hdl);
264 if (amba_pl110_lcd_control_virt_base == 0)
266 printf("Could not map controller space for '%s'\n", arm_lcd_get_info());
272 if ((read_sys_reg(Reg_sys_clcd) & Sys_clcd_idmask) == 0x1000)
274 is_qemu = 1; // remember if we run on qemu because of the different
275 // handling of the bpp16 mode with PL110: my hardware has
276 // 5551 mode, qemu does 565
277 type = PL111; // also set the type to PL111 because qemu only
278 // announces a PL110 but can do the 1024 resolution too
279 printf("Running on QEmu (assuming PL111).\n");
282 if (config_request_xga && type == PL111)
285 // get some frame buffer
286 l4re_ds_t mem = l4re_util_cap_alloc();
287 if (l4_is_invalid_cap(mem))
290 if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED))
292 printf("Error allocating memory\n");
297 if (l4re_rm_attach(&fb_vaddr, fbmem_size(),
298 L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP,
299 mem, 0, L4_PAGESHIFT))
301 printf("Error getting memory\n");
305 printf("Video memory is at virtual %p (size: 0x%x Bytes)\n",
306 fb_vaddr, fbmem_size());
308 // get physical address
309 if (l4re_ds_phys(mem, 0, &fb_paddr, &phys_size)
310 || phys_size != fbmem_size())
312 printf("Getting the physical address failed or not contiguous\n");
315 printf("Physical video memory is at %p\n", (void *)fb_paddr);
318 static void *fb(void)
326 static void pl110_enable(void)
334 case PL110: s = "ARM AMBA PrimeCell PL110"; break;
335 case PL111: s = "ARM AMBA PrimeCell PL111"; break;
336 default: s = "Unknown"; break;
339 printf("Detected a '%s' device.\n", s);
341 if (!fb_vaddr || !init(fb_paddr))
343 printf("CLCD init failed!\n");
348 static void pl110_disable(void)
351 static struct arm_lcd_ops arm_lcd_ops_pl11x = {
353 .get_fbinfo = get_fbinfo,
355 .get_video_mem_size = fbmem_size,
356 .get_info = arm_lcd_get_info,
357 .enable = pl110_enable,
358 .disable = pl110_disable,
361 arm_lcd_register(&arm_lcd_ops_pl11x);