• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Display Drivers
2pdk.version=1.0
3doc.type=guide
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
117struct pguide_fb {
118	int rotation;
119	struct fb_info fb;
120	u32			cmap[16];
121};
122
123static 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. */
132static int
133pguide_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 */
153static 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. */
185static 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. */
199static 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
214static 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
228static 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
294err_register_framebuffer_failed:
295err_fb_set_var_failed:
296	kfree(fb);
297err_fb_alloc_failed:
298	return ret;
299}
300
301static 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
312static 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
320static int __init pguide_fb_init(void)
321{
322	return platform_driver_register(&pguide_fb_driver);
323}
324
325static void __exit pguide_fb_exit(void)
326{
327	platform_driver_unregister(&pguide_fb_driver);
328}
329
330module_init(pguide_fb_init);
331module_exit(pguide_fb_exit);
332
333MODULE_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