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;
64 static int get_fbinfo(l4re_video_view_info_t *vinfo)
67 vinfo->width = use_xga ? 1024 : 640;
68 vinfo->height = use_xga ? 768 : 480;
69 vinfo->pixel_info.bytes_per_pixel = 2;
70 vinfo->bytes_per_line = 2 * vinfo->width;
72 if ((config_use_565 && type == PL111) || (is_qemu && type == PL110))
75 set_colors(vinfo, 5, 6, 5, 11, 5, 0);
77 set_colors(vinfo, 5, 6, 5, 0, 5, 11);
82 set_colors(vinfo, 5, 5, 5, 10, 5, 0);
84 set_colors(vinfo, 5, 5, 5, 0, 5, 10);
90 static int probe(const char *c)
94 return !l4io_lookup_device("AMBA PL110", NULL, 0, 0);
97 static unsigned int fbmem_size(void)
98 { return use_xga ? (1024 * 768 * 2) : (480 * 640 * 2); }
100 unsigned long amba_pl110_lcd_control_virt_base;
101 unsigned long amba_pl110_sys_base_virt;
103 static void setup_type(void)
105 uint32_t cellid, periphid;
107 amba_read_id(amba_pl110_lcd_control_virt_base + 0xfe0, &periphid, &cellid);
109 if (periphid == 0x00041111 && cellid == 0xb105f00d)
111 else if (periphid == 0x00041110 && cellid == 0xb105f00d)
117 static const char *arm_lcd_get_info(void)
119 return "ARM AMBA PrimeCell 11x";
123 l4_umword_t read_sys_reg(unsigned reg)
125 return io_read_mword(amba_pl110_sys_base_virt + reg);
129 void write_sys_reg(unsigned reg, l4_umword_t val)
131 io_write_mword(amba_pl110_sys_base_virt + reg, val);
135 void set_clcd_clock(l4_umword_t val)
137 write_sys_reg(Reg_sys_lock, Sys_lock_unlock);
138 write_sys_reg(Reg_sys_osc4, val);
139 write_sys_reg(Reg_sys_lock, Sys_lock_lock);
143 l4_umword_t read_clcd_reg(unsigned reg)
145 return *((volatile l4_umword_t *)(amba_pl110_lcd_control_virt_base + reg));
149 void write_clcd_reg(unsigned reg, l4_umword_t val)
151 *((volatile l4_umword_t *)(amba_pl110_lcd_control_virt_base + reg)) = val;
155 int init(unsigned long fb_phys_addr)
159 id = read_sys_reg(Reg_sys_clcd) & Sys_clcd_idmask;
163 case Sys_clcd_idmask:
164 case 0x1000: // (strange?) qemu value, should be 0x100, or did they think BE?
165 printf("Configure 8.4 CLCD\n");
168 set_clcd_clock(Sys_osc4_xga);
169 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_84_xga);
170 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_84_xga);
171 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_84_xga);
172 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_84_xga);
176 set_clcd_clock(Sys_osc4_25mhz);
177 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_84_vga);
178 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_84_vga);
179 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_84_vga);
180 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_84_vga);
185 printf("Configure 3.8 CLCD\n");
186 set_clcd_clock(Sys_osc4_10mhz);
187 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_38);
188 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_38);
189 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_38);
190 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_38);
194 printf("Configure 2.5 CLCD\n");
195 set_clcd_clock(Sys_osc4_5p4mhz);
196 write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_25);
197 write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_25);
198 write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_25);
199 write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_25);
201 // Turn the backlight on
202 //write_ib2_reg(Reg_ib2_ctrl, read_ib2_reg(Reg_ib2_ctrl) | 0x01);
206 printf("Error: Unknown display type (ID: %lx)\n", id >> 8);
210 // Set physical framebuffer address
211 write_clcd_reg(Reg_clcd_ubas, fb_phys_addr);
212 write_clcd_reg(Reg_clcd_lbas, 0);
213 write_clcd_reg(Reg_clcd_ienb, 0);
215 // Switch power off and configure
216 write_clcd_reg(Reg_clcd_cntl,
217 ((type == PL111 && config_use_565) ? Clcd_cntl_lcdbpp16_pl111_565
218 : Clcd_cntl_lcdbpp16)
219 | Clcd_cntl_lcden | Clcd_cntl_lcdbw
220 | Clcd_cntl_lcdtft | Clcd_cntl_lcdvcomp
221 | (config_do_bgr ? Clcd_cntl_lcdbgr : 0));
224 write_clcd_reg(Reg_clcd_cntl, read_clcd_reg(Reg_clcd_cntl) | Clcd_cntl_lcdpwr);
229 static void setup_memory(void)
232 l4io_device_handle_t dh;
233 l4io_resource_handle_t hdl;
238 if (l4io_lookup_device("System Control", &dh, 0, &hdl))
240 printf("Could not get system controller space\n");
244 /* System controller -- XXX Wrong Place XXX */
245 amba_pl110_sys_base_virt
246 = l4io_request_resource_iomem(dh, &hdl);
247 if (amba_pl110_sys_base_virt == 0)
249 printf("Could not map system controller space\n");
253 if (l4io_lookup_device("AMBA PL110", &dh, 0, &hdl))
255 printf("Could not get PL110 LCD device\n");
259 amba_pl110_lcd_control_virt_base
260 = l4io_request_resource_iomem(dh, &hdl);
261 if (amba_pl110_lcd_control_virt_base == 0)
263 printf("Could not map controller space for '%s'\n", arm_lcd_get_info());
269 if ((read_sys_reg(Reg_sys_clcd) & Sys_clcd_idmask) == 0x1000)
270 is_qemu = 1; // remember if we run on qemu because of the different
271 // handling of the bpp16 mode with PL110: my hardware has
272 // 5551 mode, qemu does 565
274 if (config_request_xga && type == PL111)
277 // get some frame buffer
278 l4re_ds_t mem = l4re_util_cap_alloc();
279 if (l4_is_invalid_cap(mem))
282 if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED))
284 printf("Error allocating memory\n");
289 if (l4re_rm_attach(&fb_vaddr, fbmem_size(),
290 L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP,
291 mem, 0, L4_PAGESHIFT))
293 printf("Error getting memory\n");
297 printf("Video memory is at virtual %p (size: 0x%x Bytes)\n",
298 fb_vaddr, fbmem_size());
300 // get physical address
301 if (l4re_ds_phys(mem, 0, &fb_paddr, &phys_size)
302 || phys_size != fbmem_size())
304 printf("Getting the physical address failed or not contiguous\n");
307 printf("Physical video memory is at %p\n", (void *)fb_paddr);
310 static void *fb(void)
318 static void pl110_enable(void)
326 case PL110: s = "ARM AMBA PrimeCell PL110"; break;
327 case PL111: s = "ARM AMBA PrimeCell PL111"; break;
328 default: s = "Unknown"; break;
331 printf("Detected a '%s' device.\n", s);
333 if (!fb_vaddr || !init(fb_paddr))
335 printf("CLCD init failed!\n");
340 printf("Running on QEmu.\n");
343 static void pl110_disable(void)
346 static struct arm_lcd_ops arm_lcd_ops_pl11x = {
348 .get_fbinfo = get_fbinfo,
350 .get_video_mem_size = fbmem_size,
351 .get_info = arm_lcd_get_info,
352 .enable = pl110_enable,
353 .disable = pl110_disable,
356 arm_lcd_register(&arm_lcd_ops_pl11x);