2
* drivers/gpu/pvr/display/omap_display.c
4
* Copyright (C) 2010 Texas Instruments
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.
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
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/>.
19
#include <linux/slab.h>
20
#include <linux/kernel.h>
21
#include <linux/module.h>
24
#include <plat/vrfb.h>
25
#include <plat/display.h>
27
/* Workaround for DEBUG macro clash in framebuffer */
29
#include <../drivers/video/omap2/omapfb/omapfb.h>
33
#include <../drivers/video/omap2/omapfb/omapfb.h>
36
#define OMAP_DISP_DRV_NAME "omap_display"
37
#define OMAP_DISP_FRAMEBUFFER_COUNT num_registered_fb
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)
44
#define OMAP_DISP_IRQ_TIMEOUT 500
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__)
54
#define DBG_PRINT(format, ...)
55
#define WRN_PRINT(format, ...)
56
#define ERR_PRINT(format, ...)
59
#include "omap_display.h"
61
/* List for the available displays */
62
static struct omap_display_device *omap_display_list;
63
static unsigned int omap_display_number;
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;
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);
77
static int open_display(struct omap_display_device *display,
78
enum omap_display_feature features)
82
DBG_PRINT("Opening display '%s'", display->name);
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;
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);
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'",
111
static int close_display(struct omap_display_device *display)
116
/* TODO: Is it the same thing to close a virtual and single display? */
117
DBG_PRINT("Closing display '%s'", display->name);
119
display->reference_count--;
120
for (i = 0; i < display->overlay_managers_count; i++)
121
omap_dss_put_device(display->overlay_managers[i]->device);
123
if (display->flip_chain) {
124
err = display->destroy_flip_chain(display);
125
display->flip_chain = 0;
127
WRN_PRINT("An error happened when destroying flip "
128
"chain for '%s'", display->name);
134
static int get_max_buffers(struct omap_display_device *display)
136
/* TODO: If TILER is wanted to be used how do you calculate this? */
138
switch (display->id) {
139
case OMAP_DISPID_PRIMARY:
142
case OMAP_DISPID_SECONDARY:
145
case OMAP_DISPID_TERTIARY:
148
case OMAP_DISPID_VIRTUAL:
151
case OMAP_DISPID_BADSTATE:
153
ERR_PRINT("Unknown display id %i", display->id);
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;
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);
168
return (int) (framebuffer->fix.smem_len / buffer_size);
170
ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
171
fb_idx, display->name);
176
static int create_flip_chain(struct omap_display_device *display,
177
unsigned int buffer_count)
181
/* TODO: What about TILER buffers */
182
if (buffer_count <= 1) {
183
ERR_PRINT("Flip chains with %i buffers not supported",
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,
191
} else if (display->flip_chain) {
192
ERR_PRINT("Flip chain already exists for '%s'", display->name);
196
/* Create the flip chain with the framebuffer memory */
197
switch (display->id) {
198
case OMAP_DISPID_PRIMARY:
201
case OMAP_DISPID_SECONDARY:
204
case OMAP_DISPID_TERTIARY:
207
case OMAP_DISPID_VIRTUAL:
210
case OMAP_DISPID_BADSTATE:
212
ERR_PRINT("Unknown display id %i", display->id);
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;
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);
231
* Check if there is enough memory in the fb for the requested
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);
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,
248
flip_chain = kzalloc(sizeof(*flip_chain), GFP_KERNEL);
251
ERR_PRINT("Out of memory");
255
for (i = 0; i < buffer_count; i++) {
256
struct omap_display_buffer *buffer;
259
* Reuse the main buffer as the first buffer in the
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);
271
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
275
* FIXME: If one buffer allocation fails,
276
* deallocate flip chain and buffers
278
ERR_PRINT("Out of memory");
282
buffer->physical_addr = framebuffer->fix.smem_start +
284
buffer->virtual_addr =
285
(unsigned long) framebuffer->screen_base +
287
buffer->size = buffer_size;
288
buffer->display = display;
289
flip_chain->buffers[i] = buffer;
291
DBG_PRINT("Flip chain buffer %i has address %lx for"
292
" display '%s'", i, buffer->physical_addr,
296
display->flip_chain = flip_chain;
299
ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
300
fb_idx, display->name);
307
static int destroy_flip_chain(struct omap_display_device *display)
312
if (!display->flip_chain) {
313
DBG_PRINT("No flip chain to destroy for '%s'", display->name);
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)
324
err = display_destroy_buffer(buffer);
326
ERR_PRINT("Error destroying buffer in flip chain for"
327
" '%s'", display->name);
332
DBG_PRINT("Destroying flip chain for '%s'", display->name);
333
kfree(display->flip_chain);
334
display->flip_chain = 0;
339
static int rotate_display(struct omap_display_device *display,
340
unsigned int rotation)
342
ERR_PRINT("Not supported yet");
346
static int display_destroy_buffer(struct omap_display_buffer *buffer)
352
static int present_buffer_virtual(struct omap_display_buffer *buffer)
355
* TODO: Support for ORIENTATION_VERTICAL is in place,
356
* ORIENTATION_HORIZONTAL is missing
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;
364
if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
365
ERR_PRINT("Not a virtual display");
369
display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
370
display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
372
* Calculate offset without page alignment round up otherwise second
373
* display may see incorrect data
375
buffer_offset = display_primary->height * display_virtual->byte_stride;
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;
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);
387
/* Primary display has the base */
388
temp_buffer.display = display_primary;
389
display_primary->present_buffer(&temp_buffer);
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;
396
if (display_virtual->features & ORIENTATION_INVERT) {
397
temp_buffer.display = display_primary;
398
display_primary->present_buffer(&temp_buffer);
400
temp_buffer.display = display_secondary;
401
display_secondary->present_buffer(&temp_buffer);
407
static int present_buffer(struct omap_display_buffer *buffer)
409
struct omap_display_device *display = buffer->display;
410
struct fb_info *framebuffer;
411
struct omapfb_info *ofbi;
412
struct omapfb2_device *fbdev;
416
switch (display->id) {
417
case OMAP_DISPID_PRIMARY:
420
case OMAP_DISPID_SECONDARY:
423
case OMAP_DISPID_TERTIARY:
426
case OMAP_DISPID_VIRTUAL:
427
case OMAP_DISPID_BADSTATE:
429
ERR_PRINT("Unable to handle display %i", display->id);
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);
439
framebuffer = registered_fb[fb_idx];
440
ofbi = FB2OFB(framebuffer);
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;
453
overlay = ofbi->overlays[i];
454
manager = overlay->manager;
455
overlay->get_overlay_info(overlay, &overlay_info);
457
overlay_info.paddr = buffer->physical_addr;
458
overlay_info.vaddr = (void *) buffer->virtual_addr;
459
overlay->set_overlay_info(overlay, &overlay_info);
462
manager->apply(manager);
463
display = manager->device;
464
driver = display ? display->driver : NULL;
467
if (dss_ovl_manually_updated(overlay)) {
468
if (driver->sched_update)
469
driver->sched_update(display, 0, 0,
471
overlay_info.height);
472
else if (driver->update)
473
driver->update(display, 0, 0,
475
overlay_info.height);
479
omapfb_unlock(fbdev);
485
static int present_buffer_sync(struct omap_display_buffer *buffer)
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;
496
switch (display->id) {
497
case OMAP_DISPID_PRIMARY:
500
case OMAP_DISPID_SECONDARY:
503
case OMAP_DISPID_TERTIARY:
506
case OMAP_DISPID_VIRTUAL:
507
case OMAP_DISPID_BADSTATE:
509
ERR_PRINT("Unable to handle display %i", display->id);
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);
519
framebuffer = registered_fb[fb_idx];
520
dss_device = fb2display(framebuffer);
523
WRN_PRINT("No DSS device to sync with display '%s'!",
528
driver = dss_device->driver;
529
manager = dss_device->manager;
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);
542
WRN_PRINT("Unable to sync with display '%s'!", display->name);
547
static void vdisp_sync_handler(struct work_struct *work)
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);
555
static int present_buffer_sync_virtual(struct omap_display_buffer *buffer)
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.
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;
569
if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
570
ERR_PRINT("Not a virtual display");
574
display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
575
display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
577
* Calculate offset without page alignment round up otherwise second
578
* display may see incorrect data
580
buffer_offset = display_primary->height * display_virtual->byte_stride;
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 +
589
temp_buffer_bottom.virtual_addr = buffer->virtual_addr + buffer_offset;
590
temp_buffer_bottom.size = buffer->size >> 1;
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;
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;
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);
612
/* Wait until each display sync and present */
613
flush_workqueue(vdisp_wq_primary);
614
flush_workqueue(vdisp_wq_secondary);
619
static int display_sync(struct omap_display_device *display)
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;
629
switch (display->id) {
630
case OMAP_DISPID_PRIMARY:
633
case OMAP_DISPID_SECONDARY:
636
case OMAP_DISPID_TERTIARY:
639
case OMAP_DISPID_VIRTUAL:
640
case OMAP_DISPID_BADSTATE:
642
ERR_PRINT("Unable to handle display %i", display->id);
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);
652
framebuffer = registered_fb[fb_idx];
653
dss_device = fb2display(framebuffer);
656
WRN_PRINT("No DSS device to sync with display '%s'!",
661
driver = dss_device->driver;
662
manager = dss_device->manager;
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);
671
WRN_PRINT("Unable to sync with display '%s'!", display->name);
676
static int display_sync_virtual(struct omap_display_device *display_virtual)
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.
683
struct omap_display_device *display_primary;
685
if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
686
ERR_PRINT("Not a virtual display");
690
display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
691
return display_primary->sync(display_primary);
694
static struct omap_display_buffer *create_main_buffer(
695
struct omap_display_device *display)
698
switch (display->id) {
699
case OMAP_DISPID_PRIMARY:
702
case OMAP_DISPID_SECONDARY:
705
case OMAP_DISPID_TERTIARY:
708
case OMAP_DISPID_VIRTUAL:
709
/* Use fb0 for virtual display */
712
case OMAP_DISPID_BADSTATE:
714
ERR_PRINT("Unknown display id %i", display->id);
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;
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);
732
* Check if there is enough memory in the fb for the
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);
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,
749
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
752
ERR_PRINT("Out of memory");
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;
763
DBG_PRINT("Created main buffer %lx for display '%s'",
764
buffer->physical_addr, display->name);
768
ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
769
fb_idx, display->name);
774
static int populate_display_info(struct omap_display_device *display,
775
struct omap_overlay_manager *overlay_manager)
777
struct omap_dss_device *dss_device = overlay_manager->device;
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";
792
ERR_PRINT("Display id '%s' not supported", dss_device->name);
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);
803
display->width = xres;
804
display->height = yres;
806
display->bits_per_pixel =
807
dss_device->driver->get_recommended_bpp(dss_device);
808
switch (display->bits_per_pixel) {
811
* TODO: Asume RGB_565, maybe need to double check in
812
* the DSS if this is true
814
display->pixel_format = RGB_565;
815
display->bytes_per_pixel = 2;
817
case 24: /* 24 bits are encapsulated with 32 bits */
820
* TODO: Asume ARGB_8888, maybe need to double check in
821
* the DSS if this is true
823
display->pixel_format = ARGB_8888;
824
display->bytes_per_pixel = 4;
827
ERR_PRINT("Unable to handle %i bpp", display->bits_per_pixel);
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;
836
/* Add the manager to the list */
837
for (i = 0; i < OMAP_DISP_MAX_MANAGERS; i++)
838
display->overlay_managers[i] = 0;
840
display->overlay_managers[0] = overlay_manager;
841
display->overlay_managers_count = 1;
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;
853
display->main_buffer = create_main_buffer(display);
854
if (!display->main_buffer)
855
WRN_PRINT("Failed to create main buffer for '%s'",
858
display->buffers_available = get_max_buffers(display);
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);
869
static int populate_virtual_display_info(struct omap_display_device *display)
871
struct omap_display_device *display_primary ;
872
struct omap_display_device *display_secondary;
875
display->id = OMAP_DISPID_VIRTUAL;
876
display->name = "virtual";
878
display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
879
display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
881
if (!display_primary) {
882
ERR_PRINT("Primary display doesn't exist");
884
} else if (!display_secondary) {
885
ERR_PRINT("Secondary display doesn't exist");
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"
898
* TODO: Here it is hardcoded the resolution asumming a vertical
899
* virtual config, what about horizontal?
901
display->width = display_primary->width;
902
display->height = display_primary->height * 2;
904
if (display_primary->bits_per_pixel !=
905
display_secondary->bits_per_pixel) {
906
ERR_PRINT("Primary and seconday displays format are"
911
display->bits_per_pixel = display_primary->bits_per_pixel;
912
switch (display->bits_per_pixel) {
915
* TODO: Asume RGB_565, maybe need to double check in
916
* the DSS if this is true
918
display->pixel_format = RGB_565;
919
display->bytes_per_pixel = 2;
921
case 24: /* 24 bits are encapsulated with 32 bits */
924
* TODO: Asume ARGB_8888, maybe need to double check in
925
* the DSS if this is true
927
display->pixel_format = ARGB_8888;
928
display->bytes_per_pixel = 4;
931
ERR_PRINT("Unable to handle %i bpp",
932
display->bits_per_pixel);
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;
942
/* Add the primary and secondary overlay managers */
943
for (i = 0; i < OMAP_DISP_MAX_MANAGERS; i++)
944
display->overlay_managers[i] = 0;
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;
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;
960
display->main_buffer = create_main_buffer(display);
961
if (!display->main_buffer)
962
WRN_PRINT("Failed to create main buffer for '%s'",
965
display->buffers_available = get_max_buffers(display);
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,
976
static int create_display_list(void)
979
struct omap_display_device *display;
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++;
986
/* Allocate custom display list */
987
omap_display_list = kzalloc(
988
sizeof(*display) * omap_display_number, GFP_KERNEL);
990
if (!omap_display_list) {
991
ERR_PRINT("Out of memory");
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;
1007
if (populate_display_info(display, overlay_manager)) {
1008
ERR_PRINT("Error populating display %i info with "
1010
overlay_manager->device->name);
1011
display->id = OMAP_DISPID_BADSTATE;
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;
1026
struct omap_display_device *omap_display_get(enum omap_display_id id)
1029
struct omap_display_device *display;
1031
if (id == OMAP_DISPID_BADSTATE) {
1032
ERR_PRINT("Oops.. user must never request a bad display");
1036
for (i = 0; i < omap_display_number; i++) {
1037
display = &omap_display_list[i];
1038
if (display->id == id)
1042
ERR_PRINT("Unknown display %i requested", id);
1045
EXPORT_SYMBOL(omap_display_get);
1047
int omap_display_count(void)
1049
return omap_display_number;
1051
EXPORT_SYMBOL(omap_display_count);
1053
int omap_display_initialize(void)
1056
* TODO: Is there a better way to check if list is already created?
1058
if (!omap_display_list) {
1059
DBG_PRINT("Initializing driver");
1060
if (create_display_list()) {
1061
ERR_PRINT("Error loading driver");
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);
1075
EXPORT_SYMBOL(omap_display_initialize);
1077
int omap_display_deinitialize(void)
1081
DBG_PRINT("Driver exiting");
1083
for (i = 0; i < omap_display_number; i++) {
1084
struct omap_display_device *display = &omap_display_list[i];
1089
if (display->main_buffer) {
1090
err = display_destroy_buffer(display->main_buffer);
1091
display->main_buffer = 0;
1093
WRN_PRINT("An error happened when destroying "
1094
"main buffer for '%s'", display->name);
1097
err = display->close(display);
1100
ERR_PRINT("Unable to close display '%s'",
1104
kfree(omap_display_list);
1105
omap_display_list = 0;
1107
destroy_workqueue(vdisp_wq_primary);
1108
destroy_workqueue(vdisp_wq_secondary);
1109
vdisp_wq_primary = NULL;
1110
vdisp_wq_secondary = NULL;
1114
EXPORT_SYMBOL(omap_display_deinitialize);