/drivers/video/omap2/dsscomp/base.c
C | 504 lines | 370 code | 68 blank | 66 comment | 59 complexity | 94f2643902cd0cb0505d61bdcf5fc965 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * linux/drivers/video/omap2/dsscomp/base.c
- *
- * DSS Composition basic operation support
- *
- * Copyright (C) 2011 Texas Instruments, Inc
- * Author: Lajos Molnar <molnar@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <linux/kernel.h>
- #include <linux/notifier.h>
- #include <mach/tiler.h>
- #include <video/omapdss.h>
- #include <video/dsscomp.h>
- #include <plat/dsscomp.h>
- #include "dsscomp.h"
- int debug;
- module_param(debug, int, 0644);
- /* color formats supported - bitfield info is used for truncation logic */
- static const struct color_info {
- int a_ix, a_bt; /* bitfields */
- int r_ix, r_bt;
- int g_ix, g_bt;
- int b_ix, b_bt;
- int x_bt;
- enum omap_color_mode mode;
- const char *name;
- } fmts[2][16] = { {
- { 0, 0, 0, 0, 0, 0, 0, 0, 1, OMAP_DSS_COLOR_CLUT1, "BITMAP1" },
- { 0, 0, 0, 0, 0, 0, 0, 0, 2, OMAP_DSS_COLOR_CLUT2, "BITMAP2" },
- { 0, 0, 0, 0, 0, 0, 0, 0, 4, OMAP_DSS_COLOR_CLUT4, "BITMAP4" },
- { 0, 0, 0, 0, 0, 0, 0, 0, 8, OMAP_DSS_COLOR_CLUT8, "BITMAP8" },
- { 0, 0, 8, 4, 4, 4, 0, 4, 4, OMAP_DSS_COLOR_RGB12U, "xRGB12-4444" },
- { 12, 4, 8, 4, 4, 4, 0, 4, 0, OMAP_DSS_COLOR_ARGB16, "ARGB16-4444" },
- { 0, 0, 11, 5, 5, 6, 0, 5, 0, OMAP_DSS_COLOR_RGB16, "RGB16-565" },
- { 15, 1, 10, 5, 5, 5, 0, 5, 0, OMAP_DSS_COLOR_ARGB16_1555,
- "ARGB16-1555" },
- { 0, 0, 16, 8, 8, 8, 0, 8, 8, OMAP_DSS_COLOR_RGB24U, "xRGB24-8888" },
- { 0, 0, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_RGB24P, "RGB24-888" },
- { 0, 0, 12, 4, 8, 4, 4, 4, 4, OMAP_DSS_COLOR_RGBX16, "RGBx12-4444" },
- { 0, 4, 12, 4, 8, 4, 4, 4, 0, OMAP_DSS_COLOR_RGBA16, "RGBA16-4444" },
- { 24, 8, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_ARGB32, "ARGB32-8888" },
- { 0, 8, 24, 8, 16, 8, 8, 8, 0, OMAP_DSS_COLOR_RGBA32, "RGBA32-8888" },
- { 0, 0, 24, 8, 16, 8, 8, 8, 8, OMAP_DSS_COLOR_RGBX32, "RGBx24-8888" },
- { 0, 0, 10, 5, 5, 5, 0, 5, 1, OMAP_DSS_COLOR_XRGB16_1555,
- "xRGB15-1555" },
- }, {
- { 0, 0, 0, 0, 0, 0, 0, 0, 12, OMAP_DSS_COLOR_NV12, "NV12" },
- { 0, 0, 12, 4, 8, 4, 4, 4, 4, OMAP_DSS_COLOR_RGBX16, "RGBx12-4444" },
- { 0, 4, 12, 4, 8, 4, 4, 4, 0, OMAP_DSS_COLOR_RGBA16, "RGBA16-4444" },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "invalid" },
- { 0, 0, 8, 4, 4, 4, 0, 4, 4, OMAP_DSS_COLOR_RGB12U, "xRGB12-4444" },
- { 12, 4, 8, 4, 4, 4, 0, 4, 0, OMAP_DSS_COLOR_ARGB16, "ARGB16-4444" },
- { 0, 0, 11, 5, 5, 6, 0, 5, 0, OMAP_DSS_COLOR_RGB16, "RGB16-565" },
- { 15, 1, 10, 5, 5, 5, 0, 5, 0, OMAP_DSS_COLOR_ARGB16_1555,
- "ARGB16-1555" },
- { 0, 0, 16, 8, 8, 8, 0, 8, 8, OMAP_DSS_COLOR_RGB24U, "xRGB24-8888" },
- { 0, 0, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_RGB24P, "RGB24-888" },
- { 0, 0, 0, 0, 0, 0, 0, 0, 16, OMAP_DSS_COLOR_YUV2, "YUYV" },
- { 0, 0, 0, 0, 0, 0, 0, 0, 16, OMAP_DSS_COLOR_UYVY, "UYVY" },
- { 24, 8, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_ARGB32, "ARGB32-8888" },
- { 0, 8, 24, 8, 16, 8, 8, 8, 0, OMAP_DSS_COLOR_RGBA32, "RGBA32-8888" },
- { 0, 0, 24, 8, 16, 8, 8, 8, 8, OMAP_DSS_COLOR_RGBX32, "RGBx24-8888" },
- { 0, 0, 10, 5, 5, 5, 0, 5, 1, OMAP_DSS_COLOR_XRGB16_1555,
- "xRGB15-1555" },
- } };
- static const struct color_info *get_color_info(enum omap_color_mode mode)
- {
- int i;
- for (i = 0; i < sizeof(fmts) / sizeof(fmts[0][0]); i++)
- if (fmts[0][i].mode == mode)
- return fmts[0] + i;
- return NULL;
- }
- static int color_mode_to_bpp(enum omap_color_mode color_mode)
- {
- const struct color_info *ci = get_color_info(color_mode);
- BUG_ON(!ci);
- return ci->a_bt + ci->r_bt + ci->g_bt + ci->b_bt + ci->x_bt;
- }
- #ifdef CONFIG_DEBUG_FS
- const char *dsscomp_get_color_name(enum omap_color_mode m)
- {
- const struct color_info *ci = get_color_info(m);
- return ci ? ci->name : NULL;
- }
- #endif
- union rect {
- struct {
- s32 x;
- s32 y;
- s32 w;
- s32 h;
- };
- struct {
- s32 xy[2];
- s32 wh[2];
- };
- struct dss2_rect_t r;
- };
- int crop_to_rect(union rect *crop, union rect *win, union rect *vis,
- int rotation, int mirror)
- {
- int c, swap = rotation & 1;
- /* align crop window with display coordinates */
- if (swap)
- crop->y -= (crop->h = -crop->h);
- if (rotation & 2)
- crop->xy[!swap] -= (crop->wh[!swap] = -crop->wh[!swap]);
- if ((!mirror) ^ !(rotation & 2))
- crop->xy[swap] -= (crop->wh[swap] = -crop->wh[swap]);
- for (c = 0; c < 2; c++) {
- /* see if complete buffer is outside the vis or it is
- fully cropped or scaled to 0 */
- if (win->wh[c] <= 0 || vis->wh[c] <= 0 ||
- win->xy[c] + win->wh[c] <= vis->xy[c] ||
- win->xy[c] >= vis->xy[c] + vis->wh[c] ||
- !crop->wh[c ^ swap])
- return -ENOENT;
- /* crop left/top */
- if (win->xy[c] < vis->xy[c]) {
- /* correction term */
- int a = (vis->xy[c] - win->xy[c]) *
- crop->wh[c ^ swap] / win->wh[c];
- crop->xy[c ^ swap] += a;
- crop->wh[c ^ swap] -= a;
- win->wh[c] -= vis->xy[c] - win->xy[c];
- win->xy[c] = vis->xy[c];
- }
- /* crop right/bottom */
- if (win->xy[c] + win->wh[c] > vis->xy[c] + vis->wh[c]) {
- crop->wh[c ^ swap] = crop->wh[c ^ swap] *
- (vis->xy[c] + vis->wh[c] - win->xy[c]) /
- win->wh[c];
- win->wh[c] = vis->xy[c] + vis->wh[c] - win->xy[c];
- }
- if (!crop->wh[c ^ swap] || !win->wh[c])
- return -ENOENT;
- }
- /* realign crop window to buffer coordinates */
- if (rotation & 2)
- crop->xy[!swap] -= (crop->wh[!swap] = -crop->wh[!swap]);
- if ((!mirror) ^ !(rotation & 2))
- crop->xy[swap] -= (crop->wh[swap] = -crop->wh[swap]);
- if (swap)
- crop->y -= (crop->h = -crop->h);
- return 0;
- }
- int set_dss_ovl_info(struct dss2_ovl_info *oi)
- {
- struct omap_overlay_info info;
- struct omap_overlay *ovl;
- struct dss2_ovl_cfg *cfg;
- union rect crop, win, vis;
- int c;
- /* check overlay number */
- if (!oi || oi->cfg.ix >= omap_dss_get_num_overlays())
- return -EINVAL;
- cfg = &oi->cfg;
- ovl = omap_dss_get_overlay(cfg->ix);
- /* just in case there are new fields, we get the current info */
- ovl->get_overlay_info(ovl, &info);
- info.enabled = cfg->enabled;
- if (!cfg->enabled)
- goto done;
- /* copied params */
- info.zorder = cfg->zorder;
- if (cfg->zonly)
- goto done;
- info.global_alpha = cfg->global_alpha;
- info.pre_mult_alpha = cfg->pre_mult_alpha;
- info.rotation = cfg->rotation;
- info.mirror = cfg->mirror;
- info.color_mode = cfg->color_mode;
- /* crop to screen */
- crop.r = cfg->crop;
- win.r = cfg->win;
- vis.x = vis.y = 0;
- vis.w = ovl->manager->device->panel.timings.x_res;
- vis.h = ovl->manager->device->panel.timings.y_res;
- if (crop_to_rect(&crop, &win, &vis, cfg->rotation, cfg->mirror) ||
- vis.w < 2) {
- info.enabled = false;
- goto done;
- }
- /* adjust crop to UV pixel boundaries */
- for (c = 0; c < (cfg->color_mode == OMAP_DSS_COLOR_NV12 ? 2 :
- (cfg->color_mode &
- (OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY)) ? 1 : 0); c++) {
- /* keep the output window to avoid trembling edges */
- crop.wh[c] += crop.xy[c] & 1; /* round down start */
- crop.xy[c] &= ~1;
- crop.wh[c] += crop.wh[c] & 1; /* round up end */
- /*
- * Buffer is aligned on UV pixel boundaries, so no
- * worries about extending crop region.
- */
- }
- info.width = crop.w;
- info.height = crop.h;
- if (cfg->rotation & 1)
- /* DISPC uses swapped height/width for 90/270 degrees */
- swap(info.width, info.height);
- info.pos_x = win.x;
- info.pos_y = win.y;
- info.out_width = win.w;
- info.out_height = win.h;