1 page.title=Display Drivers 2 pdk.version=1.0 3 doc.type=porting 4 @jd:body 5 6 7 8 <div id="qv-wrapper"> 9 <div id="qv"> 10 <h2>In this document</h2> 11 <a name="toc"/> 12 <ul> 13 <li><a href="#androidDisplayDriverFunctionality">Functionality</a></li> 14 <li><a href="#androidDisplayDriversSourceTemplate">Implementing Your Own Driver (Driver Template)</a></li> 15 <li><a href="#androidDisplayDriversTroubleshooting">Troubleshooting</a></li> 16 </ul> 17 </div> 18 </div> 19 20 <p>This section describes how the display driver functions and offers a functional template designed to help you build your own device-specific driver.</p> 21 <p>Android relies on the standard frame buffer device (<code>/dev/fb0</code> or <code>/dev/graphics/fb0</code>) and driver as described in the <code>linux/fb.h</code> kernel header file. For more information regarding the standard Linux frame buffer, please see <a href="http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.24.y.git;a=blob;f=Documentation/fb/framebuffer.txt">The Frame Buffer Device</a> at <a href="http://kernel.org">http://kernel.org</a>. 22 23 24 <a name="androidDisplayDriverFunctionality"></a><h3>Functionality</h3> 25 26 <p>In Android, every window gets implemented with an underlying Surface object, an object that gets placed on the framebuffer by SurfaceFlinger, the system-wide screen composer. Each Surface is double-buffered. The back buffer is where drawing takes place and the front buffer is used for composition. </p> 27 <p> When <code>unlockCanvas()</code> is called, the back buffer is posted, which 28 means that it gets displayed and becomes available again. Android flips the front and back buffers, ensuring a minimal amount of buffer copying and that there is always a buffer for SurfaceFlinger to use for composition (which ensures that the screen never flickers or shows artifacts).</p> 29 <p>Android makes two requirements of the driver: a linear address space of mappable memory that it can write to directly and support for the rgb_565 pixel format. A typical frame display includes:</p> 30 <ul> 31 <li>accessing the driver by calling open on <code>/dev/fb0</code></li> 32 <li>using the <code>FBIOGET_FSCREENINFO</code> and <code>FBIOGET_VSCREENINFO</code> Input / Output Control (ioctl) calls to retrieve information about the screen</li> 33 <li>using <code>FBIOPUT_VSCREENINFO</code> ioctl to attempt to create a virtual display twice the size of the physical screen and to set the pixel format to rgb_565. If this succeeds, double buffering is accomplished with video memory. </li> 34 </ul> 35 <p>When a page flip is required, Android makes another <code>FBIOPUT_VSCREENINFO</code> ioctl call with a new y-offset pointing to the other buffer in video memory. This ioctl, in turn, invokes the driver's <code>.fb_pan_display</code> function in order to do the actual flip. If there isn't sufficient video memory, regular memory is used and is just copied into the video memory when it is time do the flip. After allocating the video memory and setting the pixel format, Android uses <code>mmap()</code> to map the memory into the process's address space. All writes to the frame buffer are done through this mmaped memory.</p> 36 <p>To maintain adequate performance, framebuffer memory should be cacheable. If you use write-back, flush the cache before the frame buffer is written from DMA to the LCD. If that isn't possible, you may use write-through. As a last resort, you can also use uncached memory with the write-bugger enabled, but performance will suffer.</p> 37 38 39 <a name="androidDisplayDriversSourceTemplate"></a><h3>Implementing Your Own Driver (Driver Template)</h3> 40 41 <p>The following sample driver offers a functional example to help you build your own display driver. Modify <code>PGUIDE_FB...</code> macros as desired to match the requirements of your own device hardware.</p> 42 <pre class="prettyprint"> 43 /* 44 * pguidefb.c 45 * 46 * Copyright 2007, Google Inc. 47 * 48 * This program is free software; you can redistribute it and/or modify 49 * it under the terms of the GNU General Public License version 2 as 50 * published by the Free Software Foundation. 51 */ 52 53 54 /* 55 * ANDROID PORTING GUIDE: FRAME BUFFER DRIVER TEMPLATE 56 * 57 * This template is designed to provide the minimum frame buffer 58 * functionality necessary for Android to display properly on a new 59 * device. The PGUIDE_FB macros are meant as pointers indicating 60 * where to implement the hardware specific code necessary for the new 61 * device. The existence of the macros is not meant to trivialize the 62 * work required, just as an indication of where the work needs to be 63 * done. 64 */ 65 66 #include <linux/module.h> 67 #include <linux/kernel.h> 68 #include <linux/errno.h> 69 #include <linux/string.h> 70 #include <linux/slab.h> 71 #include <linux/delay.h> 72 #include <linux/mm.h> 73 #include <linux/fb.h> 74 #include <linux/init.h> 75 #include <linux/platform_device.h> 76 77 78 /* Android currently only uses rgb565 in the hardware framebuffer */ 79 #define ANDROID_BYTES_PER_PIXEL 2 80 81 /* Android will use double buffer in video if there is enough */ 82 #define ANDROID_NUMBER_OF_BUFFERS 2 83 84 /* Modify these macros to suit the hardware */ 85 86 #define PGUIDE_FB_ROTATE 87 /* Do what is necessary to cause the rotation */ 88 89 #define PGUIDE_FB_PAN 90 /* Do what is necessary to cause the panning */ 91 92 #define PGUIDE_FB_PROBE_FIRST 93 /* Do any early hardware initialization */ 94 95 #define PGUIDE_FB_PROBE_SECOND 96 /* Do any later hardware initialization */ 97 98 #define PGUIDE_FB_WIDTH 320 99 /* Return the width of the screen */ 100 101 #define PGUIDE_FB_HEIGHT 240 102 /* Return the heighth of the screen */ 103 104 #define PGUIDE_FB_SCREEN_BASE 0 105 /* Return the virtual address of the start of fb memory */ 106 107 #define PGUIDE_FB_SMEM_START PGUIDE_FB_SCREEN_BASE 108 /* Return the physical address of the start of fb memory */ 109 110 #define PGUIDE_FB_REMOVE 111 /* Do any hardware shutdown */ 112 113 114 115 116 117 struct pguide_fb { 118 int rotation; 119 struct fb_info fb; 120 u32 cmap[16]; 121 }; 122 123 static inline u32 convert_bitfield(int val, struct fb_bitfield *bf) 124 { 125 unsigned int mask = (1 << bf->length) - 1; 126 127 return (val >> (16 - bf->length) & mask) << bf->offset; 128 } 129 130 131 /* set the software color map. Probably doesn't need modifying. */ 132 static int 133 pguide_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, 134 unsigned int blue, unsigned int transp, struct fb_info *info) 135 { 136 struct pguide_fb *fb = container_of(info, struct pguide_fb, fb); 137 138 if (regno < 16) { 139 fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) | 140 convert_bitfield(blue, &fb->fb.var.blue) | 141 convert_bitfield(green, &fb->fb.var.green) | 142 convert_bitfield(red, &fb->fb.var.red); 143 return 0; 144 } 145 else { 146 return 1; 147 } 148 } 149 150 /* check var to see if supported by this device. Probably doesn't 151 * need modifying. 152 */ 153 static int pguide_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 154 { 155 if((var->rotate & 1) != (info->var.rotate & 1)) { 156 if((var->xres != info->var.yres) || 157 (var->yres != info->var.xres) || 158 (var->xres_virtual != info->var.yres) || 159 (var->yres_virtual > 160 info->var.xres * ANDROID_NUMBER_OF_BUFFERS) || 161 (var->yres_virtual < info->var.xres )) { 162 return -EINVAL; 163 } 164 } 165 else { 166 if((var->xres != info->var.xres) || 167 (var->yres != info->var.yres) || 168 (var->xres_virtual != info->var.xres) || 169 (var->yres_virtual > 170 info->var.yres * ANDROID_NUMBER_OF_BUFFERS) || 171 (var->yres_virtual < info->var.yres )) { 172 return -EINVAL; 173 } 174 } 175 if((var->xoffset != info->var.xoffset) || 176 (var->bits_per_pixel != info->var.bits_per_pixel) || 177 (var->grayscale != info->var.grayscale)) { 178 return -EINVAL; 179 } 180 return 0; 181 } 182 183 184 /* Handles screen rotation if device supports it. */ 185 static int pguide_fb_set_par(struct fb_info *info) 186 { 187 struct pguide_fb *fb = container_of(info, struct pguide_fb, fb); 188 if(fb->rotation != fb->fb.var.rotate) { 189 info->fix.line_length = 190 info->var.xres * ANDROID_BYTES_PER_PIXEL; 191 fb->rotation = fb->fb.var.rotate; 192 PGUIDE_FB_ROTATE; 193 } 194 return 0; 195 } 196 197 198 /* Pan the display if device supports it. */ 199 static int pguide_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 200 { 201 struct pguide_fb *fb __attribute__ ((unused)) 202 = container_of(info, struct pguide_fb, fb); 203 204 /* Set the frame buffer base to something like: 205 fb->fb.fix.smem_start + fb->fb.var.xres * 206 ANDROID_BYTES_PER_PIXEL * var->yoffset 207 */ 208 PGUIDE_FB_PAN; 209 210 return 0; 211 } 212 213 214 static struct fb_ops pguide_fb_ops = { 215 .owner = THIS_MODULE, 216 .fb_check_var = pguide_fb_check_var, 217 .fb_set_par = pguide_fb_set_par, 218 .fb_setcolreg = pguide_fb_setcolreg, 219 .fb_pan_display = pguide_fb_pan_display, 220 221 /* These are generic software based fb functions */ 222 .fb_fillrect = cfb_fillrect, 223 .fb_copyarea = cfb_copyarea, 224 .fb_imageblit = cfb_imageblit, 225 }; 226 227 228 static int pguide_fb_probe(struct platform_device *pdev) 229 { 230 int ret; 231 struct pguide_fb *fb; 232 size_t framesize; 233 uint32_t width, height; 234 235 fb = kzalloc(sizeof(*fb), GFP_KERNEL); 236 if(fb == NULL) { 237 ret = -ENOMEM; 238 goto err_fb_alloc_failed; 239 } 240 platform_set_drvdata(pdev, fb); 241 242 PGUIDE_FB_PROBE_FIRST; 243 width = PGUIDE_FB_WIDTH; 244 height = PGUIDE_FB_HEIGHT; 245 246 247 fb->fb.fbops = &pguide_fb_ops; 248 249 /* These modes are the ones currently required by Android */ 250 251 fb->fb.flags = FBINFO_FLAG_DEFAULT; 252 fb->fb.pseudo_palette = fb->cmap; 253 fb->fb.fix.type = FB_TYPE_PACKED_PIXELS; 254 fb->fb.fix.visual = FB_VISUAL_TRUECOLOR; 255 fb->fb.fix.line_length = width * ANDROID_BYTES_PER_PIXEL; 256 fb->fb.fix.accel = FB_ACCEL_NONE; 257 fb->fb.fix.ypanstep = 1; 258 259 fb->fb.var.xres = width; 260 fb->fb.var.yres = height; 261 fb->fb.var.xres_virtual = width; 262 fb->fb.var.yres_virtual = height * ANDROID_NUMBER_OF_BUFFERS; 263 fb->fb.var.bits_per_pixel = 16; 264 fb->fb.var.activate = FB_ACTIVATE_NOW; 265 fb->fb.var.height = height; 266 fb->fb.var.width = width; 267 268 fb->fb.var.red.offset = 11; 269 fb->fb.var.red.length = 5; 270 fb->fb.var.green.offset = 5; 271 fb->fb.var.green.length = 6; 272 fb->fb.var.blue.offset = 0; 273 fb->fb.var.blue.length = 5; 274 275 framesize = width * height * 276 ANDROID_BYTES_PER_PIXEL * ANDROID_NUMBER_OF_BUFFERS; 277 fb->fb.screen_base = PGUIDE_FB_SCREEN_BASE; 278 fb->fb.fix.smem_start = PGUIDE_FB_SMEM_START; 279 fb->fb.fix.smem_len = framesize; 280 281 ret = fb_set_var(&fb->fb, &fb->fb.var); 282 if(ret) 283 goto err_fb_set_var_failed; 284 285 PGUIDE_FB_PROBE_SECOND; 286 287 ret = register_framebuffer(&fb->fb); 288 if(ret) 289 goto err_register_framebuffer_failed; 290 291 return 0; 292 293 294 err_register_framebuffer_failed: 295 err_fb_set_var_failed: 296 kfree(fb); 297 err_fb_alloc_failed: 298 return ret; 299 } 300 301 static int pguide_fb_remove(struct platform_device *pdev) 302 { 303 struct pguide_fb *fb = platform_get_drvdata(pdev); 304 305 PGUIDE_FB_REMOVE; 306 307 kfree(fb); 308 return 0; 309 } 310 311 312 static struct platform_driver pguide_fb_driver = { 313 .probe = pguide_fb_probe, 314 .remove = pguide_fb_remove, 315 .driver = { 316 .name = "pguide_fb" 317 } 318 }; 319 320 static int __init pguide_fb_init(void) 321 { 322 return platform_driver_register(&pguide_fb_driver); 323 } 324 325 static void __exit pguide_fb_exit(void) 326 { 327 platform_driver_unregister(&pguide_fb_driver); 328 } 329 330 module_init(pguide_fb_init); 331 module_exit(pguide_fb_exit); 332 333 MODULE_LICENSE("GPL"); 334 </pre> 335 336 337 <a name="androidDisplayDriversTroubleshooting"></a><h3>Troubleshooting</h3> 338 339 <p>Both of the following problems have a similar cause:</p> 340 <ul> 341 <li><strong>Number keys</strong>: In the dialer application, when a number key is pressed to dial a phone number, the number doesn't display on the screen until after the next number has been pressed. </li> 342 <li><strong>Arrow keys</strong>: When an arrow key is pressed, the desired icon doesn't get highlighted. For example, if you browse through icons in the Applications menu, you might notice that icons aren't highlighted as expected when you use the arrow key to navigate between options.</li> 343 </ul> 344 <p>Both problems are caused by an incorrect implementation of the frame buffer's page flipping. Key events are captured, but the graphical interface appears to drop every other frame. </p> 345 <p>Android relies on a double buffer to smoothly render page flips (please see <a href="#androidDisplayDriverFunctionality">Functionality</a> for details).</p> 346