Home | History | Annotate | Download | only in porting
      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 &nbsp;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 &lt;linux/module.h&gt;
     67 #include &lt;linux/kernel.h&gt;
     68 #include &lt;linux/errno.h&gt;
     69 #include &lt;linux/string.h&gt;
     70 #include &lt;linux/slab.h&gt;
     71 #include &lt;linux/delay.h&gt;
     72 #include &lt;linux/mm.h&gt;
     73 #include &lt;linux/fb.h&gt;
     74 #include &lt;linux/init.h&gt;
     75 #include &lt;linux/platform_device.h&gt;
     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