Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

OMAPDSS: DISPC: Support rotation through TILER

TILER is a block in OMAP4's DMM which lets DSS fetch frames in a rotated manner.
Physical memory can be mapped to a portion of OMAP's system address space called
TILER address space. The TILER address space is split into 8 views. Each view
represents a rotated or mirrored form of the mapped physical memory. When a
DISPC overlay's base address is programmed to one of these views, the TILER
fetches the pixels according to the orientation of the view. A view is further
split into 4 containers, each container holds elements of a particular size.
Rotation can be achieved at the granularity of elements in the container. For
more information on TILER, refer to the Memory Subsytem section in OMAP4 TRM.
Rotation type TILER has been added which is used to exploit the capabilities of
these 8 views for performing various rotations.

When fetching from addresses mapped to TILER space, the DISPC DMA can fetch
pixels in either 1D or 2D bursts. The fetch depends on which TILER container we
are accessing. Accessing 8, 16 and 32 bit sized containers requires 2D bursts,
and page mode sized containers require 1D bursts.

The DSS2 user is expected to provide the Tiler address of the view that it is
interested in. This is passed to the paddr and p_uv_addr parameters in
omap_overlay_info. It is also expected to provide the stride value based on the
view's orientation and container type, this should be passed to the screen_width
parameter of omap_overlay_info. In calc_tiler_rotation_offset screen_width is
used to calculate the required row_inc for DISPC. x_predecim and y_predecim are
also used to calculate row_inc and pix_inc thereby adding predecimation support
for TILER.

Signed-off-by: Chandrabhanu Mahapatra <cmahapatra@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

authored by

Chandrabhanu Mahapatra and committed by
Tomi Valkeinen
65e006ff 3cb6a1b9

+87 -3
+59 -1
drivers/video/omap2/dss/dispc.c
··· 785 785 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); 786 786 } 787 787 788 + static void dispc_ovl_configure_burst_type(enum omap_plane plane, 789 + enum omap_dss_rotation_type rotation_type) 790 + { 791 + if (dss_has_feature(FEAT_BURST_2D) == 0) 792 + return; 793 + 794 + if (rotation_type == OMAP_DSS_ROT_TILER) 795 + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29); 796 + else 797 + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29); 798 + } 799 + 788 800 void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) 789 801 { 790 802 int shift; ··· 1743 1731 } 1744 1732 } 1745 1733 1734 + static void calc_tiler_rotation_offset(u16 screen_width, u16 width, 1735 + enum omap_color_mode color_mode, bool fieldmode, 1736 + unsigned int field_offset, unsigned *offset0, unsigned *offset1, 1737 + s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) 1738 + { 1739 + u8 ps; 1740 + 1741 + switch (color_mode) { 1742 + case OMAP_DSS_COLOR_CLUT1: 1743 + case OMAP_DSS_COLOR_CLUT2: 1744 + case OMAP_DSS_COLOR_CLUT4: 1745 + case OMAP_DSS_COLOR_CLUT8: 1746 + BUG(); 1747 + return; 1748 + default: 1749 + ps = color_mode_to_bpp(color_mode) / 8; 1750 + break; 1751 + } 1752 + 1753 + DSSDBG("scrw %d, width %d\n", screen_width, width); 1754 + 1755 + /* 1756 + * field 0 = even field = bottom field 1757 + * field 1 = odd field = top field 1758 + */ 1759 + *offset1 = 0; 1760 + if (field_offset) 1761 + *offset0 = *offset1 + field_offset * screen_width * ps; 1762 + else 1763 + *offset0 = *offset1; 1764 + *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) + 1765 + (fieldmode ? screen_width : 0), ps); 1766 + if (color_mode == OMAP_DSS_COLOR_YUV2 || 1767 + color_mode == OMAP_DSS_COLOR_UYVY) 1768 + *pix_inc = pixinc(x_predecim, 2 * ps); 1769 + else 1770 + *pix_inc = pixinc(x_predecim, ps); 1771 + } 1772 + 1746 1773 /* 1747 1774 * This function is used to avoid synclosts in OMAP3, because of some 1748 1775 * undocumented horizontal position and timing related limitations. ··· 2173 2122 row_inc = 0; 2174 2123 pix_inc = 0; 2175 2124 2176 - if (oi->rotation_type == OMAP_DSS_ROT_DMA) 2125 + if (oi->rotation_type == OMAP_DSS_ROT_TILER) 2126 + calc_tiler_rotation_offset(oi->screen_width, in_width, 2127 + oi->color_mode, fieldmode, field_offset, 2128 + &offset0, &offset1, &row_inc, &pix_inc, 2129 + x_predecim, y_predecim); 2130 + else if (oi->rotation_type == OMAP_DSS_ROT_DMA) 2177 2131 calc_dma_rotation_offset(oi->rotation, oi->mirror, 2178 2132 oi->screen_width, in_width, frame_height, 2179 2133 oi->color_mode, fieldmode, field_offset, ··· 2195 2139 offset0, offset1, row_inc, pix_inc); 2196 2140 2197 2141 dispc_ovl_set_color_mode(plane, oi->color_mode); 2142 + 2143 + dispc_ovl_configure_burst_type(plane, oi->rotation_type); 2198 2144 2199 2145 dispc_ovl_set_ba0(plane, oi->paddr + offset0); 2200 2146 dispc_ovl_set_ba1(plane, oi->paddr + offset1);
+16
drivers/video/omap2/dss/dss_features.c
··· 52 52 const char * const *clksrc_names; 53 53 const struct dss_param_range *dss_params; 54 54 55 + const enum omap_dss_rotation_type supported_rotation_types; 56 + 55 57 const u32 buffer_size_unit; 56 58 const u32 burst_size_unit; 57 59 }; ··· 407 405 FEAT_FIR_COEF_V, 408 406 FEAT_ALPHA_FREE_ZORDER, 409 407 FEAT_FIFO_MERGE, 408 + FEAT_BURST_2D, 410 409 }; 411 410 412 411 static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = { ··· 425 422 FEAT_FIR_COEF_V, 426 423 FEAT_ALPHA_FREE_ZORDER, 427 424 FEAT_FIFO_MERGE, 425 + FEAT_BURST_2D, 428 426 }; 429 427 430 428 static const enum dss_feat_id omap4_dss_feat_list[] = { ··· 444 440 FEAT_FIR_COEF_V, 445 441 FEAT_ALPHA_FREE_ZORDER, 446 442 FEAT_FIFO_MERGE, 443 + FEAT_BURST_2D, 447 444 }; 448 445 449 446 /* OMAP2 DSS Features */ ··· 462 457 .overlay_caps = omap2_dss_overlay_caps, 463 458 .clksrc_names = omap2_dss_clk_source_names, 464 459 .dss_params = omap2_dss_param_range, 460 + .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, 465 461 .buffer_size_unit = 1, 466 462 .burst_size_unit = 8, 467 463 }; ··· 482 476 .overlay_caps = omap3430_dss_overlay_caps, 483 477 .clksrc_names = omap3_dss_clk_source_names, 484 478 .dss_params = omap3_dss_param_range, 479 + .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, 485 480 .buffer_size_unit = 1, 486 481 .burst_size_unit = 8, 487 482 }; ··· 501 494 .overlay_caps = omap3630_dss_overlay_caps, 502 495 .clksrc_names = omap3_dss_clk_source_names, 503 496 .dss_params = omap3_dss_param_range, 497 + .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, 504 498 .buffer_size_unit = 1, 505 499 .burst_size_unit = 8, 506 500 }; ··· 522 514 .overlay_caps = omap4_dss_overlay_caps, 523 515 .clksrc_names = omap4_dss_clk_source_names, 524 516 .dss_params = omap4_dss_param_range, 517 + .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, 525 518 .buffer_size_unit = 16, 526 519 .burst_size_unit = 16, 527 520 }; ··· 542 533 .overlay_caps = omap4_dss_overlay_caps, 543 534 .clksrc_names = omap4_dss_clk_source_names, 544 535 .dss_params = omap4_dss_param_range, 536 + .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, 545 537 .buffer_size_unit = 16, 546 538 .burst_size_unit = 16, 547 539 }; ··· 562 552 .overlay_caps = omap4_dss_overlay_caps, 563 553 .clksrc_names = omap4_dss_clk_source_names, 564 554 .dss_params = omap4_dss_param_range, 555 + .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, 565 556 .buffer_size_unit = 16, 566 557 .burst_size_unit = 16, 567 558 }; ··· 681 670 682 671 *start = omap_current_dss_features->reg_fields[id].start; 683 672 *end = omap_current_dss_features->reg_fields[id].end; 673 + } 674 + 675 + bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type) 676 + { 677 + return omap_current_dss_features->supported_rotation_types & rot_type; 684 678 } 685 679 686 680 void dss_features_init(void)
+3
drivers/video/omap2/dss/dss_features.h
··· 62 62 FEAT_FIFO_MERGE, 63 63 /* An unknown HW bug causing the normal FIFO thresholds not to work */ 64 64 FEAT_OMAP3_DSI_FIFO_BUG, 65 + FEAT_BURST_2D, 65 66 }; 66 67 67 68 /* DSS register field id */ ··· 110 109 111 110 u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ 112 111 u32 dss_feat_get_burst_size_unit(void); /* in bytes */ 112 + 113 + bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type); 113 114 114 115 bool dss_has_feature(enum dss_feat_id id); 115 116 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
+6
drivers/video/omap2/dss/overlay.c
··· 628 628 return -EINVAL; 629 629 } 630 630 631 + if (dss_feat_rotation_type_supported(info->rotation_type) == 0) { 632 + DSSERR("check_overlay: rotation type %d not supported\n", 633 + info->rotation_type); 634 + return -EINVAL; 635 + } 636 + 631 637 return 0; 632 638 } 633 639
+3 -2
include/video/omapdss.h
··· 175 175 }; 176 176 177 177 enum omap_dss_rotation_type { 178 - OMAP_DSS_ROT_DMA = 0, 179 - OMAP_DSS_ROT_VRFB = 1, 178 + OMAP_DSS_ROT_DMA = 1 << 0, 179 + OMAP_DSS_ROT_VRFB = 1 << 1, 180 + OMAP_DSS_ROT_TILER = 1 << 2, 180 181 }; 181 182 182 183 /* clockwise rotation angle */