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