blob: 0f0bba5e275059465cdd2210da08aced2a1dbdb3 [file] [log] [blame]
David Warren5f6ca4f2009-04-30 17:11:58 -07001page.title=Display Drivers
2pdk.version=1.0
3@jd:body
4
5
6
7<a name="toc"/>
8<div style="padding:10px">
9<a href="#androidDisplayDriverIntroduction">Introduction</a><br/>
10<a href="#androidDisplayDriverFunctionality">Functionality</a><br/>
11<a href="#androidDisplayDriversSourceTemplate">Implementing Your Own Driver (Driver Template)</a><br/>
12<a href="#androidDisplayDriversTroubleshooting">Troubleshooting</a><br/></div></font></div>
13
14<a name="androidDisplayDriverIntroduction"></a><h2>Introduction</h2>
15
16<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>
17<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>.
18
19
20<a name="androidDisplayDriverFunctionality"></a><h2>Functionality</h2>
21
22<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>
23<p> When <code>unlockCanvas()</code> is called, the back buffer is posted, which
24 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>
25<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>
26<ul>
27 <li>accessing the driver by calling open on <code>/dev/fb0</code></li>
28 <li>using the <code>FBIOGET_FSCREENINFO</code> and <code>FBIOGET_VSCREENINFO</code> Input / Output Control (ioctl) calls to retrieve information about the screen</li>
29 <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>
30</ul>
31<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>
32<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>
33
34
35<a name="androidDisplayDriversSourceTemplate"></a><h2>Implementing Your Own Driver (Driver Template)</h2>
36
37<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>
38<pre class="prettyprint">
39/*
40 * pguidefb.c
41 *
42 * Copyright 2007, Google Inc.
43 *
44 * This program is free software; you can redistribute it and/or modify
45 * it under the terms of the GNU General Public License version 2 as
46 * published by the Free Software Foundation.
47 */
48
49
50/*
51 * ANDROID PORTING GUIDE: FRAME BUFFER DRIVER TEMPLATE
52 *
53 * This template is designed to provide the minimum frame buffer
54 * functionality necessary for Android to display properly on a new
55 * device. The PGUIDE_FB macros are meant as pointers indicating
56 * where to implement the hardware specific code necessary for the new
57 * device. The existence of the macros is not meant to trivialize the
58 * work required, just as an indication of where the work needs to be
59 * done.
60 */
61
62#include &lt;linux/module.h&gt;
63#include &lt;linux/kernel.h&gt;
64#include &lt;linux/errno.h&gt;
65#include &lt;linux/string.h&gt;
66#include &lt;linux/slab.h&gt;
67#include &lt;linux/delay.h&gt;
68#include &lt;linux/mm.h&gt;
69#include &lt;linux/fb.h&gt;
70#include &lt;linux/init.h&gt;
71#include &lt;linux/platform_device.h&gt;
72
73
74/* Android currently only uses rgb565 in the hardware framebuffer */
75#define ANDROID_BYTES_PER_PIXEL 2
76
77/* Android will use double buffer in video if there is enough */
78#define ANDROID_NUMBER_OF_BUFFERS 2
79
80/* Modify these macros to suit the hardware */
81
82#define PGUIDE_FB_ROTATE
83 /* Do what is necessary to cause the rotation */
84
85#define PGUIDE_FB_PAN
86 /* Do what is necessary to cause the panning */
87
88#define PGUIDE_FB_PROBE_FIRST
89 /* Do any early hardware initialization */
90
91#define PGUIDE_FB_PROBE_SECOND
92 /* Do any later hardware initialization */
93
94#define PGUIDE_FB_WIDTH 320
95 /* Return the width of the screen */
96
97#define PGUIDE_FB_HEIGHT 240
98 /* Return the heighth of the screen */
99
100#define PGUIDE_FB_SCREEN_BASE 0
101 /* Return the virtual address of the start of fb memory */
102
103#define PGUIDE_FB_SMEM_START PGUIDE_FB_SCREEN_BASE
104 /* Return the physical address of the start of fb memory */
105
106#define PGUIDE_FB_REMOVE
107 /* Do any hardware shutdown */
108
109
110
111
112
113struct pguide_fb {
114 int rotation;
115 struct fb_info fb;
116 u32 cmap[16];
117};
118
119static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
120{
121 unsigned int mask = (1 << bf->length) - 1;
122
123 return (val >> (16 - bf->length) & mask) << bf->offset;
124}
125
126
127/* set the software color map. Probably doesn't need modifying. */
128static int
129pguide_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
130 unsigned int blue, unsigned int transp, struct fb_info *info)
131{
132 struct pguide_fb *fb = container_of(info, struct pguide_fb, fb);
133
134 if (regno < 16) {
135 fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
136 convert_bitfield(blue, &fb->fb.var.blue) |
137 convert_bitfield(green, &fb->fb.var.green) |
138 convert_bitfield(red, &fb->fb.var.red);
139 return 0;
140 }
141 else {
142 return 1;
143 }
144}
145
146/* check var to see if supported by this device. Probably doesn't
147 * need modifying.
148 */
149static int pguide_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
150{
151 if((var->rotate & 1) != (info->var.rotate & 1)) {
152 if((var->xres != info->var.yres) ||
153 (var->yres != info->var.xres) ||
154 (var->xres_virtual != info->var.yres) ||
155 (var->yres_virtual >
156 info->var.xres * ANDROID_NUMBER_OF_BUFFERS) ||
157 (var->yres_virtual < info->var.xres )) {
158 return -EINVAL;
159 }
160 }
161 else {
162 if((var->xres != info->var.xres) ||
163 (var->yres != info->var.yres) ||
164 (var->xres_virtual != info->var.xres) ||
165 (var->yres_virtual >
166 info->var.yres * ANDROID_NUMBER_OF_BUFFERS) ||
167 (var->yres_virtual < info->var.yres )) {
168 return -EINVAL;
169 }
170 }
171 if((var->xoffset != info->var.xoffset) ||
172 (var->bits_per_pixel != info->var.bits_per_pixel) ||
173 (var->grayscale != info->var.grayscale)) {
174 return -EINVAL;
175 }
176 return 0;
177}
178
179
180/* Handles screen rotation if device supports it. */
181static int pguide_fb_set_par(struct fb_info *info)
182{
183 struct pguide_fb *fb = container_of(info, struct pguide_fb, fb);
184 if(fb->rotation != fb->fb.var.rotate) {
185 info->fix.line_length =
186 info->var.xres * ANDROID_BYTES_PER_PIXEL;
187 fb->rotation = fb->fb.var.rotate;
188 PGUIDE_FB_ROTATE;
189 }
190 return 0;
191}
192
193
194/* Pan the display if device supports it. */
195static int pguide_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
196{
197 struct pguide_fb *fb __attribute__ ((unused))
198 = container_of(info, struct pguide_fb, fb);
199
200 /* Set the frame buffer base to something like:
201 fb->fb.fix.smem_start + fb->fb.var.xres *
202 ANDROID_BYTES_PER_PIXEL * var->yoffset
203 */
204 PGUIDE_FB_PAN;
205
206 return 0;
207}
208
209
210static struct fb_ops pguide_fb_ops = {
211 .owner = THIS_MODULE,
212 .fb_check_var = pguide_fb_check_var,
213 .fb_set_par = pguide_fb_set_par,
214 .fb_setcolreg = pguide_fb_setcolreg,
215 .fb_pan_display = pguide_fb_pan_display,
216
217 /* These are generic software based fb functions */
218 .fb_fillrect = cfb_fillrect,
219 .fb_copyarea = cfb_copyarea,
220 .fb_imageblit = cfb_imageblit,
221};
222
223
224static int pguide_fb_probe(struct platform_device *pdev)
225{
226 int ret;
227 struct pguide_fb *fb;
228 size_t framesize;
229 uint32_t width, height;
230
231 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
232 if(fb == NULL) {
233 ret = -ENOMEM;
234 goto err_fb_alloc_failed;
235 }
236 platform_set_drvdata(pdev, fb);
237
238 PGUIDE_FB_PROBE_FIRST;
239 width = PGUIDE_FB_WIDTH;
240 height = PGUIDE_FB_HEIGHT;
241
242
243 fb->fb.fbops = &pguide_fb_ops;
244
245 /* These modes are the ones currently required by Android */
246
247 fb->fb.flags = FBINFO_FLAG_DEFAULT;
248 fb->fb.pseudo_palette = fb->cmap;
249 fb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
250 fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
251 fb->fb.fix.line_length = width * ANDROID_BYTES_PER_PIXEL;
252 fb->fb.fix.accel = FB_ACCEL_NONE;
253 fb->fb.fix.ypanstep = 1;
254
255 fb->fb.var.xres = width;
256 fb->fb.var.yres = height;
257 fb->fb.var.xres_virtual = width;
258 fb->fb.var.yres_virtual = height * ANDROID_NUMBER_OF_BUFFERS;
259 fb->fb.var.bits_per_pixel = 16;
260 fb->fb.var.activate = FB_ACTIVATE_NOW;
261 fb->fb.var.height = height;
262 fb->fb.var.width = width;
263
264 fb->fb.var.red.offset = 11;
265 fb->fb.var.red.length = 5;
266 fb->fb.var.green.offset = 5;
267 fb->fb.var.green.length = 6;
268 fb->fb.var.blue.offset = 0;
269 fb->fb.var.blue.length = 5;
270
271 framesize = width * height *
272 ANDROID_BYTES_PER_PIXEL * ANDROID_NUMBER_OF_BUFFERS;
273 fb->fb.screen_base = PGUIDE_FB_SCREEN_BASE;
274 fb->fb.fix.smem_start = PGUIDE_FB_SMEM_START;
275 fb->fb.fix.smem_len = framesize;
276
277 ret = fb_set_var(&fb->fb, &fb->fb.var);
278 if(ret)
279 goto err_fb_set_var_failed;
280
281 PGUIDE_FB_PROBE_SECOND;
282
283 ret = register_framebuffer(&fb->fb);
284 if(ret)
285 goto err_register_framebuffer_failed;
286
287 return 0;
288
289
290err_register_framebuffer_failed:
291err_fb_set_var_failed:
292 kfree(fb);
293err_fb_alloc_failed:
294 return ret;
295}
296
297static int pguide_fb_remove(struct platform_device *pdev)
298{
299 struct pguide_fb *fb = platform_get_drvdata(pdev);
300
301 PGUIDE_FB_REMOVE;
302
303 kfree(fb);
304 return 0;
305}
306
307
308static struct platform_driver pguide_fb_driver = {
309 .probe = pguide_fb_probe,
310 .remove = pguide_fb_remove,
311 .driver = {
312 .name = "pguide_fb"
313 }
314};
315
316static int __init pguide_fb_init(void)
317{
318 return platform_driver_register(&pguide_fb_driver);
319}
320
321static void __exit pguide_fb_exit(void)
322{
323 platform_driver_unregister(&pguide_fb_driver);
324}
325
326module_init(pguide_fb_init);
327module_exit(pguide_fb_exit);
328
329MODULE_LICENSE("GPL");
330</pre>
331
332
333<a name="androidDisplayDriversTroubleshooting"></a><h2>Troubleshooting</h2>
334
335<p>Both of the following problems have a similar cause:</p>
336<ul>
337 <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>
338 <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>
339</ul>
340<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>
341<p>Android relies on a double buffer to smoothly render page flips (please see <a href="androidDisplayDriverFunctionality">Functionality</a> for details).</p>