~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/gpu/pvr/display/omap_display.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * drivers/gpu/pvr/display/omap_display.c
 
3
 *
 
4
 * Copyright (C) 2010 Texas Instruments
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License version 2 as published by
 
8
 * the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
13
 * more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along with
 
16
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <linux/slab.h>
 
20
#include <linux/kernel.h>
 
21
#include <linux/module.h>
 
22
#include <linux/fb.h>
 
23
 
 
24
#include <plat/vrfb.h>
 
25
#include <plat/display.h>
 
26
 
 
27
/* Workaround for DEBUG macro clash in framebuffer */
 
28
#ifdef RELEASE
 
29
#include <../drivers/video/omap2/omapfb/omapfb.h>
 
30
#undef DEBUG
 
31
#else
 
32
#undef DEBUG
 
33
#include <../drivers/video/omap2/omapfb/omapfb.h>
 
34
#endif
 
35
 
 
36
#define OMAP_DISP_DRV_NAME "omap_display"
 
37
#define OMAP_DISP_FRAMEBUFFER_COUNT num_registered_fb
 
38
 
 
39
#define OMAP_DISP_PAGE_MASK (PAGE_SIZE - 1)
 
40
#define OMAP_DISP_PAGE_TRUNCATE (~OMAP_DISP_PAGE_MASK)
 
41
#define OMAP_DISP_PAGE_ROUND_UP(x) \
 
42
        (((x)+OMAP_DISP_PAGE_MASK) & OMAP_DISP_PAGE_TRUNCATE)
 
43
 
 
44
#define OMAP_DISP_IRQ_TIMEOUT 500
 
45
 
 
46
#ifdef DEBUG
 
47
#define DBG_PRINT(format, ...) printk(KERN_INFO OMAP_DISP_DRV_NAME \
 
48
        " (%s %i): " format "\n", __func__, __LINE__, ## __VA_ARGS__)
 
49
#define WRN_PRINT(format, ...) printk(KERN_WARNING OMAP_DISP_DRV_NAME \
 
50
        " (%s %i): " format "\n", __func__, __LINE__, ## __VA_ARGS__)
 
51
#define ERR_PRINT(format, ...) printk(KERN_ERR OMAP_DISP_DRV_NAME \
 
52
        " (%s %i): " format "\n", __func__, __LINE__, ## __VA_ARGS__)
 
53
#else
 
54
#define DBG_PRINT(format, ...)
 
55
#define WRN_PRINT(format, ...)
 
56
#define ERR_PRINT(format, ...)
 
57
#endif
 
58
 
 
59
#include "omap_display.h"
 
60
 
 
61
/* List for the available displays */
 
62
static struct omap_display_device *omap_display_list;
 
63
static unsigned int omap_display_number;
 
64
 
 
65
/* Workqueues for virtual display (primary, seconday)*/
 
66
static struct workqueue_struct *vdisp_wq_primary;
 
67
static struct workqueue_struct *vdisp_wq_secondary;
 
68
static struct omap_display_sync_item vdisp_sync_primary;
 
69
static struct omap_display_sync_item vdisp_sync_secondary;
 
70
 
 
71
/* Forward declarations */
 
72
static struct omap_display_buffer *create_main_buffer(
 
73
        struct omap_display_device *display);
 
74
static int display_destroy_buffer(struct omap_display_buffer *buffer);
 
75
static void vdisp_sync_handler(struct work_struct *work);
 
76
 
 
77
static int open_display(struct omap_display_device *display,
 
78
        enum omap_display_feature features)
 
79
{
 
80
        int i;
 
81
 
 
82
        DBG_PRINT("Opening display '%s'", display->name);
 
83
 
 
84
        /* TODO: Support horizontal orientation */
 
85
        if (features & ORIENTATION_HORIZONTAL) {
 
86
                DBG_PRINT("Horizontal orientation is not supported yet , "
 
87
                        "falling back to vertical orientation");
 
88
                features = ORIENTATION_VERTICAL;
 
89
        }
 
90
 
 
91
        display->features = features;
 
92
        display->reference_count++;
 
93
        for (i = 0; i < display->overlay_managers_count; i++)
 
94
                omap_dss_get_device(display->overlay_managers[i]->device);
 
95
 
 
96
        /* If the main buffer doesn't exist create it */
 
97
        if (!display->main_buffer) {
 
98
                DBG_PRINT("Main buffer doesn't exist for display '%s', create"
 
99
                        " one", display->name);
 
100
                display->main_buffer = create_main_buffer(display);
 
101
                if (!display->main_buffer) {
 
102
                        ERR_PRINT("Failed to create main buffer for '%s'",
 
103
                                display->name);
 
104
                        return 1;
 
105
                }
 
106
        }
 
107
 
 
108
        return 0;
 
109
}
 
110
 
 
111
static int close_display(struct omap_display_device *display)
 
112
{
 
113
        int err;
 
114
        int i;
 
115
 
 
116
        /* TODO: Is it the same thing to close a virtual and single display? */
 
117
        DBG_PRINT("Closing display '%s'", display->name);
 
118
 
 
119
        display->reference_count--;
 
120
        for (i = 0; i < display->overlay_managers_count; i++)
 
121
                omap_dss_put_device(display->overlay_managers[i]->device);
 
122
 
 
123
        if (display->flip_chain) {
 
124
                err = display->destroy_flip_chain(display);
 
125
                display->flip_chain = 0;
 
126
                if (err)
 
127
                        WRN_PRINT("An error happened when destroying flip "
 
128
                                "chain for '%s'", display->name);
 
129
        }
 
130
 
 
131
        return 0;
 
132
}
 
133
 
 
134
static int get_max_buffers(struct omap_display_device *display)
 
135
{
 
136
        /* TODO: If TILER is wanted to be used how do you calculate this? */
 
137
        int fb_idx;
 
138
        switch (display->id) {
 
139
        case OMAP_DISPID_PRIMARY:
 
140
                fb_idx = 0;
 
141
                break;
 
142
        case OMAP_DISPID_SECONDARY:
 
143
                fb_idx = 1;
 
144
                break;
 
145
        case OMAP_DISPID_TERTIARY:
 
146
                fb_idx = 2;
 
147
                break;
 
148
        case OMAP_DISPID_VIRTUAL:
 
149
                fb_idx = 0;
 
150
                break;
 
151
        case OMAP_DISPID_BADSTATE:
 
152
        default:
 
153
                ERR_PRINT("Unknown display id %i", display->id);
 
154
                BUG();
 
155
        }
 
156
 
 
157
        /* Use the framebuffer memory */
 
158
        if (fb_idx >= 0 && fb_idx < num_registered_fb) {
 
159
                struct fb_info *framebuffer = registered_fb[fb_idx];
 
160
                unsigned long buffer_size;
 
161
 
 
162
                /* Single buffer size */
 
163
                buffer_size = display->width * display->height *
 
164
                        display->bytes_per_pixel;
 
165
                /* Page align the buffer size, round up to the page size */
 
166
                buffer_size = OMAP_DISP_PAGE_ROUND_UP(buffer_size);
 
167
 
 
168
                return (int) (framebuffer->fix.smem_len / buffer_size);
 
169
        } else {
 
170
                ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
 
171
                        fb_idx, display->name);
 
172
                return 0;
 
173
        }
 
174
}
 
175
 
 
176
static int create_flip_chain(struct omap_display_device *display,
 
177
        unsigned int buffer_count)
 
178
{
 
179
        int fb_idx;
 
180
 
 
181
        /* TODO: What about TILER buffers */
 
182
        if (buffer_count <= 1) {
 
183
                ERR_PRINT("Flip chains with %i buffers not supported",
 
184
                        buffer_count);
 
185
                return 1;
 
186
        } else if (buffer_count > display->buffers_available) {
 
187
                ERR_PRINT("Requesting %i buffers when there is %i available"
 
188
                        " for '%s'", buffer_count, display->buffers_available,
 
189
                        display->name);
 
190
                return 1;
 
191
        } else if (display->flip_chain) {
 
192
                ERR_PRINT("Flip chain already exists for '%s'", display->name);
 
193
                return 1;
 
194
        }
 
195
 
 
196
        /* Create the flip chain with the framebuffer memory */
 
197
        switch (display->id) {
 
198
        case OMAP_DISPID_PRIMARY:
 
199
                fb_idx = 0;
 
200
                break;
 
201
        case OMAP_DISPID_SECONDARY:
 
202
                fb_idx = 1;
 
203
                break;
 
204
        case OMAP_DISPID_TERTIARY:
 
205
                fb_idx = 2;
 
206
                break;
 
207
        case OMAP_DISPID_VIRTUAL:
 
208
                fb_idx = 0;
 
209
                break;
 
210
        case OMAP_DISPID_BADSTATE:
 
211
        default:
 
212
                ERR_PRINT("Unknown display id %i", display->id);
 
213
                BUG();
 
214
        }
 
215
 
 
216
        /* Use the framebuffer memory */
 
217
        if (fb_idx >= 0 && fb_idx < num_registered_fb) {
 
218
                struct fb_info *framebuffer = registered_fb[fb_idx];
 
219
                unsigned long buffer_size;
 
220
                struct omap_display_flip_chain *flip_chain;
 
221
                int i;
 
222
 
 
223
                if (!framebuffer || !framebuffer->fix.smem_start ||
 
224
                        !framebuffer->screen_base) {
 
225
                        ERR_PRINT("Framebuffer %i doesn't seem to be "
 
226
                                "initialized", fb_idx);
 
227
                        return 1;
 
228
                }
 
229
 
 
230
                /*
 
231
                 * Check if there is enough memory in the fb for the requested
 
232
                 * buffers
 
233
                 */
 
234
                buffer_size = display->width * display->height *
 
235
                        display->bytes_per_pixel;
 
236
                /* Page align the buffer size, round up to the page size */
 
237
                buffer_size = OMAP_DISP_PAGE_ROUND_UP(buffer_size);
 
238
 
 
239
                if (buffer_size * buffer_count > framebuffer->fix.smem_len) {
 
240
                        ERR_PRINT("Not enough memory to allocate %i buffers "
 
241
                                "(%lu bytes each), memory available %lu for "
 
242
                                "display '%s'", buffer_count, buffer_size,
 
243
                                (unsigned long)framebuffer->fix.smem_len,
 
244
                                display->name);
 
245
                        return 1;
 
246
                }
 
247
 
 
248
                flip_chain = kzalloc(sizeof(*flip_chain), GFP_KERNEL);
 
249
 
 
250
                if (!flip_chain) {
 
251
                        ERR_PRINT("Out of memory");
 
252
                        return 1;
 
253
                }
 
254
 
 
255
                for (i = 0; i < buffer_count; i++) {
 
256
                        struct omap_display_buffer *buffer;
 
257
 
 
258
                        /*
 
259
                         * Reuse the main buffer as the first buffer in the
 
260
                         * flip chain
 
261
                         */
 
262
                        if (i == 0) {
 
263
                                buffer = display->main_buffer;
 
264
                                flip_chain->buffers[i] = buffer;
 
265
                                DBG_PRINT("Flip chain buffer %i has address "
 
266
                                        "%lx for display '%s'", i,
 
267
                                        buffer->physical_addr, display->name);
 
268
                                continue;
 
269
                        }
 
270
 
 
271
                        buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
 
272
 
 
273
                        if (!buffer) {
 
274
                                /*
 
275
                                 * FIXME: If one buffer allocation fails,
 
276
                                 * deallocate flip chain and buffers
 
277
                                 */
 
278
                                ERR_PRINT("Out of memory");
 
279
                                return 1;
 
280
                        }
 
281
 
 
282
                        buffer->physical_addr = framebuffer->fix.smem_start +
 
283
                                (buffer_size * i);
 
284
                        buffer->virtual_addr =
 
285
                                (unsigned long) framebuffer->screen_base +
 
286
                                (buffer_size * i);
 
287
                        buffer->size = buffer_size;
 
288
                        buffer->display = display;
 
289
                        flip_chain->buffers[i] = buffer;
 
290
 
 
291
                        DBG_PRINT("Flip chain buffer %i has address %lx for"
 
292
                                " display '%s'", i, buffer->physical_addr,
 
293
                                display->name);
 
294
                }
 
295
 
 
296
                display->flip_chain = flip_chain;
 
297
                return 0;
 
298
        } else {
 
299
                ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
 
300
                        fb_idx, display->name);
 
301
                return 1;
 
302
        }
 
303
 
 
304
        return 0;
 
305
}
 
306
 
 
307
static int destroy_flip_chain(struct omap_display_device *display)
 
308
{
 
309
        int i;
 
310
        int err;
 
311
 
 
312
        if (!display->flip_chain) {
 
313
                DBG_PRINT("No flip chain to destroy for '%s'", display->name);
 
314
                return 0;
 
315
        }
 
316
 
 
317
        for (i = 0; i < display->flip_chain->buffer_count; i++) {
 
318
                struct omap_display_buffer *buffer =
 
319
                        display->flip_chain->buffers[i];
 
320
                /* If buffer is main buffer don't touch it */
 
321
                if (display->main_buffer == buffer)
 
322
                        continue;
 
323
 
 
324
                err = display_destroy_buffer(buffer);
 
325
                if (err) {
 
326
                        ERR_PRINT("Error destroying buffer in flip chain for"
 
327
                        " '%s'", display->name);
 
328
                        return 1;
 
329
                }
 
330
        }
 
331
 
 
332
        DBG_PRINT("Destroying flip chain for '%s'", display->name);
 
333
        kfree(display->flip_chain);
 
334
        display->flip_chain = 0;
 
335
 
 
336
        return 0;
 
337
}
 
338
 
 
339
static int rotate_display(struct omap_display_device *display,
 
340
        unsigned int rotation)
 
341
{
 
342
        ERR_PRINT("Not supported yet");
 
343
        return 1;
 
344
}
 
345
 
 
346
static int display_destroy_buffer(struct omap_display_buffer *buffer)
 
347
{
 
348
        kfree(buffer);
 
349
        return 0;
 
350
}
 
351
 
 
352
static int present_buffer_virtual(struct omap_display_buffer *buffer)
 
353
{
 
354
        /*
 
355
         * TODO: Support for ORIENTATION_VERTICAL is in place,
 
356
         * ORIENTATION_HORIZONTAL is missing
 
357
         */
 
358
        struct omap_display_device *display_virtual = buffer->display;
 
359
        struct omap_display_device *display_primary;
 
360
        struct omap_display_device *display_secondary;
 
361
        struct omap_display_buffer temp_buffer;
 
362
        unsigned int buffer_offset;
 
363
 
 
364
        if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
 
365
                ERR_PRINT("Not a virtual display");
 
366
                BUG();
 
367
        }
 
368
 
 
369
        display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
 
370
        display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
 
371
        /*
 
372
         * Calculate offset without page alignment round up otherwise second
 
373
         * display may see incorrect data
 
374
         */
 
375
        buffer_offset = display_primary->height * display_virtual->byte_stride;
 
376
 
 
377
        /* The first buffer will be the base */
 
378
        temp_buffer.physical_addr = buffer->physical_addr;
 
379
        temp_buffer.virtual_addr = buffer->virtual_addr;
 
380
        temp_buffer.size = buffer->size >> 1;
 
381
 
 
382
        if (display_virtual->features & ORIENTATION_INVERT) {
 
383
                /* Secondary display has the base */
 
384
                temp_buffer.display = display_secondary;
 
385
                display_secondary->present_buffer(&temp_buffer);
 
386
        } else {
 
387
                /* Primary display has the base */
 
388
                temp_buffer.display = display_primary;
 
389
                display_primary->present_buffer(&temp_buffer);
 
390
        }
 
391
 
 
392
        /* Remaining display will show the rest */
 
393
        temp_buffer.physical_addr = buffer->physical_addr + buffer_offset;
 
394
        temp_buffer.virtual_addr = buffer->virtual_addr + buffer_offset;
 
395
 
 
396
        if (display_virtual->features & ORIENTATION_INVERT) {
 
397
                temp_buffer.display = display_primary;
 
398
                display_primary->present_buffer(&temp_buffer);
 
399
        } else {
 
400
                temp_buffer.display = display_secondary;
 
401
                display_secondary->present_buffer(&temp_buffer);
 
402
        }
 
403
 
 
404
        return 0;
 
405
}
 
406
 
 
407
static int present_buffer(struct omap_display_buffer *buffer)
 
408
{
 
409
        struct omap_display_device *display = buffer->display;
 
410
        struct fb_info *framebuffer;
 
411
        struct omapfb_info *ofbi;
 
412
        struct omapfb2_device *fbdev;
 
413
        int i;
 
414
        int fb_idx;
 
415
 
 
416
        switch (display->id) {
 
417
        case OMAP_DISPID_PRIMARY:
 
418
                fb_idx = 0;
 
419
                break;
 
420
        case OMAP_DISPID_SECONDARY:
 
421
                fb_idx = 1;
 
422
                break;
 
423
        case OMAP_DISPID_TERTIARY:
 
424
                fb_idx = 2;
 
425
                break;
 
426
        case OMAP_DISPID_VIRTUAL:
 
427
        case OMAP_DISPID_BADSTATE:
 
428
        default:
 
429
                ERR_PRINT("Unable to handle display %i", display->id);
 
430
                BUG();
 
431
        }
 
432
 
 
433
        if (fb_idx < 0 || fb_idx >= num_registered_fb) {
 
434
                ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
 
435
                        fb_idx, display->name);
 
436
                return 1;
 
437
        }
 
438
 
 
439
        framebuffer = registered_fb[fb_idx];
 
440
        ofbi = FB2OFB(framebuffer);
 
441
        fbdev = ofbi->fbdev;
 
442
 
 
443
        omapfb_lock(fbdev);
 
444
 
 
445
        /* Get the overlays attached to the framebuffer */
 
446
        for (i = 0; i < ofbi->num_overlays ; i++) {
 
447
                struct omap_dss_device *display = NULL;
 
448
                struct omap_dss_driver *driver = NULL;
 
449
                struct omap_overlay_manager *manager;
 
450
                struct omap_overlay *overlay;
 
451
                struct omap_overlay_info overlay_info;
 
452
 
 
453
                overlay = ofbi->overlays[i];
 
454
                manager = overlay->manager;
 
455
                overlay->get_overlay_info(overlay, &overlay_info);
 
456
 
 
457
                overlay_info.paddr = buffer->physical_addr;
 
458
                overlay_info.vaddr = (void *) buffer->virtual_addr;
 
459
                overlay->set_overlay_info(overlay, &overlay_info);
 
460
 
 
461
                if (manager) {
 
462
                        manager->apply(manager);
 
463
                        display = manager->device;
 
464
                        driver = display ? display->driver : NULL;
 
465
                }
 
466
 
 
467
                if (dss_ovl_manually_updated(overlay)) {
 
468
                        if (driver->sched_update)
 
469
                                driver->sched_update(display, 0, 0,
 
470
                                                        overlay_info.width,
 
471
                                                        overlay_info.height);
 
472
                        else if (driver->update)
 
473
                                driver->update(display, 0, 0,
 
474
                                                        overlay_info.width,
 
475
                                                        overlay_info.height);
 
476
                }
 
477
        }
 
478
 
 
479
        omapfb_unlock(fbdev);
 
480
 
 
481
 
 
482
        return 0;
 
483
}
 
484
 
 
485
static int present_buffer_sync(struct omap_display_buffer *buffer)
 
486
{
 
487
        /* TODO: Cloning may tear with this implementation */
 
488
        struct omap_display_device *display = buffer->display;
 
489
        struct fb_info *framebuffer;
 
490
        struct omap_dss_device *dss_device;
 
491
        struct omap_dss_driver *driver;
 
492
        struct omap_overlay_manager *manager;
 
493
        int fb_idx;
 
494
        int err = 1;
 
495
 
 
496
        switch (display->id) {
 
497
        case OMAP_DISPID_PRIMARY:
 
498
                fb_idx = 0;
 
499
                break;
 
500
        case OMAP_DISPID_SECONDARY:
 
501
                fb_idx = 1;
 
502
                break;
 
503
        case OMAP_DISPID_TERTIARY:
 
504
                fb_idx = 2;
 
505
                break;
 
506
        case OMAP_DISPID_VIRTUAL:
 
507
        case OMAP_DISPID_BADSTATE:
 
508
        default:
 
509
                ERR_PRINT("Unable to handle display %i", display->id);
 
510
                BUG();
 
511
        }
 
512
 
 
513
        if (fb_idx < 0 || fb_idx >= num_registered_fb) {
 
514
                ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
 
515
                        fb_idx, display->name);
 
516
                return 1;
 
517
        }
 
518
 
 
519
        framebuffer = registered_fb[fb_idx];
 
520
        dss_device = fb2display(framebuffer);
 
521
 
 
522
        if (!dss_device) {
 
523
                WRN_PRINT("No DSS device to sync with display '%s'!",
 
524
                                display->name);
 
525
                return 1;
 
526
        }
 
527
 
 
528
        driver = dss_device->driver;
 
529
        manager = dss_device->manager;
 
530
 
 
531
        if (driver && driver->sync &&
 
532
                driver->get_update_mode(dss_device) ==
 
533
                OMAP_DSS_UPDATE_MANUAL) {
 
534
                err = driver->sync(dss_device);
 
535
                err |= display->present_buffer(buffer);
 
536
        } else if (manager && manager->wait_for_vsync) {
 
537
                err = manager->wait_for_vsync(manager);
 
538
                err |= display->present_buffer(buffer);
 
539
        }
 
540
 
 
541
        if (err)
 
542
                WRN_PRINT("Unable to sync with display '%s'!", display->name);
 
543
 
 
544
        return err;
 
545
}
 
546
 
 
547
static void vdisp_sync_handler(struct work_struct *work)
 
548
{
 
549
        struct omap_display_sync_item *sync_item =
 
550
                (struct omap_display_sync_item *) work;
 
551
        struct omap_display_device *display = sync_item->buffer->display;
 
552
        display->present_buffer_sync(sync_item->buffer);
 
553
}
 
554
 
 
555
static int present_buffer_sync_virtual(struct omap_display_buffer *buffer)
 
556
{
 
557
        /*
 
558
         * TODO: Support for ORIENTATION_VERTICAL is in place,
 
559
         * ORIENTATION_HORIZONTAL is missing. Some code can be reduced here,
 
560
         * it will be simplified in the future.
 
561
         */
 
562
        struct omap_display_device *display_virtual = buffer->display;
 
563
        struct omap_display_device *display_primary;
 
564
        struct omap_display_device *display_secondary;
 
565
        struct omap_display_buffer temp_buffer_top;
 
566
        struct omap_display_buffer temp_buffer_bottom;
 
567
        unsigned int buffer_offset;
 
568
 
 
569
        if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
 
570
                ERR_PRINT("Not a virtual display");
 
571
                BUG();
 
572
        }
 
573
 
 
574
        display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
 
575
        display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
 
576
        /*
 
577
         * Calculate offset without page alignment round up otherwise second
 
578
         * display may see incorrect data
 
579
         */
 
580
        buffer_offset = display_primary->height * display_virtual->byte_stride;
 
581
 
 
582
        /* The first buffer will be the top */
 
583
        temp_buffer_top.physical_addr = buffer->physical_addr;
 
584
        temp_buffer_top.virtual_addr = buffer->virtual_addr;
 
585
        temp_buffer_top.size = buffer->size >> 1;
 
586
        /* Then the bottom */
 
587
        temp_buffer_bottom.physical_addr = buffer->physical_addr +
 
588
                buffer_offset;
 
589
        temp_buffer_bottom.virtual_addr = buffer->virtual_addr + buffer_offset;
 
590
        temp_buffer_bottom.size = buffer->size >> 1;
 
591
 
 
592
        if (display_virtual->features & ORIENTATION_INVERT) {
 
593
                /* Secondary display has the base */
 
594
                temp_buffer_top.display = display_secondary;
 
595
                temp_buffer_bottom.display = display_primary;
 
596
                vdisp_sync_primary.buffer = &temp_buffer_bottom;
 
597
                vdisp_sync_secondary.buffer = &temp_buffer_top;
 
598
        } else {
 
599
                /* Primary display has the base */
 
600
                temp_buffer_top.display = display_primary;
 
601
                temp_buffer_bottom.display = display_secondary;
 
602
                vdisp_sync_primary.buffer = &temp_buffer_top;
 
603
                vdisp_sync_secondary.buffer = &temp_buffer_bottom;
 
604
        }
 
605
 
 
606
        /* Launch the workqueues for each display to present independently */
 
607
        queue_work(vdisp_wq_primary,
 
608
                (struct work_struct *)&vdisp_sync_primary);
 
609
        queue_work(vdisp_wq_secondary,
 
610
                (struct work_struct *)&vdisp_sync_secondary);
 
611
 
 
612
        /* Wait until each display sync and present */
 
613
        flush_workqueue(vdisp_wq_primary);
 
614
        flush_workqueue(vdisp_wq_secondary);
 
615
 
 
616
        return 0;
 
617
}
 
618
 
 
619
static int display_sync(struct omap_display_device *display)
 
620
{
 
621
        /* TODO: Synchronize properly with multiple managers */
 
622
        struct fb_info *framebuffer;
 
623
        struct omap_dss_device *dss_device;
 
624
        struct omap_dss_driver *driver;
 
625
        struct omap_overlay_manager *manager;
 
626
        int fb_idx;
 
627
        int err = 1;
 
628
 
 
629
        switch (display->id) {
 
630
        case OMAP_DISPID_PRIMARY:
 
631
                fb_idx = 0;
 
632
                break;
 
633
        case OMAP_DISPID_SECONDARY:
 
634
                fb_idx = 1;
 
635
                break;
 
636
        case OMAP_DISPID_TERTIARY:
 
637
                fb_idx = 2;
 
638
                break;
 
639
        case OMAP_DISPID_VIRTUAL:
 
640
        case OMAP_DISPID_BADSTATE:
 
641
        default:
 
642
                ERR_PRINT("Unable to handle display %i", display->id);
 
643
                BUG();
 
644
        }
 
645
 
 
646
        if (fb_idx < 0 || fb_idx >= num_registered_fb) {
 
647
                ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
 
648
                        fb_idx, display->name);
 
649
                return 1;
 
650
        }
 
651
 
 
652
        framebuffer = registered_fb[fb_idx];
 
653
        dss_device = fb2display(framebuffer);
 
654
 
 
655
        if (!dss_device) {
 
656
                WRN_PRINT("No DSS device to sync with display '%s'!",
 
657
                                display->name);
 
658
                return 1;
 
659
        }
 
660
 
 
661
        driver = dss_device->driver;
 
662
        manager = dss_device->manager;
 
663
 
 
664
        if (driver && driver->sync &&
 
665
                driver->get_update_mode(dss_device) == OMAP_DSS_UPDATE_MANUAL)
 
666
                err = driver->sync(dss_device);
 
667
        else if (manager && manager->wait_for_vsync)
 
668
                err = manager->wait_for_vsync(manager);
 
669
 
 
670
        if (err)
 
671
                WRN_PRINT("Unable to sync with display '%s'!", display->name);
 
672
 
 
673
        return err;
 
674
}
 
675
 
 
676
static int display_sync_virtual(struct omap_display_device *display_virtual)
 
677
{
 
678
        /*
 
679
         * XXX: This function only waits for the primary display it should
 
680
         * be adapted to the customer needs since waiting for the primary
 
681
         * AND the secondary display may take too long for a single sync.
 
682
         */
 
683
        struct omap_display_device *display_primary;
 
684
 
 
685
        if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
 
686
                ERR_PRINT("Not a virtual display");
 
687
                BUG();
 
688
        }
 
689
 
 
690
        display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
 
691
        return display_primary->sync(display_primary);
 
692
}
 
693
 
 
694
static struct omap_display_buffer *create_main_buffer(
 
695
        struct omap_display_device *display)
 
696
{
 
697
        int fb_idx;
 
698
        switch (display->id) {
 
699
        case OMAP_DISPID_PRIMARY:
 
700
                fb_idx = 0;
 
701
                break;
 
702
        case OMAP_DISPID_SECONDARY:
 
703
                fb_idx = 1;
 
704
                break;
 
705
        case OMAP_DISPID_TERTIARY:
 
706
                fb_idx = 2;
 
707
                break;
 
708
        case OMAP_DISPID_VIRTUAL:
 
709
                /* Use fb0 for virtual display */
 
710
                fb_idx = 0;
 
711
                break;
 
712
        case OMAP_DISPID_BADSTATE:
 
713
        default:
 
714
                ERR_PRINT("Unknown display id %i", display->id);
 
715
                BUG();
 
716
        }
 
717
 
 
718
        /* Use the framebuffer memory */
 
719
        if (fb_idx >= 0 && fb_idx < num_registered_fb) {
 
720
                struct fb_info *framebuffer = registered_fb[fb_idx];
 
721
                unsigned long buffer_size;
 
722
                struct omap_display_buffer *buffer;
 
723
 
 
724
                if (!framebuffer || !framebuffer->fix.smem_start ||
 
725
                        !framebuffer->screen_base) {
 
726
                        ERR_PRINT("Framebuffer %i doesn't seem to be "
 
727
                                "initialized", fb_idx);
 
728
                        return NULL;
 
729
                }
 
730
 
 
731
                /*
 
732
                 * Check if there is enough memory in the fb for the
 
733
                 * main buffer
 
734
                 */
 
735
                buffer_size = display->width * display->height *
 
736
                        display->bytes_per_pixel;
 
737
                /* Page align the buffer size */
 
738
                buffer_size = OMAP_DISP_PAGE_ROUND_UP(buffer_size);
 
739
 
 
740
                if (buffer_size > framebuffer->fix.smem_len) {
 
741
                        ERR_PRINT("Main buffer needs %lu bytes while the "
 
742
                                "framebuffer %i has only %lu bytes for display"
 
743
                                " '%s'", buffer_size, fb_idx,
 
744
                                (unsigned long)framebuffer->fix.smem_len,
 
745
                                display->name);
 
746
                        return NULL;
 
747
                }
 
748
 
 
749
                buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
 
750
 
 
751
                if (!buffer) {
 
752
                        ERR_PRINT("Out of memory");
 
753
                        return NULL;
 
754
                }
 
755
 
 
756
                /* Use base addresses reported by the framebuffer */
 
757
                buffer->physical_addr = framebuffer->fix.smem_start;
 
758
                buffer->virtual_addr =
 
759
                        (unsigned long) framebuffer->screen_base;
 
760
                buffer->size = buffer_size;
 
761
                buffer->display = display;
 
762
 
 
763
                DBG_PRINT("Created main buffer %lx for display '%s'",
 
764
                        buffer->physical_addr, display->name);
 
765
 
 
766
                return buffer;
 
767
        } else {
 
768
                ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
 
769
                        fb_idx, display->name);
 
770
                return NULL;
 
771
        }
 
772
}
 
773
 
 
774
static int populate_display_info(struct omap_display_device *display,
 
775
        struct omap_overlay_manager *overlay_manager)
 
776
{
 
777
        struct omap_dss_device *dss_device = overlay_manager->device;
 
778
        u16 xres;
 
779
        u16 yres;
 
780
        int i;
 
781
 
 
782
        if (!strcmp(dss_device->name, "lcd")) {
 
783
                display->id = OMAP_DISPID_PRIMARY;
 
784
                display->name = "primary";
 
785
        } else if (!strcmp(dss_device->name, "lcd2")) {
 
786
                display->id = OMAP_DISPID_SECONDARY;
 
787
                display->name = "secondary";
 
788
        } else if (!strcmp(dss_device->name, "hdmi")) {
 
789
                display->id = OMAP_DISPID_TERTIARY;
 
790
                display->name = "tertiary";
 
791
        } else {
 
792
                ERR_PRINT("Display id '%s' not supported", dss_device->name);
 
793
                return 1;
 
794
        }
 
795
 
 
796
        dss_device->driver->get_resolution(dss_device, &xres, &yres);
 
797
        if (xres == 0 || yres == 0) {
 
798
                ERR_PRINT("Unable to handle display '%s' with width %i "
 
799
                "and height %i", dss_device->name, xres, yres);
 
800
                return 1;
 
801
        }
 
802
 
 
803
        display->width = xres;
 
804
        display->height = yres;
 
805
 
 
806
        display->bits_per_pixel =
 
807
                dss_device->driver->get_recommended_bpp(dss_device);
 
808
        switch (display->bits_per_pixel) {
 
809
        case 16:
 
810
                /*
 
811
                 * TODO: Asume RGB_565, maybe need to double check in
 
812
                 * the DSS if this is true
 
813
                 */
 
814
                display->pixel_format = RGB_565;
 
815
                display->bytes_per_pixel = 2;
 
816
                break;
 
817
        case 24: /* 24 bits are encapsulated with 32 bits */
 
818
        case 32:
 
819
                /*
 
820
                 * TODO: Asume ARGB_8888, maybe need to double check in
 
821
                 * the DSS if this is true
 
822
                 */
 
823
                display->pixel_format = ARGB_8888;
 
824
                display->bytes_per_pixel = 4;
 
825
                break;
 
826
        default:
 
827
                ERR_PRINT("Unable to handle %i bpp", display->bits_per_pixel);
 
828
                return 1;
 
829
        }
 
830
 
 
831
        display->byte_stride = display->bytes_per_pixel * display->width;
 
832
        display->rotation = OMAP_DSS_ROT_0; /* Asume rotation 0 degrees */
 
833
        display->main_buffer = 0;
 
834
        display->flip_chain = 0;
 
835
 
 
836
        /* Add the manager to the list */
 
837
        for (i = 0; i < OMAP_DISP_MAX_MANAGERS; i++)
 
838
                display->overlay_managers[i] = 0;
 
839
 
 
840
        display->overlay_managers[0] = overlay_manager;
 
841
        display->overlay_managers_count = 1;
 
842
 
 
843
        /* Assign function pointers for display operations */
 
844
        display->open = open_display;
 
845
        display->close = close_display;
 
846
        display->create_flip_chain = create_flip_chain;
 
847
        display->destroy_flip_chain = destroy_flip_chain;
 
848
        display->rotate = rotate_display;
 
849
        display->present_buffer = present_buffer;
 
850
        display->sync = display_sync;
 
851
        display->present_buffer_sync = present_buffer_sync;
 
852
 
 
853
        display->main_buffer = create_main_buffer(display);
 
854
        if (!display->main_buffer)
 
855
                WRN_PRINT("Failed to create main buffer for '%s'",
 
856
                        display->name);
 
857
 
 
858
        display->buffers_available = get_max_buffers(display);
 
859
 
 
860
        /* Just print some display info */
 
861
        DBG_PRINT("Found display '%s-%s' (%i,%i) %i bpp (%i bytes per pixel)"
 
862
                " rotation %i", display->name, dss_device->name,
 
863
                display->width, display->height, display->bits_per_pixel,
 
864
                display->bytes_per_pixel, display->rotation);
 
865
 
 
866
        return 0;
 
867
}
 
868
 
 
869
static int populate_virtual_display_info(struct omap_display_device *display)
 
870
{
 
871
        struct omap_display_device *display_primary ;
 
872
        struct omap_display_device *display_secondary;
 
873
        int i;
 
874
 
 
875
        display->id = OMAP_DISPID_VIRTUAL;
 
876
        display->name = "virtual";
 
877
 
 
878
        display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
 
879
        display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
 
880
 
 
881
        if (!display_primary) {
 
882
                ERR_PRINT("Primary display doesn't exist");
 
883
                return 1;
 
884
        } else if (!display_secondary) {
 
885
                ERR_PRINT("Secondary display doesn't exist");
 
886
                return 1;
 
887
        }
 
888
 
 
889
        /* Combine primary and secondary display resolutions */
 
890
        if (display_primary->width != display_secondary->width ||
 
891
                display_primary->height != display_secondary->height) {
 
892
                ERR_PRINT("Primary and seconday displays resolution are not"
 
893
                        " the same");
 
894
                return 1;
 
895
        }
 
896
 
 
897
        /*
 
898
         * TODO: Here it is hardcoded the resolution asumming a vertical
 
899
         * virtual config, what about horizontal?
 
900
         */
 
901
        display->width = display_primary->width;
 
902
        display->height = display_primary->height * 2;
 
903
 
 
904
        if (display_primary->bits_per_pixel !=
 
905
                display_secondary->bits_per_pixel) {
 
906
                ERR_PRINT("Primary and seconday displays format are"
 
907
                        " not the same");
 
908
                return 1;
 
909
        }
 
910
 
 
911
        display->bits_per_pixel = display_primary->bits_per_pixel;
 
912
        switch (display->bits_per_pixel) {
 
913
        case 16:
 
914
                /*
 
915
                 * TODO: Asume RGB_565, maybe need to double check in
 
916
                 * the DSS if this is true
 
917
                 */
 
918
                display->pixel_format = RGB_565;
 
919
                display->bytes_per_pixel = 2;
 
920
                break;
 
921
        case 24: /* 24 bits are encapsulated with 32 bits */
 
922
        case 32:
 
923
                /*
 
924
                 * TODO: Asume ARGB_8888, maybe need to double check in
 
925
                 * the DSS if this is true
 
926
                 */
 
927
                display->pixel_format = ARGB_8888;
 
928
                display->bytes_per_pixel = 4;
 
929
                break;
 
930
        default:
 
931
                ERR_PRINT("Unable to handle %i bpp",
 
932
                        display->bits_per_pixel);
 
933
                return 1;
 
934
        }
 
935
 
 
936
        /* TODO: Asumming a vertical virtual config too for stride */
 
937
        display->byte_stride = display->bytes_per_pixel * display->width;
 
938
        display->rotation = OMAP_DSS_ROT_0; /* Asume rotation 0 degrees */
 
939
        display->main_buffer = 0;
 
940
        display->flip_chain = 0;
 
941
 
 
942
        /* Add the primary and secondary overlay managers */
 
943
        for (i = 0; i < OMAP_DISP_MAX_MANAGERS; i++)
 
944
                display->overlay_managers[i] = 0;
 
945
 
 
946
        display->overlay_managers[0] = display_primary->overlay_managers[0];
 
947
        display->overlay_managers[1] = display_secondary->overlay_managers[0];
 
948
        display->overlay_managers_count = 2;
 
949
 
 
950
        /* Assign function pointers for display operations */
 
951
        display->open = open_display;
 
952
        display->close = close_display;
 
953
        display->create_flip_chain = create_flip_chain;
 
954
        display->destroy_flip_chain = destroy_flip_chain;
 
955
        display->rotate = rotate_display;
 
956
        display->present_buffer = present_buffer_virtual;
 
957
        display->sync = display_sync_virtual;
 
958
        display->present_buffer_sync = present_buffer_sync_virtual;
 
959
 
 
960
        display->main_buffer = create_main_buffer(display);
 
961
        if (!display->main_buffer)
 
962
                WRN_PRINT("Failed to create main buffer for '%s'",
 
963
                        display->name);
 
964
 
 
965
        display->buffers_available = get_max_buffers(display);
 
966
 
 
967
        /* Just print some display info */
 
968
        DBG_PRINT("Found display '%s' (%i,%i) %i bpp (%i bytes per pixel)"
 
969
                " rotation %i", display->name, display->width, display->height,
 
970
                display->bits_per_pixel, display->bytes_per_pixel,
 
971
                display->rotation);
 
972
 
 
973
        return 0;
 
974
}
 
975
 
 
976
static int create_display_list(void)
 
977
{
 
978
        int i;
 
979
        struct omap_display_device *display;
 
980
 
 
981
        /* Query number of possible displays available first */
 
982
        omap_display_number = omap_dss_get_num_overlay_managers();
 
983
        /* For virtual display */
 
984
        omap_display_number++;
 
985
 
 
986
        /* Allocate custom display list */
 
987
        omap_display_list = kzalloc(
 
988
                sizeof(*display) * omap_display_number, GFP_KERNEL);
 
989
 
 
990
        if (!omap_display_list) {
 
991
                ERR_PRINT("Out of memory");
 
992
                return 1;
 
993
        }
 
994
 
 
995
        /* Populate each display info */
 
996
        for (i = 0; i < omap_display_number - 1; i++) {
 
997
                struct omap_overlay_manager *overlay_manager =
 
998
                        omap_dss_get_overlay_manager(i);
 
999
                display = &omap_display_list[i];
 
1000
                if (!overlay_manager->device) {
 
1001
                        WRN_PRINT("Display '%s' doesn't have a dss device "
 
1002
                                "attached to it, ignoring",
 
1003
                                overlay_manager->name);
 
1004
                        display->id = OMAP_DISPID_BADSTATE;
 
1005
                        continue;
 
1006
                }
 
1007
                if (populate_display_info(display, overlay_manager)) {
 
1008
                        ERR_PRINT("Error populating display %i info with "
 
1009
                                "manager '%s'", i,
 
1010
                                overlay_manager->device->name);
 
1011
                        display->id = OMAP_DISPID_BADSTATE;
 
1012
                        continue;
 
1013
                }
 
1014
        }
 
1015
 
 
1016
        /* Populate virtual display */
 
1017
        display = &omap_display_list[omap_display_number - 1];
 
1018
        if (populate_virtual_display_info(display)) {
 
1019
                ERR_PRINT("Error populating virtual display info");
 
1020
                display->id = OMAP_DISPID_BADSTATE;
 
1021
        }
 
1022
 
 
1023
        return 0;
 
1024
}
 
1025
 
 
1026
struct omap_display_device *omap_display_get(enum omap_display_id id)
 
1027
{
 
1028
        int i;
 
1029
        struct omap_display_device *display;
 
1030
 
 
1031
        if (id == OMAP_DISPID_BADSTATE) {
 
1032
                ERR_PRINT("Oops.. user must never request a bad display");
 
1033
                BUG();
 
1034
        }
 
1035
 
 
1036
        for (i = 0; i < omap_display_number; i++) {
 
1037
                display = &omap_display_list[i];
 
1038
                if (display->id == id)
 
1039
                        return display;
 
1040
        }
 
1041
 
 
1042
        ERR_PRINT("Unknown display %i requested", id);
 
1043
        return 0;
 
1044
}
 
1045
EXPORT_SYMBOL(omap_display_get);
 
1046
 
 
1047
int omap_display_count(void)
 
1048
{
 
1049
        return omap_display_number;
 
1050
}
 
1051
EXPORT_SYMBOL(omap_display_count);
 
1052
 
 
1053
int omap_display_initialize(void)
 
1054
{
 
1055
        /*
 
1056
         * TODO: Is there a better way to check if list is already created?
 
1057
         */
 
1058
        if (!omap_display_list) {
 
1059
                DBG_PRINT("Initializing driver");
 
1060
                if (create_display_list()) {
 
1061
                        ERR_PRINT("Error loading driver");
 
1062
                        return 1;
 
1063
                }
 
1064
        }
 
1065
 
 
1066
        vdisp_wq_primary = __create_workqueue("vdisp_wq_primary", 1, 1, 1);
 
1067
        vdisp_wq_secondary = __create_workqueue("vdisp_wq_secondary", 1, 1, 1);
 
1068
        INIT_WORK((struct work_struct *)&vdisp_sync_primary,
 
1069
                vdisp_sync_handler);
 
1070
        INIT_WORK((struct work_struct *)&vdisp_sync_secondary,
 
1071
                vdisp_sync_handler);
 
1072
 
 
1073
        return 0;
 
1074
}
 
1075
EXPORT_SYMBOL(omap_display_initialize);
 
1076
 
 
1077
int omap_display_deinitialize(void)
 
1078
{
 
1079
        int i;
 
1080
        int err = 0;
 
1081
        DBG_PRINT("Driver exiting");
 
1082
 
 
1083
        for (i = 0; i < omap_display_number; i++) {
 
1084
                struct omap_display_device *display = &omap_display_list[i];
 
1085
 
 
1086
                if (!display)
 
1087
                        continue;
 
1088
 
 
1089
                if (display->main_buffer) {
 
1090
                        err = display_destroy_buffer(display->main_buffer);
 
1091
                        display->main_buffer = 0;
 
1092
                        if (err)
 
1093
                                WRN_PRINT("An error happened when destroying "
 
1094
                                        "main buffer for '%s'", display->name);
 
1095
                }
 
1096
 
 
1097
                err = display->close(display);
 
1098
 
 
1099
                if (err)
 
1100
                        ERR_PRINT("Unable to close display '%s'",
 
1101
                                display->name);
 
1102
        }
 
1103
 
 
1104
        kfree(omap_display_list);
 
1105
        omap_display_list = 0;
 
1106
 
 
1107
        destroy_workqueue(vdisp_wq_primary);
 
1108
        destroy_workqueue(vdisp_wq_secondary);
 
1109
        vdisp_wq_primary = NULL;
 
1110
        vdisp_wq_secondary = NULL;
 
1111
 
 
1112
        return err;
 
1113
}
 
1114
EXPORT_SYMBOL(omap_display_deinitialize);
 
1115