blob: 6b458cb88db4ec80498308551186d8f58eb124ce [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
/* Linux Headers */
#include <linux/types.h>
/* Amlogic Headers */
#include <linux/amlogic/media/ge2d/ge2d.h>
#include <linux/amlogic/media/canvas/canvas.h>
/* Local Headers */
#include "ge2d_log.h"
#include "ge2d_io.h"
#include "ge2d_reg.h"
#define GE2D_DST1_INDEX 0
#define GE2D_SRC1_INDEX 1
#define GE2D_SRC2_INDEX 2
static int gaul_filter_used;
static const unsigned int filt_coef_gau1[] = { /* gau1+phase */
0x20402000,
0x203f2001,
0x203e2002,
0x203d2003,
0x203c2004,
0x203b2005,
0x203a2006,
0x20392007,
0x20382008,
0x20372009,
0x2036200a,
0x2035200b,
0x2034200c,
0x2033200d,
0x2032200e,
0x2031200f,
0x20302010,
0x202f2011,
0x202e2012,
0x202d2013,
0x202c2014,
0x202b2015,
0x202a2016,
0x20292017,
0x20282018,
0x20272019,
0x2026201a,
0x2025201b,
0x2024201c,
0x2023201d,
0x2022201e,
0x2021201f,
0x20202020
};
/* average, no phase, horizontal filter and vertical filter for top field */
static const unsigned int filt_coef_gau0[] = {
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020,
0x20202020
};
/* average, no phase, only for vertical filter of bot filed*/
static const unsigned int filt_coef_gau0_bot[] = {
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00,
0x2a2b2a00
};
static const unsigned int filt_coef0[] = { /* bicubic */
0x00800000,
0x007f0100,
0xff7f0200,
0xfe7f0300,
0xfd7e0500,
0xfc7e0600,
0xfb7d0800,
0xfb7c0900,
0xfa7b0b00,
0xfa7a0dff,
0xf9790fff,
0xf97711ff,
0xf87613ff,
0xf87416fe,
0xf87218fe,
0xf8701afe,
0xf76f1dfd,
0xf76d1ffd,
0xf76b21fd,
0xf76824fd,
0xf76627fc,
0xf76429fc,
0xf7612cfc,
0xf75f2ffb,
0xf75d31fb,
0xf75a34fb,
0xf75837fa,
0xf7553afa,
0xf8523cfa,
0xf8503ff9,
0xf84d42f9,
0xf84a45f9,
0xf84848f8
};
static const unsigned int filt_coef1[] = { /* 2 point bilinear */
0x00800000,
0x007e0200,
0x007c0400,
0x007a0600,
0x00780800,
0x00760a00,
0x00740c00,
0x00720e00,
0x00701000,
0x006e1200,
0x006c1400,
0x006a1600,
0x00681800,
0x00661a00,
0x00641c00,
0x00621e00,
0x00602000,
0x005e2200,
0x005c2400,
0x005a2600,
0x00582800,
0x00562a00,
0x00542c00,
0x00522e00,
0x00503000,
0x004e3200,
0x004c3400,
0x004a3600,
0x00483800,
0x00463a00,
0x00443c00,
0x00423e00,
0x00404000
};
static const unsigned int filt_coef2[] = { /* 3 point triangle */
0x40400000,
0x3f400100,
0x3d410200,
0x3c410300,
0x3a420400,
0x39420500,
0x37430600,
0x36430700,
0x35430800,
0x33450800,
0x32450900,
0x31450a00,
0x30450b00,
0x2e460c00,
0x2d460d00,
0x2c470d00,
0x2b470e00,
0x29480f00,
0x28481000,
0x27481100,
0x26491100,
0x25491200,
0x24491300,
0x234a1300,
0x224a1400,
0x214a1500,
0x204a1600,
0x1f4b1600,
0x1e4b1700,
0x1d4b1800,
0x1c4c1800,
0x1b4c1900,
0x1a4c1a00
};
static const unsigned int filt_coef3[] = { /* 3 point triangle */
0x20402000,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
void ge2d_canv_config(u32 index, ulong *addr, u32 *stride, u32 *stride_mode)
{
int i;
ge2d_log_dbg("%s:index=%d,addr=%lx,stride=%d\n",
__func__, index, addr[0], stride[0]);
if (ge2d_meson_dev.canvas_status == 1) {
if (index <= 2) {
ge2d_reg_write(GE2D_DST1_BADDR_CTRL + index * 2,
((addr[0] + 7) >> 3));
ge2d_reg_write(GE2D_DST1_STRIDE_CTRL + index * 2,
((stride[0] + 7) >> 3));
}
} else if (ge2d_meson_dev.canvas_status == 2) {
if (index <= 2) {
if (!ge2d_meson_dev.blk_stride_mode)
memset(stride_mode, 0, sizeof(u32) * MAX_PLANE);
switch (index) {
case GE2D_SRC1_INDEX:
for (i = 0; i < 3; i++) {
if (!addr[i] || !stride[i])
break;
ge2d_reg_write
(GE2D_C1_SRC1_BADDR_CTRL_Y + i * 2,
((addr[i] + 7) >> 3));
ge2d_reg_write
(GE2D_C1_SRC1_STRIDE_CTRL_Y + i * 2,
((stride[i] + 7) >> 3) |
(stride_mode[i] << 17));
}
break;
case GE2D_SRC2_INDEX:
ge2d_reg_write(GE2D_C1_SRC2_BADDR_CTRL,
((addr[0] + 7) >> 3));
ge2d_reg_write(GE2D_C1_SRC2_STRIDE_CTRL,
((stride[0] + 7) >> 3) |
(stride_mode[0] << 17));
break;
case GE2D_DST1_INDEX:
for (i = 0; i < 2; i++) {
if (!addr[i] || !stride[i])
break;
ge2d_reg_write
(GE2D_C1_DST1_BADDR_CTRL + i * 2,
((addr[i] + 7) >> 3));
ge2d_reg_write
(GE2D_C1_DST1_STRIDE_CTRL + i * 2,
((stride[i] + 7) >> 3) |
(stride_mode[i] << 17));
}
break;
}
}
}
}
static void get_canvas_info(u32 canvas_index, ulong *addr, u32 *stride,
u32 *stride_mode)
{
struct canvas_s canvas;
int i, tmp_index = 0;
if (!addr || !stride || !stride_mode) {
ge2d_log_err("get canvas info error\n");
return;
}
for (i = 0; i < 3 ; i++) {
tmp_index = (canvas_index >> (i * 8)) & 0xff;
if (tmp_index) {
canvas_read(tmp_index, &canvas);
addr[i] = canvas.addr;
stride[i] = canvas.width;
stride_mode[i] = canvas.blkmode;
}
}
}
void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg)
{
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->urgent_en, 10, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->ddr_burst_size_y, 20, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->ddr_burst_size_cb, 18, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->ddr_burst_size_cr, 16, 2);
if (ge2d_meson_dev.canvas_status) {
/* if virtual canvas is used, get info from it */
if (cfg->canaddr)
get_canvas_info(cfg->canaddr, cfg->phy_addr,
cfg->stride, cfg->stride_mode);
ge2d_canv_config(GE2D_SRC1_INDEX,
cfg->phy_addr,
cfg->stride,
cfg->stride_mode);
} else {
ge2d_reg_write(GE2D_SRC1_CANVAS,
((cfg->canaddr & 0xff) << 24) |
(((cfg->canaddr >> 8) & 0xff) << 16) |
(((cfg->canaddr >> 16) & 0xff) << 8));
}
ge2d_reg_set_bits(GE2D_GEN_CTRL0,
((cfg->x_yc_ratio << 1) | cfg->y_yc_ratio),
10, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->sep_en, 0, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->endian, 7, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->color_map, 3, 4);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->format, 0, 2);
if (ge2d_meson_dev.deep_color == 1)
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->deep_color, 2, 1);
if (ge2d_meson_dev.canvas_status == 1) {
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->mult_rounding, 18, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->alpha_conv_mode0, 31, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->alpha_conv_mode1, 10, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->color_conv_mode0, 30, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->color_conv_mode1, 26, 1);
}
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->mode_8b_sel, 5, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->lut_en, 3, 1);
ge2d_reg_write(GE2D_SRC1_DEF_COLOR, cfg->def_color);
if (cfg->x_yc_ratio)
/* horizontal formatter enable */
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, 1, 18, 1);
else
/* horizontal formatter disable */
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, 0, 18, 1);
if (cfg->y_yc_ratio)
/* vertical formatter enable */
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, 1, 16, 1);
else
/* vertical formatter disable */
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, 0, 16, 1);
}
void ge2d_set_src1_scale_coef(unsigned int v_filt_type,
unsigned int h_filt_type)
{
int i;
/* write vert filter coefs */
ge2d_reg_write(GE2D_SCALE_COEF_IDX, 0x0000);
if (v_filt_type == FILTER_TYPE_GAU0 ||
v_filt_type == FILTER_TYPE_GAU0_BOT ||
v_filt_type == FILTER_TYPE_GAU1 ||
h_filt_type == FILTER_TYPE_GAU0 ||
h_filt_type == FILTER_TYPE_GAU0_BOT ||
h_filt_type == FILTER_TYPE_GAU1)
gaul_filter_used = 1;
else
gaul_filter_used = 0;
for (i = 0; i < 33; i++) {
if (v_filt_type == FILTER_TYPE_BICUBIC) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef0[i]);
} else if (v_filt_type == FILTER_TYPE_BILINEAR) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef1[i]);
} else if (v_filt_type == FILTER_TYPE_TRIANGLE) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef2[i]);
} else if (v_filt_type == FILTER_TYPE_GAU0) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef_gau0[i]);
} else if (v_filt_type == FILTER_TYPE_GAU0_BOT) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef_gau0_bot[i]);
} else if (v_filt_type == FILTER_TYPE_GAU1) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef_gau1[i]);
} else {
/* TODO */
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef3[i]);
}
}
/* write horz filter coefs */
ge2d_reg_write(GE2D_SCALE_COEF_IDX, 0x0100);
for (i = 0; i < 33; i++) {
if (h_filt_type == FILTER_TYPE_BICUBIC) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef0[i]);
} else if (h_filt_type == FILTER_TYPE_BILINEAR) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef1[i]);
} else if (h_filt_type == FILTER_TYPE_TRIANGLE) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef2[i]);
} else if (h_filt_type == FILTER_TYPE_GAU0) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef_gau0[i]);
} else if (h_filt_type == FILTER_TYPE_GAU0_BOT) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef_gau0_bot[i]);
} else if (h_filt_type == FILTER_TYPE_GAU1) {
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef_gau1[i]);
} else {
/* TODO */
ge2d_reg_write(GE2D_SCALE_COEF, filt_coef3[i]);
}
}
}
void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg)
{
ge2d_reg_write(GE2D_SRC1_CLIPX_START_END,
(cfg->clipx_start_ex << 31) |
(cfg->clipx_start << 16) |
(cfg->clipx_end_ex << 15) |
(cfg->clipx_end << 0)
);
ge2d_reg_write(GE2D_SRC1_CLIPY_START_END,
(cfg->clipy_start_ex << 31) |
(cfg->clipy_start << 16) |
(cfg->clipy_end_ex << 15) |
(cfg->clipy_end << 0)
);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->pic_struct, 1, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, (cfg->fill_mode & 0x1), 4, 1);
ge2d_reg_set_bits(GE2D_SRC_OUTSIDE_ALPHA,
((cfg->fill_mode & 0x2) << 7) |
cfg->outside_alpha, 0, 9);
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, cfg->chfmt_rpt_pix, 19, 1);
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, cfg->cvfmt_rpt_pix, 17, 1);
}
void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg)
{
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->urgent_en, 9, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->ddr_burst_size, 22, 2);
if (ge2d_meson_dev.canvas_status) {
/* if virtual canvas is used, get info from it */
if (cfg->src2_canaddr)
get_canvas_info(cfg->src2_canaddr, cfg->src2_phyaddr,
cfg->src2_stride,
cfg->src2_stride_mode);
if (cfg->dst_canaddr)
get_canvas_info(cfg->dst_canaddr, cfg->dst_phyaddr,
cfg->dst_stride, cfg->dst_stride_mode);
ge2d_canv_config(GE2D_SRC2_INDEX,
cfg->src2_phyaddr,
cfg->src2_stride,
cfg->src2_stride_mode);
ge2d_canv_config(GE2D_DST1_INDEX,
cfg->dst_phyaddr,
cfg->dst_stride,
cfg->dst_stride_mode);
} else {
/* only for m6 and later chips. */
ge2d_reg_write(GE2D_SRC2_DST_CANVAS, (cfg->src2_canaddr << 8) |
((cfg->dst_canaddr & 0xff) << 0) |
((cfg->dst_canaddr & 0xff00) << 8)
);
}
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->src2_endian, 15, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->src2_color_map, 11, 4);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->src2_format, 8, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->dst_endian, 23, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->dst_color_map, 19, 4);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->dst_format, 16, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->src2_mode_8b_sel, 15, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->dst_mode_8b_sel, 24, 2);
if (ge2d_meson_dev.dst_repeat)
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->dst_rpt, 17, 6);
ge2d_reg_set_bits(GE2D_GEN_CTRL3, cfg->dst2_pixel_byte_width, 16, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL3, cfg->dst2_color_map, 19, 4);
ge2d_reg_set_bits(GE2D_GEN_CTRL3, cfg->dst2_discard_mode, 10, 4);
/* ge2d_reg_set_bits (GE2D_GEN_CTRL3, 1, 0, 1); */
ge2d_reg_set_bits(GE2D_GEN_CTRL3, cfg->dst2_enable, 8, 1);
ge2d_reg_write(GE2D_SRC2_DEF_COLOR, cfg->src2_def_color);
}
void ge2d_set_src2_dst_gen(struct ge2d_src2_dst_gen_s *cfg,
struct ge2d_cmd_s *cmd)
{
unsigned int widtho, heighto;
unsigned int is_rotate = cmd->dst_xy_swap ? 1 : 0;
unsigned int is_blend = cmd->cmd_op == IS_BLEND ? 1 : 0;
widtho = is_rotate ? (cfg->dst_clipy_end - cfg->dst_clipy_start + 1) :
(cfg->dst_clipx_end - cfg->dst_clipx_start + 1);
heighto = is_rotate ? (cfg->dst_clipx_end - cfg->dst_clipx_start + 1) :
(cfg->dst_clipy_end - cfg->dst_clipy_start + 1);
/* in blend case, if src2_repeat is support, use output W H to set */
if (is_blend && ge2d_meson_dev.src2_repeat) {
ge2d_reg_write(GE2D_SRC2_CLIPX_START_END,
(cfg->src2_clipx_start << 16) |
((widtho - 1) << 0)
);
ge2d_reg_write(GE2D_SRC2_CLIPY_START_END,
(cfg->src2_clipy_start << 16) |
((heighto - 1) << 0)
);
} else {
ge2d_reg_write(GE2D_SRC2_CLIPX_START_END,
(cfg->src2_clipx_start << 16) |
(cfg->src2_clipx_end << 0)
);
ge2d_reg_write(GE2D_SRC2_CLIPY_START_END,
(cfg->src2_clipy_start << 16) |
(cfg->src2_clipy_end << 0)
);
}
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->src2_pic_struct, 12, 2);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, (cfg->src2_fill_mode & 0x1), 14, 1);
ge2d_reg_set_bits(GE2D_SRC_OUTSIDE_ALPHA,
((cfg->src2_fill_mode & 0x2) << 7) |
cfg->src2_outside_alpha, 16, 9);
ge2d_reg_write(GE2D_DST_CLIPX_START_END,
(cfg->dst_clipx_start << 16) |
(cfg->dst_clipx_end << 0)
);
ge2d_reg_write(GE2D_DST_CLIPY_START_END,
(cfg->dst_clipy_start << 16) |
(cfg->dst_clipy_end << 0)
);
ge2d_reg_set_bits(GE2D_GEN_CTRL0, cfg->dst_clip_mode, 23, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->dst_pic_struct, 14, 2);
}
void ge2d_set_dp_gen(struct ge2d_config_s *config)
{
struct ge2d_dp_gen_s *cfg = &config->dp_gen;
unsigned int antiflick_color_filter_n1[] = {0, 8, 16, 32};
unsigned int antiflick_color_filter_n2[] = {128, 112, 96, 64};
unsigned int antiflick_color_filter_n3[] = {0, 8, 16, 32};
unsigned int antiflick_color_filter_th[] = {8, 16, 64};
unsigned int antiflick_alpha_filter_n1[] = {0, 8, 16, 32};
unsigned int antiflick_alpha_filter_n2[] = {128, 112, 96, 64};
unsigned int antiflick_alpha_filter_n3[] = {0, 8, 16, 32};
unsigned int antiflick_alpha_filter_th[] = {8, 16, 64};
unsigned int matrix_total = 1, i = 0;
unsigned int matrix_base_addr;
unsigned int matrix_pre_offset;
unsigned int matrix_coef00_01;
unsigned int matrix_coef02_10;
unsigned int matrix_coef11_12;
unsigned int matrix_coef20_21;
unsigned int matrix_coef22_ctrl;
unsigned int matrix_offset;
unsigned char matrix_using = 0;
unsigned char matrix_en = 0;
if (cfg->conv_matrix_en) {
cfg->antiflick_ycbcr_rgb_sel = 0; /* 0: yuv2rgb 1:rgb2rgb */
cfg->antiflick_cbcr_en = 1;
cfg->antiflick_r_coef = 0;
cfg->antiflick_g_coef = 0;
cfg->antiflick_b_coef = 0;
} else {
cfg->antiflick_ycbcr_rgb_sel = 1; /* 0: yuv2rgb 1:rgb2rgb */
cfg->antiflick_cbcr_en = 1;
cfg->antiflick_r_coef = 0x42; /* 0.257 */
cfg->antiflick_g_coef = 0x81; /* 0.504 */
cfg->antiflick_b_coef = 0x19; /* 0.098 */
}
memcpy(cfg->antiflick_color_filter_n1, antiflick_color_filter_n1,
4 * sizeof(unsigned int));
memcpy(cfg->antiflick_color_filter_n2, antiflick_color_filter_n2,
4 * sizeof(unsigned int));
memcpy(cfg->antiflick_color_filter_n3, antiflick_color_filter_n3,
4 * sizeof(unsigned int));
memcpy(cfg->antiflick_color_filter_th, antiflick_color_filter_th,
3 * sizeof(unsigned int));
memcpy(cfg->antiflick_alpha_filter_n1, antiflick_alpha_filter_n1,
4 * sizeof(unsigned int));
memcpy(cfg->antiflick_alpha_filter_n2, antiflick_alpha_filter_n2,
4 * sizeof(unsigned int));
memcpy(cfg->antiflick_alpha_filter_n3, antiflick_alpha_filter_n3,
4 * sizeof(unsigned int));
memcpy(cfg->antiflick_alpha_filter_th, antiflick_alpha_filter_th,
3 * sizeof(unsigned int));
cfg->src1_vsc_bank_length = 4;
cfg->src1_hsc_bank_length = 4;
ge2d_reg_set_bits(GE2D_SC_MISC_CTRL,
((cfg->src1_hsc_rpt_ctrl << 9) |
(cfg->src1_vsc_rpt_ctrl << 8) |
(cfg->src1_vsc_phase0_always_en << 7) |
(cfg->src1_vsc_bank_length << 4) |
(cfg->src1_hsc_phase0_always_en << 3) |
(cfg->src1_hsc_bank_length << 0)), 0, 10);
ge2d_reg_set_bits(GE2D_SC_MISC_CTRL,
((cfg->src1_vsc_nearest_en << 1) |
(cfg->src1_hsc_nearest_en << 0)), 29, 2);
if (cfg->antiflick_en == 1) {
/* Wr(GE2D_ANTIFLICK_CTRL0, 0x81000100); */
ge2d_reg_write(GE2D_ANTIFLICK_CTRL0, 0x80000000);
ge2d_reg_write
(GE2D_ANTIFLICK_CTRL1,
(cfg->antiflick_ycbcr_rgb_sel << 25) |
(cfg->antiflick_cbcr_en << 24) |
((cfg->antiflick_r_coef & 0xff) << 16) |
((cfg->antiflick_g_coef & 0xff) << 8) |
((cfg->antiflick_b_coef & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_COLOR_FILT0,
((cfg->antiflick_color_filter_th[0] & 0xff) << 24) |
((cfg->antiflick_color_filter_n3[0] & 0xff) << 16) |
((cfg->antiflick_color_filter_n2[0] & 0xff) << 8) |
((cfg->antiflick_color_filter_n1[0] & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_COLOR_FILT1,
((cfg->antiflick_color_filter_th[1] & 0xff) << 24) |
((cfg->antiflick_color_filter_n3[1] & 0xff) << 16) |
((cfg->antiflick_color_filter_n2[1] & 0xff) << 8) |
((cfg->antiflick_color_filter_n1[1] & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_COLOR_FILT2,
((cfg->antiflick_color_filter_th[2] & 0xff) << 24) |
((cfg->antiflick_color_filter_n3[2] & 0xff) << 16) |
((cfg->antiflick_color_filter_n2[2] & 0xff) << 8) |
((cfg->antiflick_color_filter_n1[2] & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_COLOR_FILT3,
((cfg->antiflick_color_filter_n3[3] & 0xff) << 16) |
((cfg->antiflick_color_filter_n2[3] & 0xff) << 8) |
((cfg->antiflick_color_filter_n1[3] & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_ALPHA_FILT0,
((cfg->antiflick_alpha_filter_th[0] & 0xff) << 24) |
((cfg->antiflick_alpha_filter_n3[0] & 0xff) << 16) |
((cfg->antiflick_alpha_filter_n2[0] & 0xff) << 8) |
((cfg->antiflick_alpha_filter_n1[0] & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_ALPHA_FILT1,
((cfg->antiflick_alpha_filter_th[1] & 0xff) << 24) |
((cfg->antiflick_alpha_filter_n3[1] & 0xff) << 16) |
((cfg->antiflick_alpha_filter_n2[1] & 0xff) << 8) |
((cfg->antiflick_alpha_filter_n1[1] & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_ALPHA_FILT2,
((cfg->antiflick_alpha_filter_th[2] & 0xff) << 24) |
((cfg->antiflick_alpha_filter_n3[2] & 0xff) << 16) |
((cfg->antiflick_alpha_filter_n2[2] & 0xff) << 8) |
((cfg->antiflick_alpha_filter_n1[2] & 0xff) << 0)
);
ge2d_reg_write
(GE2D_ANTIFLICK_ALPHA_FILT3,
((cfg->antiflick_alpha_filter_n3[3] & 0xff) << 16) |
((cfg->antiflick_alpha_filter_n2[3] & 0xff) << 8) |
((cfg->antiflick_alpha_filter_n1[3] & 0xff) << 0)
);
} else {
ge2d_reg_set_bits(GE2D_ANTIFLICK_CTRL0, 0, 31, 1);
}
if (ge2d_meson_dev.adv_matrix)
matrix_total = 3;
for (i = 0; i < matrix_total; i++) {
switch (i) {
case 0:
matrix_using = cfg->use_matrix_default;
matrix_en = cfg->conv_matrix_en;
matrix_base_addr = GE2D_MATRIX_PRE_OFFSET;
break;
case 1:
matrix_using = cfg->use_matrix_default_src2;
matrix_en = cfg->conv_matrix_en_src2;
matrix_base_addr = GE2D_MATRIX2_PRE_OFFSET;
break;
case 2:
matrix_using = cfg->use_matrix_default_dst;
matrix_en = cfg->conv_matrix_en_dst;
matrix_base_addr = GE2D_MATRIX3_PRE_OFFSET;
break;
}
matrix_pre_offset = matrix_base_addr++;
matrix_coef00_01 = matrix_base_addr++;
matrix_coef02_10 = matrix_base_addr++;
matrix_coef11_12 = matrix_base_addr++;
matrix_coef20_21 = matrix_base_addr++;
matrix_coef22_ctrl = matrix_base_addr++;
matrix_offset = matrix_base_addr;
if (matrix_using & MATRIX_CUSTOM) {
struct ge2d_matrix_s *matrix = &config->matrix_custom;
ge2d_log_dbg("using matrix_custom\n");
cfg->matrix_coef[0] = matrix->coef0;
cfg->matrix_coef[1] = matrix->coef1;
cfg->matrix_coef[2] = matrix->coef2;
cfg->matrix_coef[3] = matrix->coef3;
cfg->matrix_coef[4] = matrix->coef4;
cfg->matrix_coef[5] = matrix->coef5;
cfg->matrix_coef[6] = matrix->coef6;
cfg->matrix_coef[7] = matrix->coef7;
cfg->matrix_coef[8] = matrix->coef8;
cfg->matrix_offset[0] = matrix->offset0;
cfg->matrix_offset[1] = matrix->offset1;
cfg->matrix_offset[2] = matrix->offset2;
cfg->matrix_sat_in_en = matrix->sat_in_en;
ge2d_reg_write(matrix_pre_offset,
(matrix->pre_offset0 << 20) |
(matrix->pre_offset1 << 10) |
matrix->pre_offset2);
} else {
if (matrix_using & MATRIX_YCC_TO_RGB) {
/* ycbcr(16-235) to rgb(0-255) */
cfg->matrix_coef[0] = 0x4a8;
cfg->matrix_coef[1] = 0;
cfg->matrix_coef[2] = 0x662;
cfg->matrix_coef[3] = 0x4a8;
cfg->matrix_coef[4] = 0x1e6f;
cfg->matrix_coef[5] = 0x1cbf;
cfg->matrix_coef[6] = 0x4a8;
cfg->matrix_coef[7] = 0x811;
cfg->matrix_coef[8] = 0x0;
cfg->matrix_offset[0] = 0;
cfg->matrix_offset[1] = 0;
cfg->matrix_offset[2] = 0;
cfg->matrix_sat_in_en = 1;
cfg->matrix_minus_16_ctrl = 0x4;
cfg->matrix_sign_ctrl = 0x3;
} else if (matrix_using & MATRIX_RGB_TO_YCC) {
if (matrix_using & MATRIX_BT_709) {
/* VDIN_MATRIX_RGB_YUV709 */
/* 0 0.183 0.614 0.062 16 */
/* 0 -0.101 -0.338 0.439 128 */
/* 0 0.439 -0.399 -0.04 128 */
cfg->matrix_coef[0] = 0xbb;
cfg->matrix_coef[1] = 0x275;
cfg->matrix_coef[2] = 0x3f;
cfg->matrix_coef[3] = 0x1f99;
cfg->matrix_coef[4] = 0x1ea6;
cfg->matrix_coef[5] = 0x1c2;
cfg->matrix_coef[6] = 0x1c2;
cfg->matrix_coef[7] = 0x1e67;
cfg->matrix_coef[8] = 0x1fd7;
} else {
/* rgb(0-255) to ycbcr(16-235) */
/* 0.257 0.504 0.098 */
/* -0.148 -0.291 0.439 */
/* 0.439 -0.368 -0.071 */
cfg->matrix_coef[0] = 0x107;
cfg->matrix_coef[1] = 0x204;
cfg->matrix_coef[2] = 0x64;
cfg->matrix_coef[3] = 0x1f68;
cfg->matrix_coef[4] = 0x1ed6;
cfg->matrix_coef[5] = 0x1c2;
cfg->matrix_coef[6] = 0x1c2;
cfg->matrix_coef[7] = 0x1e87;
cfg->matrix_coef[8] = 0x1fb7;
}
cfg->matrix_offset[0] = 16;
cfg->matrix_offset[1] = 128;
cfg->matrix_offset[2] = 128;
cfg->matrix_sat_in_en = 0;
cfg->matrix_minus_16_ctrl = 0;
cfg->matrix_sign_ctrl = 0;
} else if (matrix_using &
MATRIX_FULL_RANGE_YCC_TO_RGB) {
/* ycbcr (0-255) to rgb(0-255) */
/* 1, 0, 1.402 */
/* 1, -0.34414, -0.71414 */
/* 1, 1.772 0 */
cfg->matrix_coef[0] = 0x400;
cfg->matrix_coef[1] = 0;
cfg->matrix_coef[2] = 0x59c;
cfg->matrix_coef[3] = 0x400;
cfg->matrix_coef[4] = 0x1ea0;
cfg->matrix_coef[5] = 0x1d25;
cfg->matrix_coef[6] = 0x400;
cfg->matrix_coef[7] = 0x717;
cfg->matrix_coef[8] = 0;
cfg->matrix_offset[0] = 0;
cfg->matrix_offset[1] = 0;
cfg->matrix_offset[2] = 0;
cfg->matrix_sat_in_en = 0;
cfg->matrix_minus_16_ctrl = 0;
cfg->matrix_sign_ctrl = 0x3;
} else if (matrix_using &
MATRIX_RGB_TO_FULL_RANGE_YCC) {
cfg->matrix_coef[0] = 0x132;
cfg->matrix_coef[1] = 0x259;
cfg->matrix_coef[2] = 0x75;
cfg->matrix_coef[3] = 0x1f53;
cfg->matrix_coef[4] = 0x1ead;
cfg->matrix_coef[5] = 0x200;
cfg->matrix_coef[6] = 0x200;
cfg->matrix_coef[7] = 0x1e53;
cfg->matrix_coef[8] = 0x1fad;
cfg->matrix_offset[0] = 0;
cfg->matrix_offset[1] = 128;
cfg->matrix_offset[2] = 128;
cfg->matrix_sat_in_en = 0;
cfg->matrix_minus_16_ctrl = 0;
cfg->matrix_sign_ctrl = 0;
} else if (matrix_using & MATRIX_SIGNED) {
cfg->matrix_coef[0] = 0x400;
cfg->matrix_coef[1] = 0;
cfg->matrix_coef[2] = 0;
cfg->matrix_coef[3] = 0;
cfg->matrix_coef[4] = 0x400;
cfg->matrix_coef[5] = 0;
cfg->matrix_coef[6] = 0;
cfg->matrix_coef[7] = 0;
cfg->matrix_coef[8] = 0x400;
cfg->matrix_offset[0] = 384; /* -128 */
cfg->matrix_offset[1] = 384; /* -128 */
cfg->matrix_offset[2] = 384; /* -128 */
cfg->matrix_sat_in_en = 0;
cfg->matrix_minus_16_ctrl = 0;
cfg->matrix_sign_ctrl = 0;
}
if (cfg->matrix_minus_16_ctrl)
ge2d_reg_set_bits(matrix_pre_offset,
0x1f0, 20, 9);
else
ge2d_reg_set_bits(matrix_pre_offset, 0, 20, 9);
if (cfg->matrix_sign_ctrl & 3)
ge2d_reg_set_bits(matrix_pre_offset,
((0x180 << 10) | 0x180),
0, 20);
else
ge2d_reg_set_bits(matrix_pre_offset, 0, 0, 20);
}
ge2d_reg_write(matrix_coef00_01,
(cfg->matrix_coef[0] << 16) |
(cfg->matrix_coef[1] << 0)
);
ge2d_reg_write(matrix_coef02_10,
(cfg->matrix_coef[2] << 16) |
(cfg->matrix_coef[3] << 0)
);
ge2d_reg_write(matrix_coef11_12,
(cfg->matrix_coef[4] << 16) |
(cfg->matrix_coef[5] << 0)
);
ge2d_reg_write(matrix_coef20_21,
(cfg->matrix_coef[6] << 16) |
(cfg->matrix_coef[7] << 0)
);
ge2d_reg_write(matrix_coef22_ctrl,
(cfg->matrix_coef[8] << 16) |
(cfg->matrix_sat_in_en << 7) |
(matrix_en << 0)
);
ge2d_reg_write(matrix_offset,
(cfg->matrix_offset[0] << 20) |
(cfg->matrix_offset[1] << 10) |
(cfg->matrix_offset[2] << 0)
);
}
if (ge2d_meson_dev.dst_sign_mode && cfg->conv_matrix_en_dst)
ge2d_reg_set_bits(GE2D_MATRIX3_COEF22_CTRL,
cfg->dst_signed_mode, 6, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->src1_gb_alpha, 0, 8);
ge2d_reg_set_bits(GE2D_GEN_CTRL2,
cfg->src1_gb_alpha_en, 29, 1);
#ifdef CONFIG_GE2D_SRC2
if (ge2d_meson_dev.src2_alp == 1) {
ge2d_reg_set_bits(GE2D_GEN_CTRL5, cfg->src2_gb_alpha, 0, 8);
ge2d_reg_set_bits(GE2D_GEN_CTRL5,
cfg->src2_gb_alpha_en, 8, 1);
}
#endif
ge2d_reg_write(GE2D_ALU_CONST_COLOR, cfg->alu_const_color);
ge2d_reg_write(GE2D_SRC1_KEY, cfg->src1_key);
ge2d_reg_write(GE2D_SRC1_KEY_MASK, cfg->src1_key_mask);
ge2d_reg_write(GE2D_SRC2_KEY, cfg->src2_key);
ge2d_reg_write(GE2D_SRC2_KEY_MASK, cfg->src2_key_mask);
ge2d_reg_write(GE2D_DST_BITMASK, cfg->bitmask);
ge2d_reg_set_bits(GE2D_GEN_CTRL0,
((cfg->bytemask_only << 5) |
(cfg->bitmask_en << 4) |
(cfg->src2_key_en << 3) |
(cfg->src2_key_mode << 2) |
(cfg->src1_key_en << 1) |
(cfg->src1_key_mode << 0)), 26, 6);
}
int ge2d_cmd_fifo_full(void)
{
return ge2d_reg_read(GE2D_STATUS0) & (1 << 1);
}
void ge2d_set_cmd(struct ge2d_cmd_s *cfg)
{
unsigned int widthi, heighti, tmp_widthi, tmp_heighti, widtho, heighto;
unsigned int multo;
unsigned int x_extra_bit_start = 0, x_extra_bit_end = 0;
unsigned int y_extra_bit_start = 0, y_extra_bit_end = 0;
unsigned int x_chr_phase = 0, y_chr_phase = 0;
unsigned int x_yc_ratio, y_yc_ratio;
unsigned int src2_x_interp_ctrl = 0; /* interpolation mode */
unsigned int src2_x_repeat = 0, src2_y_repeat = 0;
int sc_prehsc_en, sc_prevsc_en;
int rate_w = 10, rate_h = 10;
/* expand src region with one line. */
unsigned int src1_y_end = cfg->src1_y_end + 1;
struct ge2d_queue_item_s *queue_item = NULL;
unsigned int mem_secure = 0;
while ((ge2d_reg_read(GE2D_STATUS0) & (1 << 1)))
;
x_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 11, 1);
y_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 10, 1);
/* src:yuv , dst: rgb */
if ((cfg->src1_fmt & GE2D_FORMAT_YUV) &&
((cfg->dst_fmt & GE2D_FORMAT_YUV) == 0)) {
if (x_yc_ratio) {
if ((cfg->src1_x_rev + cfg->dst_x_rev) == 1) {
x_extra_bit_start = 3;
x_extra_bit_end = 2;
x_chr_phase = 0x4c;
} else {
x_extra_bit_start = 2;
x_extra_bit_end = 3;
x_chr_phase = 0xc4;
}
}
if (y_yc_ratio) {
if ((cfg->src1_y_rev + cfg->dst_y_rev) == 1) {
y_extra_bit_start = 3;
y_extra_bit_end = 2;
y_chr_phase = 0x4c;
} else {
y_extra_bit_start = 2;
y_extra_bit_end = 3;
y_chr_phase = 0xc4;
}
}
} else {
if (x_yc_ratio) {
if ((cfg->src1_x_rev + cfg->dst_x_rev) == 1) {
x_extra_bit_start = 3;
x_extra_bit_end = 2;
x_chr_phase = 0x08;
} else {
x_extra_bit_start = 2;
x_extra_bit_end = 3;
x_chr_phase = 0x08;
}
}
if (y_yc_ratio) {
if ((cfg->src1_y_rev + cfg->dst_y_rev) == 1) {
y_extra_bit_start = 3;
y_extra_bit_end = 2;
y_chr_phase = 0x4c;
} else {
y_extra_bit_start = 2;
y_extra_bit_end = 3;
y_chr_phase = 0x4c;
}
}
}
ge2d_reg_write(GE2D_SRC1_X_START_END,
(x_extra_bit_start << 30) | /* x start extra */
((cfg->src1_x_start & 0x3fff) << 16) |
(x_extra_bit_end << 14) | /* x end extra */
((cfg->src1_x_end & 0x3fff) << 0)
);
ge2d_reg_write(GE2D_SRC1_Y_START_END,
(y_extra_bit_start << 30) | /* y start extra */
((cfg->src1_y_start & 0x3fff) << 16) |
(y_extra_bit_end << 14) | /* y end extra */
((src1_y_end & 0x3fff) << 0)
);
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, x_chr_phase, 8, 8);
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, y_chr_phase, 0, 8);
if (((cfg->src1_x_end - cfg->src1_x_start) ==
(cfg->dst_x_end - cfg->dst_x_start)) &&
((cfg->src1_y_end - cfg->src1_y_start) ==
(cfg->dst_y_end - cfg->dst_y_start))) {
/* set chroma formatter repeat mode */
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, 1, 19, 1);
ge2d_reg_set_bits(GE2D_SRC1_FMT_CTRL, 1, 17, 1);
}
/* src1 scaler setting */
widthi = cfg->src1_x_end - cfg->src1_x_start + 1;
heighti = cfg->src1_y_end - cfg->src1_y_start + 1;
widtho = cfg->dst_xy_swap ? (cfg->dst_y_end - cfg->dst_y_start + 1) :
(cfg->dst_x_end - cfg->dst_x_start + 1);
heighto = cfg->dst_xy_swap ? (cfg->dst_x_end - cfg->dst_x_start + 1) :
(cfg->dst_y_end - cfg->dst_y_start + 1);
sc_prehsc_en = (widthi > widtho * 2) ? 1 : 0;
sc_prevsc_en = (heighti > heighto * 2) ? 1 : 0;
tmp_widthi = sc_prehsc_en ? ((widthi + 1) >> 1) : widthi;
tmp_heighti = sc_prevsc_en ? ((heighti + 1) >> 1) : heighti;
if (cfg->hsc_phase_step == 0)
cfg->hsc_phase_step = ((tmp_widthi << 18) / widtho) <<
6; /* width no more than 8192 */
if (cfg->vsc_phase_step == 0)
cfg->vsc_phase_step = ((tmp_heighti << 18) / heighto) <<
6;/* height no more than 8192 */
if (cfg->sc_hsc_en && cfg->hsc_div_en) {
unsigned int hsc_div_length;
hsc_div_length = (124 << 24) / cfg->hsc_phase_step;
/* in blend case, for chip after C2
* src2 repeat function needs hsc_div_length 8 alignment
*/
if (cfg->cmd_op == IS_BLEND && ge2d_meson_dev.src2_repeat)
hsc_div_length = (hsc_div_length + 7) & ~7;
cfg->hsc_div_length = hsc_div_length;
multo = cfg->hsc_phase_step * cfg->hsc_div_length;
cfg->hsc_adv_num = multo >> 24;
cfg->hsc_adv_phase = multo & 0xffffff;
}
if (!gaul_filter_used) {
if (widthi == 0 || heighti == 0) {
ge2d_log_err("wrong parameters, widthi=%d,heighti=%d\n",
widthi, heighti);
return;
}
rate_w = (widtho * 10) / widthi;
rate_h = (heighto * 10) / heighti;
if (rate_h == 10) {
/* not scaler case */
cfg->vsc_ini_phase = 0;
ge2d_reg_set_bits(GE2D_SC_MISC_CTRL,
((0 << 1) | (0 << 0)), 8, 2);
} else if (rate_h < 10) {
/* scaler down case */
cfg->sc_vsc_en = 1;
cfg->vsc_rpt_l0_num = 1;
if (rate_h != 0)
cfg->vsc_ini_phase =
0x5000000 / rate_h - 0x800000;
else
cfg->vsc_ini_phase = 0x5000000;
} else {
/* scaler up case */
cfg->sc_vsc_en = 1;
cfg->vsc_rpt_l0_num = 2;
cfg->vsc_ini_phase =
0x800000 + 0x5000000 / rate_h;
}
if (rate_w == 10) {
/* not scaler case */
cfg->hsc_ini_phase = 0;
ge2d_reg_set_bits(GE2D_SC_MISC_CTRL,
((0 << 1) | (0 << 0)), 8, 2);
} else if (rate_w < 10) {
/* scaler down case */
cfg->sc_hsc_en = 1;
cfg->hsc_rpt_p0_num = 1;
if (rate_w != 0)
cfg->hsc_ini_phase =
0x5000000 / rate_w - 0x800000;
else
cfg->hsc_ini_phase = 0x5000000;
} else {
/* scaler up case */
cfg->sc_hsc_en = 1;
cfg->hsc_rpt_p0_num = 2;
cfg->hsc_ini_phase =
0x800000 + 0x5000000 / rate_w;
}
/* expand src1/src2 color with 1 */
ge2d_reg_set_bits(GE2D_GEN_CTRL2, 1, 27, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL2, 1, 25, 1);
}
ge2d_log_dbg("rate_w=%d,rate_h=%d\n", rate_w, rate_h);
ge2d_reg_set_bits(GE2D_SC_MISC_CTRL,
((cfg->hsc_div_en << 17) |
(cfg->hsc_div_length << 4) |
(sc_prehsc_en << 3) |
(sc_prevsc_en << 2) |
(cfg->sc_vsc_en << 1) |
(cfg->sc_hsc_en << 0)), 11, 18);
ge2d_reg_write(GE2D_HSC_START_PHASE_STEP, cfg->hsc_phase_step);
ge2d_reg_write(GE2D_HSC_PHASE_SLOPE, cfg->hsc_phase_slope);
#ifdef CONFIG_GE2D_ADV_NUM
ge2d_reg_write(GE2D_HSC_ADV_CTRL,
(cfg->hsc_adv_num << 24) |
(cfg->hsc_adv_phase << 0)
);
if (cfg->hsc_adv_num > 255)
cfg->hsc_adv_num = cfg->hsc_adv_num >> 8;
else
cfg->hsc_adv_num = 0;
ge2d_reg_write(GE2D_HSC_INI_CTRL,
(cfg->hsc_rpt_p0_num << 29) |
(cfg->hsc_adv_num << 24) |
((cfg->hsc_ini_phase & 0xffffff) << 0)
);
#else
ge2d_reg_write(GE2D_HSC_ADV_CTRL,
(cfg->hsc_adv_num << 24) |
(cfg->hsc_adv_phase << 0)
);
ge2d_reg_write(GE2D_HSC_INI_CTRL,
(cfg->hsc_rpt_p0_num << 29) |
((cfg->hsc_ini_phase & 0xffffff) << 0)
);
#endif
ge2d_reg_write(GE2D_VSC_START_PHASE_STEP, cfg->vsc_phase_step);
ge2d_reg_write(GE2D_VSC_PHASE_SLOPE, cfg->vsc_phase_slope);
ge2d_reg_write(GE2D_VSC_INI_CTRL,
(cfg->vsc_rpt_l0_num << 29) |
(cfg->vsc_ini_phase << 0)
);
/* src2 scaler setting, just support 2^n repeat (n = 0, 1, 2 or 3) */
if (cfg->cmd_op == IS_BLEND && ge2d_meson_dev.src2_repeat) {
widthi = cfg->src2_x_end - cfg->src2_x_start + 1;
heighti = cfg->src2_y_end - cfg->src2_y_start + 1;
if (widthi == 0 || heighti == 0) {
ge2d_log_err("wrong parameters, widthi=%d,heighti=%d\n",
widthi, heighti);
return;
}
switch (widtho / widthi) {
case 0:
ge2d_log_err("src2_x scale down is not supported\n");
src2_x_interp_ctrl = 0;
src2_x_repeat = 0;
break;
case 1:
src2_x_interp_ctrl = 0;
src2_x_repeat = 0;
break;
case 2:
src2_x_interp_ctrl = 1;
src2_x_repeat = 1;
break;
case 4:
src2_x_interp_ctrl = 1;
src2_x_repeat = 2;
break;
case 8:
src2_x_interp_ctrl = 1;
src2_x_repeat = 3;
break;
default:
src2_x_interp_ctrl = 1;
src2_x_repeat = 3;
ge2d_log_err("src2_x scale up just support 2^n\n");
break;
}
switch (heighto / heighti) {
case 0:
ge2d_log_err("src2_y scale down is not supported\n");
src2_y_repeat = 0;
break;
case 1:
src2_y_repeat = 0;
break;
case 2:
src2_y_repeat = 1;
break;
case 4:
src2_y_repeat = 2;
break;
case 8:
src2_y_repeat = 3;
break;
default:
src2_y_repeat = 3;
ge2d_log_err("src2_y scale up just support 2^n\n");
break;
}
ge2d_log_dbg("src2_x_interp_ctrl(%d), src2_x_repeat(%d)\n",
src2_x_interp_ctrl, src2_x_repeat);
ge2d_log_dbg("src2_y_repeat(%d)\n", src2_y_repeat);
}
/* in blend case, if src2_repeat is support, use output W H to set */
if (cfg->cmd_op == IS_BLEND && ge2d_meson_dev.src2_repeat) {
ge2d_reg_write(GE2D_SRC2_X_START_END,
(cfg->src2_x_start << 16) |
((widtho - 1) << 0)
);
ge2d_reg_write(GE2D_SRC2_Y_START_END,
(cfg->src2_y_start << 16) |
((heighto - 1) << 0)
);
} else {
ge2d_reg_write(GE2D_SRC2_X_START_END,
(cfg->src2_x_start << 16) |
(cfg->src2_x_end << 0)
);
ge2d_reg_write(GE2D_SRC2_Y_START_END,
(cfg->src2_y_start << 16) |
(cfg->src2_y_end << 0)
);
}
ge2d_reg_write(GE2D_DST_X_START_END,
(cfg->dst_x_start << 16) |
(cfg->dst_x_end << 0)
);
ge2d_reg_write(GE2D_DST_Y_START_END,
(cfg->dst_y_start << 16) |
(cfg->dst_y_end << 0)
);
#ifdef CONFIG_GE2D_SRC2
if (ge2d_meson_dev.src2_alp == 1)
ge2d_reg_write(GE2D_ALU_OP_CTRL,
(cfg->src2_cmult_ad << 27) |
(cfg->src1_cmult_asel << 25) |
(cfg->src2_cmult_asel << 23) |
(cfg->color_blend_mode << 20) |
(cfg->color_src_blend_factor << 16) |
(((cfg->color_blend_mode == 5) ?
cfg->color_logic_op :
cfg->color_dst_blend_factor) << 12) |
(cfg->alpha_blend_mode << 8) |
(cfg->alpha_src_blend_factor << 4) |
(((cfg->alpha_blend_mode == 5) ?
cfg->alpha_logic_op :
cfg->alpha_dst_blend_factor) << 0)
);
else
#endif
ge2d_reg_write(GE2D_ALU_OP_CTRL,
(cfg->src1_cmult_asel << 25) |
(cfg->src2_cmult_asel << 24) |
(cfg->color_blend_mode << 20) |
(cfg->color_src_blend_factor << 16) |
(((cfg->color_blend_mode == 5) ?
cfg->color_logic_op :
cfg->color_dst_blend_factor) << 12) |
(cfg->alpha_blend_mode << 8) |
(cfg->alpha_src_blend_factor << 4) |
(((cfg->alpha_blend_mode == 5) ?
cfg->alpha_logic_op :
cfg->alpha_dst_blend_factor) << 0)
);
/* if true, disable bug fix about the dp_out_done/
* scale_out_done(test1823) hang issue when
* scaling down ratio is high.
*/
if (ge2d_meson_dev.hang_flag == 1)
ge2d_reg_set_bits(GE2D_GEN_CTRL4, cfg->hang_flag, 0, 1);
/* memory security setting */
queue_item = container_of(cfg, struct ge2d_queue_item_s, cmd);
if (ge2d_meson_dev.chip_type >= MESON_CPU_MAJOR_ID_SC2)
mem_secure = queue_item->config.mem_sec;
ge2d_log_dbg("secure mode:%d\n", mem_secure);
ge2d_reg_write(GE2D_CMD_CTRL,
(mem_secure << 28) |
(src2_x_interp_ctrl << 14) |
(src2_x_repeat << 12) |
(src2_y_repeat << 10) |
(cfg->src2_fill_color_en << 9) |
(cfg->src1_fill_color_en << 8) |
(cfg->dst_xy_swap << 7) |
(cfg->dst_x_rev << 6) |
(cfg->dst_y_rev << 5) |
(cfg->src2_x_rev << 4) |
(cfg->src2_y_rev << 3) |
(cfg->src1_x_rev << 2) |
(cfg->src1_y_rev << 1) |
1 << 0 /* start cmd */
);
cfg->release_flag |= START_FLAG;
}
void ge2d_wait_done(void)
{
while (ge2d_reg_read(GE2D_STATUS0) & 1)
;
}
bool ge2d_is_busy(void)
{
if (ge2d_reg_read(GE2D_STATUS0) & 1)
return true;
else
return false;
}
void ge2d_soft_rst(void)
{
ge2d_reg_set_bits(GE2D_GEN_CTRL1, 1, 31, 1);
ge2d_reg_set_bits(GE2D_GEN_CTRL1, 0, 31, 1);
}
void ge2d_set_gen(struct ge2d_gen_s *cfg)
{
ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->interrupt_ctrl, 24, 2);
ge2d_reg_write(GE2D_DP_ONOFF_CTRL,
(cfg->dp_onoff_mode << 31) |
(cfg->dp_on_cnt << 16) |
(cfg->vfmt_onoff_en << 15) |
(cfg->dp_off_cnt << 0)
);
if (ge2d_meson_dev.fifo == 1) {
ge2d_reg_set_bits(GE2D_GEN_CTRL4,
(cfg->bytes_per_burst << 12) |
(cfg->fifo_size << 10) |
(cfg->fifo_size << 8) |
(cfg->fifo_size << 6) |
(cfg->fifo_size << 4) |
(cfg->burst_ctrl << 2) |
(cfg->burst_ctrl),
16, 13);
}
}