blob: 7845e054a0f2c1e5fe6d8bd7dc95a66fd419e100 [file] [log] [blame]
/*
* drivers/amlogic/media/common/ge2d/ge2d_hw.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/types.h>
/* Amlogic Headers */
#include <linux/amlogic/cpu_version.h>
#include <linux/amlogic/media/ge2d/ge2d.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, u32 addr, u32 stride)
{
ge2d_log_dbg("ge2d_canv_config:index=%d,addr=%x,stride=%d\n",
index, addr, stride);
if (index <= 2) {
ge2d_reg_write(GE2D_DST1_BADDR_CTRL + index * 2,
((addr + 7) >> 3));
ge2d_reg_write(GE2D_DST1_STRIDE_CTRL + index * 2,
((stride + 7) >> 3));
}
}
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 == 1) {
ge2d_canv_config(GE2D_SRC1_INDEX,
cfg->phy_addr,
cfg->stride);
} 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 == 1) {
ge2d_canv_config(GE2D_SRC2_INDEX,
cfg->src2_phyaddr,
cfg->src2_stride);
ge2d_canv_config(GE2D_DST1_INDEX,
cfg->dst_phyaddr,
cfg->dst_stride);
} 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);
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)
{
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_dp_gen_s *cfg)
{
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};
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 (cfg->use_matrix_default == 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 (cfg->use_matrix_default == MATRIX_RGB_TO_YCC) {
/* 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 (cfg->use_matrix_default == 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 (cfg->use_matrix_default == 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;
}
if (cfg->matrix_minus_16_ctrl)
ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0x1f0, 20, 9);
else
ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0, 20, 9);
if (cfg->matrix_sign_ctrl & 3)
ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET,
((0x180 << 10) | 0x180), 0, 20);
else
ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0, 0, 20);
ge2d_reg_write(GE2D_MATRIX_COEF00_01,
(cfg->matrix_coef[0] << 16) |
(cfg->matrix_coef[1] << 0)
);
ge2d_reg_write(GE2D_MATRIX_COEF02_10,
(cfg->matrix_coef[2] << 16) |
(cfg->matrix_coef[3] << 0)
);
ge2d_reg_write(GE2D_MATRIX_COEF11_12,
(cfg->matrix_coef[4] << 16) |
(cfg->matrix_coef[5] << 0)
);
ge2d_reg_write(GE2D_MATRIX_COEF20_21,
(cfg->matrix_coef[6] << 16) |
(cfg->matrix_coef[7] << 0)
);
ge2d_reg_write(GE2D_MATRIX_COEF22_CTRL,
(cfg->matrix_coef[8] << 16) |
(cfg->matrix_sat_in_en << 7) |
#if 0
(cfg->matrix_minus_16_ctrl << 4) |
(cfg->matrix_sign_ctrl << 1) |
#endif
(cfg->conv_matrix_en << 0)
);
ge2d_reg_write(GE2D_MATRIX_OFFSET,
(cfg->matrix_offset[0] << 20) |
(cfg->matrix_offset[1] << 10) |
(cfg->matrix_offset[2] << 0)
);
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;
int sc_prehsc_en, sc_prevsc_en;
int rate_w = 10, rate_h = 10;
/* expand src region with two lines. */
unsigned int src1_y_end = cfg->src1_y_end + 2;
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);
}
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)
);
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)) {
cfg->hsc_div_length = (124 << 24) / cfg->hsc_phase_step;
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) {
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)
);
#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);
ge2d_reg_write(GE2D_CMD_CTRL,
(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->fifo_size << 26) |
(cfg->fifo_size << 24) |
(cfg->fifo_size << 22) |
(cfg->fifo_size << 20) |
(cfg->burst_ctrl << 18) |
(cfg->burst_ctrl << 16),
16, 12);
}
}