aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorRodrigo Vivi <rodrigo.vivi@openbossa.org>2009-09-22 19:46:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:49 -0400
commit2f21a62f16136f369788795a98aa5c313261f07b (patch)
tree1974092ab93bee721536018d7890d77e268af7cd /drivers/video
parent8fea8844a72f95ef22b108f5dc5c4237019771dd (diff)
omapfb: add support for rotation on the Blizzard LCD ctrl
The LCD controller (EPSON S1D13744) supports rotation (0, 90, 180 and 270 degrees) on hardware just setting the bits 0 and 1 of 0x28 register (LCD Panel Configuration Register). Now it is possible to use this caps only setting the angle degree on var rotate of fb_var_screeninfo using the FBIOPUT_VSCREENINFO ioctl. Fixed-by: Siarhei Siamashka <siarhei.siamashka@nokia.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@openbossa.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Imre Deak <imre.deak@nokia.com> Acked-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap/blizzard.c91
-rw-r--r--drivers/video/omap/omapfb_main.c52
2 files changed, 124 insertions, 19 deletions
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index 9dfcf39d3367..d5e59556f9e2 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -44,6 +44,7 @@
44#define BLIZZARD_CLK_SRC 0x0e 44#define BLIZZARD_CLK_SRC 0x0e
45#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 45#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
46#define BLIZZARD_MEM_BANK0_STATUS 0x14 46#define BLIZZARD_MEM_BANK0_STATUS 0x14
47#define BLIZZARD_PANEL_CONFIGURATION 0x28
47#define BLIZZARD_HDISP 0x2a 48#define BLIZZARD_HDISP 0x2a
48#define BLIZZARD_HNDP 0x2c 49#define BLIZZARD_HNDP 0x2c
49#define BLIZZARD_VDISP0 0x2e 50#define BLIZZARD_VDISP0 0x2e
@@ -162,6 +163,10 @@ struct blizzard_struct {
162 int vid_scaled; 163 int vid_scaled;
163 int last_color_mode; 164 int last_color_mode;
164 int zoom_on; 165 int zoom_on;
166 int zoom_area_gx1;
167 int zoom_area_gx2;
168 int zoom_area_gy1;
169 int zoom_area_gy2;
165 int screen_width; 170 int screen_width;
166 int screen_height; 171 int screen_height;
167 unsigned te_connected:1; 172 unsigned te_connected:1;
@@ -513,6 +518,13 @@ static int do_full_screen_update(struct blizzard_request *req)
513 return REQ_PENDING; 518 return REQ_PENDING;
514} 519}
515 520
521static int check_1d_intersect(int a1, int a2, int b1, int b2)
522{
523 if (a2 <= b1 || b2 <= a1)
524 return 0;
525 return 1;
526}
527
516/* Setup all planes with an overlapping area with the update window. */ 528/* Setup all planes with an overlapping area with the update window. */
517static int do_partial_update(struct blizzard_request *req, int plane, 529static int do_partial_update(struct blizzard_request *req, int plane,
518 int x, int y, int w, int h, 530 int x, int y, int w, int h,
@@ -525,6 +537,7 @@ static int do_partial_update(struct blizzard_request *req, int plane,
525 int color_mode; 537 int color_mode;
526 int flags; 538 int flags;
527 int zoom_off; 539 int zoom_off;
540 int have_zoom_for_this_update = 0;
528 541
529 /* Global coordinates, relative to pixel 0,0 of the LCD */ 542 /* Global coordinates, relative to pixel 0,0 of the LCD */
530 gx1 = x + blizzard.plane[plane].pos_x; 543 gx1 = x + blizzard.plane[plane].pos_x;
@@ -544,10 +557,6 @@ static int do_partial_update(struct blizzard_request *req, int plane,
544 gx2_out = gx1_out + w_out; 557 gx2_out = gx1_out + w_out;
545 gy2_out = gy1_out + h_out; 558 gy2_out = gy1_out + h_out;
546 } 559 }
547 zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 &&
548 w == blizzard.screen_width && h == blizzard.screen_height;
549 blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) ||
550 (w < w_out || h < h_out);
551 560
552 for (i = 0; i < OMAPFB_PLANE_NUM; i++) { 561 for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
553 struct plane_info *p = &blizzard.plane[i]; 562 struct plane_info *p = &blizzard.plane[i];
@@ -653,8 +662,49 @@ static int do_partial_update(struct blizzard_request *req, int plane,
653 else 662 else
654 disable_tearsync(); 663 disable_tearsync();
655 664
665 if ((gx2_out - gx1_out) != (gx2 - gx1) ||
666 (gy2_out - gy1_out) != (gy2 - gy1))
667 have_zoom_for_this_update = 1;
668
669 /* 'background' type of screen update (as opposed to 'destructive')
670 can be used to disable scaling if scaling is active */
671 zoom_off = blizzard.zoom_on && !have_zoom_for_this_update &&
672 (gx1_out == 0) && (gx2_out == blizzard.screen_width) &&
673 (gy1_out == 0) && (gy2_out == blizzard.screen_height) &&
674 (gx1 == 0) && (gy1 == 0);
675
676 if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off &&
677 check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2,
678 gx1_out, gx2_out) &&
679 check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2,
680 gy1_out, gy2_out)) {
681 /* Previous screen update was using scaling, current update
682 * is not using it. Additionally, current screen update is
683 * going to overlap with the scaled area. Scaling needs to be
684 * disabled in order to avoid 'magnifying glass' effect.
685 * Dummy setup of background window can be used for this.
686 */
687 set_window_regs(0, 0, blizzard.screen_width,
688 blizzard.screen_height,
689 0, 0, blizzard.screen_width,
690 blizzard.screen_height,
691 BLIZZARD_COLOR_RGB565, 1, flags);
692 blizzard.zoom_on = 0;
693 }
694
695 /* remember scaling settings if we have scaled update */
696 if (have_zoom_for_this_update) {
697 blizzard.zoom_on = 1;
698 blizzard.zoom_area_gx1 = gx1_out;
699 blizzard.zoom_area_gx2 = gx2_out;
700 blizzard.zoom_area_gy1 = gy1_out;
701 blizzard.zoom_area_gy2 = gy2_out;
702 }
703
656 set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out, 704 set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
657 color_mode, zoom_off, flags); 705 color_mode, zoom_off, flags);
706 if (zoom_off)
707 blizzard.zoom_on = 0;
658 708
659 blizzard.extif->set_bits_per_cycle(16); 709 blizzard.extif->set_bits_per_cycle(16);
660 /* set_window_regs has left the register index at the right 710 /* set_window_regs has left the register index at the right
@@ -908,6 +958,35 @@ static int blizzard_set_scale(int plane, int orig_w, int orig_h,
908 return 0; 958 return 0;
909} 959}
910 960
961static int blizzard_set_rotate(int angle)
962{
963 u32 l;
964
965 l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION);
966 l &= ~0x03;
967
968 switch (angle) {
969 case 0:
970 l = l | 0x00;
971 break;
972 case 90:
973 l = l | 0x03;
974 break;
975 case 180:
976 l = l | 0x02;
977 break;
978 case 270:
979 l = l | 0x01;
980 break;
981 default:
982 return -EINVAL;
983 }
984
985 blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l);
986
987 return 0;
988}
989
911static int blizzard_enable_plane(int plane, int enable) 990static int blizzard_enable_plane(int plane, int enable)
912{ 991{
913 if (enable) 992 if (enable)
@@ -1285,7 +1364,8 @@ static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
1285 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | 1364 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
1286 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE | 1365 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
1287 OMAPFB_CAPS_WINDOW_SCALE | 1366 OMAPFB_CAPS_WINDOW_SCALE |
1288 OMAPFB_CAPS_WINDOW_OVERLAY; 1367 OMAPFB_CAPS_WINDOW_OVERLAY |
1368 OMAPFB_CAPS_WINDOW_ROTATE;
1289 if (blizzard.te_connected) 1369 if (blizzard.te_connected)
1290 caps->ctrl |= OMAPFB_CAPS_TEARSYNC; 1370 caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
1291 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | 1371 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
@@ -1560,6 +1640,7 @@ struct lcd_ctrl blizzard_ctrl = {
1560 .setup_plane = blizzard_setup_plane, 1640 .setup_plane = blizzard_setup_plane,
1561 .set_scale = blizzard_set_scale, 1641 .set_scale = blizzard_set_scale,
1562 .enable_plane = blizzard_enable_plane, 1642 .enable_plane = blizzard_enable_plane,
1643 .set_rotate = blizzard_set_rotate,
1563 .update_window = blizzard_update_window_async, 1644 .update_window = blizzard_update_window_async,
1564 .sync = blizzard_sync, 1645 .sync = blizzard_sync,
1565 .suspend = blizzard_suspend, 1646 .suspend = blizzard_suspend,
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 8862233d57b6..db05f7e316e7 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -67,6 +67,7 @@ static struct caps_table_struct ctrl_caps[] = {
67 { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" }, 67 { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
68 { OMAPFB_CAPS_WINDOW_SCALE, "scale window" }, 68 { OMAPFB_CAPS_WINDOW_SCALE, "scale window" },
69 { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" }, 69 { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
70 { OMAPFB_CAPS_WINDOW_ROTATE, "rotate window" },
70 { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" }, 71 { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" },
71}; 72};
72 73
@@ -215,6 +216,15 @@ static int ctrl_change_mode(struct fb_info *fbi)
215 offset, var->xres_virtual, 216 offset, var->xres_virtual,
216 plane->info.pos_x, plane->info.pos_y, 217 plane->info.pos_x, plane->info.pos_y,
217 var->xres, var->yres, plane->color_mode); 218 var->xres, var->yres, plane->color_mode);
219 if (r < 0)
220 return r;
221
222 if (fbdev->ctrl->set_rotate != NULL) {
223 r = fbdev->ctrl->set_rotate(var->rotate);
224 if (r < 0)
225 return r;
226 }
227
218 if (fbdev->ctrl->set_scale != NULL) 228 if (fbdev->ctrl->set_scale != NULL)
219 r = fbdev->ctrl->set_scale(plane->idx, 229 r = fbdev->ctrl->set_scale(plane->idx,
220 var->xres, var->yres, 230 var->xres, var->yres,
@@ -600,7 +610,7 @@ static void omapfb_rotate(struct fb_info *fbi, int rotate)
600 struct omapfb_device *fbdev = plane->fbdev; 610 struct omapfb_device *fbdev = plane->fbdev;
601 611
602 omapfb_rqueue_lock(fbdev); 612 omapfb_rqueue_lock(fbdev);
603 if (cpu_is_omap15xx() && rotate != fbi->var.rotate) { 613 if (rotate != fbi->var.rotate) {
604 struct fb_var_screeninfo *new_var = &fbdev->new_var; 614 struct fb_var_screeninfo *new_var = &fbdev->new_var;
605 615
606 memcpy(new_var, &fbi->var, sizeof(*new_var)); 616 memcpy(new_var, &fbi->var, sizeof(*new_var));
@@ -707,28 +717,42 @@ int omapfb_update_window_async(struct fb_info *fbi,
707 void (*callback)(void *), 717 void (*callback)(void *),
708 void *callback_data) 718 void *callback_data)
709{ 719{
720 int xres, yres;
710 struct omapfb_plane_struct *plane = fbi->par; 721 struct omapfb_plane_struct *plane = fbi->par;
711 struct omapfb_device *fbdev = plane->fbdev; 722 struct omapfb_device *fbdev = plane->fbdev;
712 struct fb_var_screeninfo *var; 723 struct fb_var_screeninfo *var = &fbi->var;
724
725 switch (var->rotate) {
726 case 0:
727 case 180:
728 xres = fbdev->panel->x_res;
729 yres = fbdev->panel->y_res;
730 break;
731 case 90:
732 case 270:
733 xres = fbdev->panel->y_res;
734 yres = fbdev->panel->x_res;
735 break;
736 default:
737 return -EINVAL;
738 }
713 739
714 var = &fbi->var; 740 if (win->x >= xres || win->y >= yres ||
715 if (win->x >= var->xres || win->y >= var->yres || 741 win->out_x > xres || win->out_y > yres)
716 win->out_x > var->xres || win->out_y >= var->yres)
717 return -EINVAL; 742 return -EINVAL;
718 743
719 if (!fbdev->ctrl->update_window || 744 if (!fbdev->ctrl->update_window ||
720 fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) 745 fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
721 return -ENODEV; 746 return -ENODEV;
722 747
723 if (win->x + win->width >= var->xres) 748 if (win->x + win->width > xres)
724 win->width = var->xres - win->x; 749 win->width = xres - win->x;
725 if (win->y + win->height >= var->yres) 750 if (win->y + win->height > yres)
726 win->height = var->yres - win->y; 751 win->height = yres - win->y;
727 /* The out sizes should be cropped to the LCD size */ 752 if (win->out_x + win->out_width > xres)
728 if (win->out_x + win->out_width > fbdev->panel->x_res) 753 win->out_width = xres - win->out_x;
729 win->out_width = fbdev->panel->x_res - win->out_x; 754 if (win->out_y + win->out_height > yres)
730 if (win->out_y + win->out_height > fbdev->panel->y_res) 755 win->out_height = yres - win->out_y;
731 win->out_height = fbdev->panel->y_res - win->out_y;
732 if (!win->width || !win->height || !win->out_width || !win->out_height) 756 if (!win->width || !win->height || !win->out_width || !win->out_height)
733 return 0; 757 return 0;
734 758