/*
|
* Allwinner SoCs display driver.
|
*
|
* Copyright (C) 2016 Allwinner.
|
*
|
* This file is licensed under the terms of the GNU General Public
|
* License version 2. This program is licensed "as is" without any
|
* warranty of any kind, whether express or implied.
|
*/
|
|
#include "de_hal.h"
|
|
#define EINK_DEBUG 0
|
static unsigned int g_device_fps[DE_NUM] = { 60 };
|
static bool g_de_blank[DE_NUM] = { false };
|
static unsigned int g_de_freq;
|
|
int de_update_device_fps(unsigned int sel, u32 fps)
|
{
|
g_device_fps[sel] = fps;
|
|
return 0;
|
}
|
|
/**
|
* Update clk rate of de, unit hz.
|
*/
|
int de_update_clk_rate(u32 rate)
|
{
|
g_de_freq = rate / 1000000;
|
|
return 0;
|
}
|
|
/**
|
* Get clk rate of de, unit hz.
|
*/
|
int de_get_clk_rate(void)
|
{
|
return g_de_freq * 1000000;
|
}
|
|
static int de_set_coarse(unsigned int sel, unsigned char chno, unsigned int fmt,
|
unsigned int lcd_fps, unsigned int lcd_height,
|
unsigned int de_freq_mhz, unsigned int ovl_w,
|
unsigned int ovl_h, unsigned int vsu_outw,
|
unsigned int vsu_outh, unsigned int *midyw,
|
unsigned int *midyh, struct scaler_para *fix_ypara,
|
struct scaler_para *fix_cpara)
|
{
|
int coarse_status;
|
unsigned int midcw, midch;
|
|
coarse_status =
|
de_rtmx_set_coarse_fac(sel, chno, fmt, lcd_fps, lcd_height,
|
de_freq_mhz, ovl_w, ovl_h, vsu_outw,
|
vsu_outh, midyw, midyh, &midcw, &midch);
|
de_vsu_recalc_scale_para(coarse_status, vsu_outw, vsu_outh, *midyw,
|
*midyh, midcw, midch, fix_ypara, fix_cpara);
|
|
return 0;
|
}
|
|
static int
|
de_calc_overlay_scaler_para(unsigned int screen_id,
|
unsigned char chn, unsigned char layno,
|
unsigned char *fmt,
|
struct disp_layer_config_data *data,
|
unsigned char (*premul)[LAYER_MAX_NUM_PER_CHN],
|
unsigned char *premode,
|
struct de_rect(*crop)[LAYER_MAX_NUM_PER_CHN],
|
struct de_rect(*layer)[LAYER_MAX_NUM_PER_CHN],
|
struct de_rect *bld_rect, unsigned int *ovlw,
|
unsigned int *ovlh, unsigned char *pen,
|
struct scaler_para *ovl_para,
|
struct scaler_para *ovl_cpara)
|
{
|
bool scaler_en;
|
unsigned char i, j, k, lay_en[CHN_NUM][LAYER_MAX_NUM_PER_CHN];
|
unsigned int midyw, midyh;
|
unsigned int lcd_fps = g_device_fps[screen_id];
|
unsigned int lcd_width = 1280, lcd_height = 720;
|
unsigned int de_freq_mhz = g_de_freq;
|
struct de_rect64 crop64[CHN_NUM][LAYER_MAX_NUM_PER_CHN];
|
struct de_rect frame[CHN_NUM][LAYER_MAX_NUM_PER_CHN];
|
static struct scaler_para para[CHN_NUM][LAYER_MAX_NUM_PER_CHN];
|
static struct scaler_para cpara[VI_CHN_NUM][LAYER_MAX_NUM_PER_CHN];
|
unsigned int vi_chn = de_feat_get_num_vi_chns(screen_id);
|
unsigned int scaler_num = de_feat_is_support_scale(screen_id);
|
|
de_rtmx_get_display_size(screen_id, &lcd_width, &lcd_height);
|
/* init para */
|
for (j = 0; j < vi_chn; j++)
|
memset((void *)cpara[j], 0x0,
|
layno * sizeof(struct scaler_para));
|
for (j = 0; j < chn; j++)
|
memset((void *)para[j], 0x0,
|
layno * sizeof(struct scaler_para));
|
|
/* get the original crop frame data */
|
for (j = 0, k = 0; j < chn; j++) {
|
for (i = 0; i < layno;) {
|
memcpy(&crop64[j][i], &data[k].config.info.fb.crop,
|
sizeof(struct disp_rect64));
|
memcpy(&frame[j][i], &data[k].config.info.screen_win,
|
sizeof(struct disp_rect));
|
lay_en[j][i] = data[k].config.enable;
|
premul[j][i] = data[k].config.info.fb.pre_multiply;
|
|
/* 3d mode */
|
if (data[k].config.info.fb.flags) {
|
memcpy(&crop64[j][i + 1],
|
&data[k].config.info.fb.crop,
|
sizeof(struct disp_rect64));
|
de_rtmx_get_3d_in_single_size(
|
(enum de_3d_in_mode)
|
data[k].config.info.fb.flags,
|
&crop64[j][i]);
|
if (data[k].config.info.b_trd_out) {
|
de_rtmx_get_3d_in_single_size(
|
(enum de_3d_in_mode) data[k].config.
|
info.fb.flags, &crop64[j][i + 1]);
|
de_rtmx_get_3d_out(frame[j][i],
|
lcd_width,
|
lcd_height,
|
(enum de_3d_out_mode)
|
data[k].config.info.
|
out_trd_mode,
|
&frame[j][i + 1]);
|
lay_en[j][i + 1] =
|
data[k].config.enable;
|
} else {
|
lay_en[j][i + 1] = 0;
|
}
|
premul[j][i + 1] =
|
data[k].config.info.fb.pre_multiply;
|
k += 2;
|
i += 2;
|
} else {
|
i++;
|
k++;
|
}
|
}
|
}
|
|
for (j = 0; j < vi_chn; j++) {
|
for (i = 0; i < layno; i++) {
|
if (lay_en[j][i])
|
de_vsu_calc_scaler_para(fmt[j], crop64[j][i],
|
frame[j][i],
|
&crop[j][i],
|
¶[j][i],
|
&cpara[j][i]);
|
}
|
}
|
|
for (j = vi_chn; j < chn; j++) {
|
for (i = 0; i < layno; i++) {
|
if (lay_en[j][i])
|
de_gsu_calc_scaler_para(crop64[j][i],
|
frame[j][i],
|
&crop[j][i],
|
¶[j][i]);
|
}
|
}
|
|
/* calculate the layer coordinate,
|
* overlay size & blending input coordinate
|
*/
|
for (j = 0; j < chn; j++) {
|
int gsu_sel = (j < vi_chn) ? 0 : 1;
|
|
pen[j] =
|
de_rtmx_calc_chnrect(lay_en[j], layno, frame[j], crop[j],
|
gsu_sel, para[j], layer[j],
|
&bld_rect[j], &ovlw[j], &ovlh[j]);
|
premode[j] = de_rtmx_get_premul_ctl(layno, premul[j]);
|
__inf("ovl_rect[%d]=<%d,%d>\n", j, ovlw[j], ovlh[j]);
|
__inf("bld_rect[%d]=<%d,%d,%d,%d>\n", j, bld_rect[j].x,
|
bld_rect[j].y, bld_rect[j].w, bld_rect[j].h);
|
}
|
|
/* get video overlay parameter for scaler */
|
for (j = 0; j < vi_chn; j++) {
|
__inf("fmt[%d]=%d, ovlw[%d]=%d,ovlh[%d]=%d, bld_rect[%d].w=%d, bld_rect[%d].h=%d\n",
|
j, fmt[j], j, ovlw[j], j, ovlh[j], j, bld_rect[j].w,
|
j, bld_rect[j].h);
|
scaler_en = 0x1;
|
if ((fmt[j] == 0) && (ovlw[j] == bld_rect[j].w)
|
&& (ovlh[j] == bld_rect[j].h)) {
|
scaler_en = 0x0;
|
}
|
if (scaler_en)
|
de_vsu_sel_ovl_scaler_para(lay_en[j], para[j], cpara[j],
|
&ovl_para[j], &ovl_cpara[j]);
|
|
/* recalculate overlay size, blending coordinate,
|
* blending size, layer coordinate
|
*/
|
de_recalc_ovl_bld_for_scale(scaler_en, lay_en[j], layno,
|
&ovl_para[j], layer[j],
|
&bld_rect[j], &ovlw[j], &ovlh[j], 0,
|
lcd_width, lcd_height);
|
|
de_set_coarse(screen_id, j, fmt[j], lcd_fps, lcd_height,
|
de_freq_mhz, ovlw[j], ovlh[j], bld_rect[j].w,
|
bld_rect[j].h, &midyw, &midyh, &ovl_para[j],
|
&ovl_cpara[j]);
|
de_vsu_set_para(screen_id, j, scaler_en, fmt[j], midyw, midyh,
|
bld_rect[j].w, bld_rect[j].h, &ovl_para[j],
|
&ovl_cpara[j]);
|
}
|
|
/* get ui overlay parameter for scaler */
|
for (j = vi_chn; j < scaler_num; j++) {
|
scaler_en = 0x1;
|
if ((ovlw[j] == bld_rect[j].w) && (ovlh[j] == bld_rect[j].h))
|
scaler_en = 0x0;
|
if (scaler_en)
|
de_gsu_sel_ovl_scaler_para(lay_en[j], para[j],
|
&ovl_para[j]);
|
|
/* recalculate overlay size, blending coordinate,
|
* blending size, layer coordinate
|
*/
|
de_recalc_ovl_bld_for_scale(scaler_en, lay_en[j], layno,
|
&ovl_para[j], layer[j],
|
&bld_rect[j], &ovlw[j], &ovlh[j], 1,
|
lcd_width, lcd_height);
|
|
de_gsu_set_para(screen_id, j, scaler_en, ovlw[j], ovlh[j],
|
bld_rect[j].w, bld_rect[j].h, &ovl_para[j]);
|
}
|
|
return 0;
|
}
|
|
int de_al_lyr_apply_direct_show(unsigned int screen_id,
|
struct disp_layer_config_data *data,
|
unsigned int layer_num, bool direct_show)
|
{
|
unsigned int display_width, display_height;
|
unsigned int i;
|
|
if (!direct_show)
|
return 0;
|
|
de_rtmx_get_display_size(screen_id, &display_width, &display_height);
|
|
for (i = 0; i < layer_num; i++, data++) {
|
struct disp_rect64 *crop64;
|
struct disp_rect crop;
|
struct disp_rect frame;
|
struct disp_rect *screen_win;
|
|
if (!data->config.enable)
|
continue;
|
|
crop64 = &data->config.info.fb.crop;
|
screen_win = &data->config.info.screen_win;
|
crop.x = crop64->x >> VSU_FB_FRAC_BITWIDTH;
|
crop.y = crop64->y >> VSU_FB_FRAC_BITWIDTH;
|
crop.width = crop64->width >> VSU_FB_FRAC_BITWIDTH;
|
crop.height = crop64->height >> VSU_FB_FRAC_BITWIDTH;
|
|
frame.x = 0;
|
frame.y = 0;
|
/*
|
* If source is larger than screen, crop the source.
|
* And if source is smaller than screen,
|
* make frame para center in the screen
|
*/
|
if (crop.width > display_width) {
|
crop.x = (crop.width - display_width) >> 1;
|
crop.width = display_width;
|
frame.x = 0;
|
} else {
|
crop.x = 0;
|
frame.x = (display_width - crop.width) >> 1;
|
}
|
|
if (crop.height > display_height) {
|
crop.y = (crop.height - display_height) >> 1;
|
crop.height = display_height;
|
frame.y = 0;
|
} else {
|
crop.y = 0;
|
crop.height = (crop.height >> 2) << 2;
|
frame.y = (display_height - crop.height) >> 1;
|
}
|
|
frame.width = crop.width;
|
frame.height = crop.height;
|
|
crop64->x = (long long)crop.x << VSU_FB_FRAC_BITWIDTH;
|
crop64->y = (long long)crop.y << VSU_FB_FRAC_BITWIDTH;
|
crop64->width = (unsigned long long)crop.width
|
<< VSU_FB_FRAC_BITWIDTH;
|
crop64->height = (unsigned long long)crop.height
|
<< VSU_FB_FRAC_BITWIDTH;
|
screen_win->x = frame.x;
|
screen_win->y = frame.y;
|
screen_win->width = frame.width;
|
screen_win->height = frame.height;
|
}
|
|
return 0;
|
}
|
|
static enum de_color_space __cs_transform(enum disp_color_space cs)
|
{
|
enum de_color_space cs_inner;
|
|
switch (cs) {
|
case DISP_BT709:
|
case DISP_BT709_F:
|
cs_inner = DE_BT709;
|
break;
|
case DISP_BT601:
|
case DISP_BT601_F:
|
cs_inner = DE_BT601;
|
break;
|
default:
|
cs_inner = DE_BT601;
|
break;
|
}
|
|
return cs_inner;
|
}
|
|
int de_al_lyr_apply(unsigned int screen_id, struct disp_layer_config_data *data,
|
unsigned int layer_num, bool direct_show)
|
{
|
unsigned char i, j, k, chn, vi_chn, layno;
|
unsigned char haddr[LAYER_MAX_NUM_PER_CHN][3];
|
unsigned char premul[CHN_NUM][LAYER_MAX_NUM_PER_CHN], format[CHN_NUM],
|
premode[CHN_NUM], zoder[CHN_NUM] = { 0, 1}, pen[CHN_NUM];
|
unsigned int ovlw[CHN_NUM], ovlh[CHN_NUM];
|
static struct __lay_para_t lay_cfg[CHN_NUM * LAYER_MAX_NUM_PER_CHN];
|
struct de_rect layer[CHN_NUM][LAYER_MAX_NUM_PER_CHN], bld_rect[CHN_NUM];
|
struct de_rect crop[CHN_NUM][LAYER_MAX_NUM_PER_CHN];
|
static struct scaler_para ovl_para[CHN_NUM], ovl_cpara[VI_CHN_NUM];
|
bool chn_used[CHN_NUM] = { false }, chn_zorder_cfg[CHN_NUM] = {
|
false}, chn_dirty[CHN_NUM] = {
|
false};
|
bool chn_is_yuv[CHN_NUM] = { false };
|
enum de_color_space cs[CHN_NUM];
|
unsigned char layer_zorder[CHN_NUM] = { 0 }, chn_index;
|
unsigned char pipe_used[CHN_NUM] = { 0 };
|
unsigned int pipe_sel[CHN_NUM] = { 0 };
|
struct de_rect pipe_rect[CHN_NUM] = { {0} };
|
struct disp_rect dispsize[CHN_NUM] = { {0} };
|
struct disp_layer_config_data *data1;
|
unsigned int color = 0xff000000;
|
#if EINK_DEBUG
|
u32 count = 0;
|
u32 kcon = 0;
|
char buf[256] = {0};
|
struct disp_layer_config_data data_print;
|
#endif
|
|
data1 = data;
|
|
chn = de_feat_get_num_chns(screen_id);
|
vi_chn = de_feat_get_num_vi_chns(screen_id);
|
layno = LAYER_MAX_NUM_PER_CHN;
|
|
#if EINK_DEBUG
|
for (kcon = 0; kcon < layer_num; kcon++) {
|
if (data[kcon].config.enable == false)
|
continue;
|
memcpy(&data_print, &data[kcon],
|
sizeof(struct disp_layer_config_data));
|
memset(buf, 0, sizeof(buf));
|
count = 0;
|
count += sprintf(buf + count, " %5s ",
|
(data_print.config.info.mode == LAYER_MODE_BUFFER) ?
|
"BUF" : "COLOR");
|
count += sprintf(buf + count, " %8s ",
|
(data_print.config.enable == 1) ? "enable" : "disable");
|
count += sprintf(buf + count, "ch[%1u] ",
|
data_print.config.channel);
|
count += sprintf(buf + count, "lyr[%1u] ",
|
data_print.config.layer_id);
|
count += sprintf(buf + count, "z[%1u] ",
|
data_print.config.info.zorder);
|
count += sprintf(buf + count, "prem[%1s] ",
|
(data_print.config.info.fb.pre_multiply) ? "Y" : "N");
|
count += sprintf(buf + count, "a[%5s %3u] ",
|
(data_print.config.info.alpha_mode) ? "globl" : "pixel",
|
data_print.config.info.alpha_value);
|
count += sprintf(buf + count,
|
"fmt[%3d] ",
|
data_print.config.info.fb.format);
|
count += sprintf(buf + count, "fb[%4u,%4u;%4u,%4u;%4u,%4u] ",
|
data_print.config.info.fb.size[0].width,
|
data_print.config.info.fb.size[0].height,
|
data_print.config.info.fb.size[1].width,
|
data_print.config.info.fb.size[1].height,
|
data_print.config.info.fb.size[2].width,
|
data_print.config.info.fb.size[2].height);
|
count += sprintf(buf + count, "crop[%4u,%4u,%4u,%4u] ",
|
(unsigned int)(data_print.config.info.fb.crop.x>>32),
|
(unsigned int)(data_print.config.info.fb.crop.y>>32),
|
(unsigned int)(data_print.config.info.fb.crop.width>>32),
|
(unsigned int)(data_print.config.info.fb.crop.height>>32));
|
|
count += sprintf(buf + count, "frame[%4d,%4d,%4u,%4u] ",
|
data_print.config.info.screen_win.x,
|
data_print.config.info.screen_win.y,
|
data_print.config.info.screen_win.width,
|
data_print.config.info.screen_win.height);
|
count += sprintf(buf + count, "addr[%8llx,%8llx,%8llx] ",
|
data_print.config.info.fb.addr[0],
|
data_print.config.info.fb.addr[1],
|
data_print.config.info.fb.addr[2]);
|
count += sprintf(buf + count, "flags[0x%8x] trd[%1d,%1d]\n",
|
data_print.config.info.fb.flags,
|
data_print.config.info.b_trd_out,
|
data_print.config.info.out_trd_mode);
|
pr_info("%s\n", buf);
|
}
|
#endif
|
|
de_al_lyr_apply_direct_show(screen_id, data, layer_num, direct_show);
|
/* parse zorder of channel */
|
data1 = data;
|
for (i = 0; i < layer_num; i++) {
|
if (data1->config.enable) {
|
chn_used[data1->config.channel] = true;
|
if (data1->config.info.fb.format >=
|
DISP_FORMAT_YUV444_I_AYUV) {
|
chn_is_yuv[data1->config.channel] = true;
|
cs[data1->config.channel] = __cs_transform(
|
data1->config.info.fb.color_space);
|
}
|
if (data1->flag)
|
chn_dirty[data1->config.channel] = true;
|
|
layer_zorder[data1->config.channel] =
|
data1->config.info.zorder;
|
}
|
data1++;
|
}
|
|
data1 = data;
|
for (i = 0; i < layer_num; i++) {
|
if (data1->config.enable && chn_dirty[data1->config.channel])
|
data1->flag = LAYER_ALL_DIRTY;
|
data1++;
|
}
|
|
chn_index = 0;
|
for (i = 0; i < chn; i++) {
|
u32 min_zorder = 255, min_zorder_chn = 0;
|
bool find = false;
|
|
for (j = 0; j < chn; j++) {
|
if ((true == chn_used[j]) && (true != chn_zorder_cfg[j]
|
&& (min_zorder > layer_zorder[j]))) {
|
min_zorder = layer_zorder[j];
|
min_zorder_chn = j;
|
find = true;
|
}
|
}
|
if (find) {
|
chn_zorder_cfg[min_zorder_chn] = true;
|
zoder[min_zorder_chn] = chn_index++;
|
}
|
}
|
|
/* parse zorder of pipe */
|
for (i = 0; i < chn; i++) {
|
if (chn_used[i]) {
|
u32 pipe_index = zoder[i];
|
|
pipe_used[pipe_index] = (g_de_blank[screen_id]) ?
|
false : true;
|
pipe_sel[pipe_index] = i;
|
}
|
}
|
for (i = 0; i < chn; i++)
|
__inf("ch%d z %d %s\n", i, zoder[i],
|
chn_used[i] ? "en" : "dis");
|
for (i = 0; i < chn; i++)
|
__inf("pipe%d z %d %s\n", i, pipe_sel[i],
|
pipe_used[i] ? "en" : "dis");
|
|
/* init para */
|
for (j = 0; j < chn; j++)
|
memset((void *)crop[j], 0x0, layno * sizeof(struct de_rect));
|
|
/* check the video format for fill color, because of the hardware limit */
|
for (j = 0, k = 0; j < vi_chn; j++) {
|
format[j] = 0;
|
for (i = 0; i < layno; i++) {
|
if (data[k].config.info.fb.format >=
|
DISP_FORMAT_YUV422_I_YVYU)
|
format[j] = data[k].config.info.fb.format;
|
k++;
|
}
|
__inf("format[%d]=%d\n", j, format[j]);
|
}
|
|
de_calc_overlay_scaler_para(screen_id, chn, layno, format, data, premul,
|
premode, crop, layer, bld_rect, ovlw, ovlh,
|
pen, ovl_para, ovl_cpara);
|
|
for (j = 0; j < vi_chn; j++) {
|
if (chn_used[j]) {
|
struct disp_csc_config csc_cfg;
|
|
/*
|
* We need to disable csc function when on direct show,
|
* And to enable csc function if needed otherwise.
|
* When the input format of csc module is the same width
|
* the output, the csc function will be disable.
|
*/
|
if (direct_show) {
|
csc_cfg.in_fmt = DE_YUV;
|
csc_cfg.in_mode = DE_BT601;
|
csc_cfg.out_fmt = DE_YUV;
|
csc_cfg.out_mode = DE_BT601;
|
|
color = (16 << 16) | (128 << 8) | (128 << 0);
|
} else {
|
csc_cfg.in_fmt = (chn_is_yuv[j]) ?
|
DE_YUV : DE_RGB;
|
csc_cfg.in_mode = cs[j];
|
csc_cfg.out_fmt = DE_RGB;
|
csc_cfg.out_mode = DE_BT601;
|
|
color = 0;
|
}
|
csc_cfg.out_color_range = DISP_COLOR_RANGE_0_255;
|
csc_cfg.brightness = 50;
|
csc_cfg.contrast = 50;
|
csc_cfg.saturation = 50;
|
csc_cfg.hue = 50;
|
de_ccsc_apply(screen_id, j, &csc_cfg);
|
de_rtmx_set_blend_color(screen_id, j, color);
|
}
|
}
|
|
/* init lay_cfg from layer config */
|
for (j = 0, k = 0; j < chn; j++) {
|
for (i = 0; i < layno;) {
|
lay_cfg[k].en = data[k].config.enable;
|
lay_cfg[k].alpha_mode = data[k].config.info.alpha_mode;
|
lay_cfg[k].alpha = data[k].config.info.alpha_value;
|
lay_cfg[k].fcolor_en = data[k].config.info.mode;
|
lay_cfg[k].fmt = data[k].config.info.fb.format;
|
lay_cfg[k].premul_ctl = premul[j][i];
|
|
lay_cfg[k].pitch[0] =
|
data[k].config.info.fb.size[0].width;
|
lay_cfg[k].pitch[1] =
|
data[k].config.info.fb.size[1].width;
|
lay_cfg[k].pitch[2] =
|
data[k].config.info.fb.size[2].width;
|
lay_cfg[k].layer = layer[j][i];
|
lay_cfg[k].laddr_t[0] =
|
(data[k].config.info.fb.addr[0] & 0xFFFFFFFF);
|
lay_cfg[k].laddr_t[1] =
|
(data[k].config.info.fb.addr[1] & 0xFFFFFFFF);
|
lay_cfg[k].laddr_t[2] =
|
(data[k].config.info.fb.addr[2] & 0xFFFFFFFF);
|
|
lay_cfg[k].top_bot_en = 0x0;
|
lay_cfg[k].laddr_b[0] = 0x0;
|
lay_cfg[k].laddr_b[1] = 0x0;
|
lay_cfg[k].laddr_b[2] = 0x0;
|
|
/* 3d mode */
|
if (data[k].config.info.fb.flags) {
|
if (data[k].config.info.b_trd_out)
|
lay_cfg[k + 1].en =
|
data[k].config.enable;
|
else
|
lay_cfg[k + 1].en = 0;
|
|
lay_cfg[k + 1].alpha_mode =
|
data[k].config.info.alpha_mode;
|
lay_cfg[k + 1].alpha =
|
data[k].config.info.alpha_value;
|
lay_cfg[k + 1].fcolor_en =
|
data[k].config.info.mode;
|
lay_cfg[k + 1].fmt =
|
data[k].config.info.fb.format;
|
lay_cfg[k + 1].premul_ctl = premul[j][i];
|
|
lay_cfg[k + 1].layer = layer[j][i + 1];
|
de_rtmx_get_3d_in(data[k].config.info.fb.format,
|
crop[j][i + 1],
|
(struct de_fb *) data[k].config.info.
|
fb.size,
|
data[k].config.info.fb.align,
|
(enum de_3d_in_mode) data[k].
|
config.info.fb.flags,
|
lay_cfg[k].laddr_t,
|
data[k].config.info.fb.
|
trd_right_addr,
|
lay_cfg[k].pitch,
|
lay_cfg[k + 1].pitch,
|
lay_cfg[k + 1].laddr_t);
|
|
lay_cfg[k + 1].top_bot_en =
|
lay_cfg[k].top_bot_en;
|
lay_cfg[k + 1].laddr_b[0] =
|
lay_cfg[k].laddr_b[0];
|
lay_cfg[k + 1].laddr_b[1] =
|
lay_cfg[k].laddr_b[1];
|
lay_cfg[k + 1].laddr_b[2] =
|
lay_cfg[k].laddr_b[2];
|
data[k + 1].flag = data[k].flag;
|
k += 2;
|
i += 2;
|
} else {
|
i++;
|
k++;
|
}
|
}
|
}
|
|
for (j = 0, k = 0; j < chn; j++) {
|
for (i = 0; i < layno; i++) {
|
if (LAYER_SIZE_DIRTY & data[k + i].flag) {
|
de_rtmx_set_overlay_size(screen_id, j, ovlw[j],
|
ovlh[j]);
|
break;
|
}
|
}
|
|
for (i = 0; i < layno; i++) {
|
if (LAYER_ATTR_DIRTY & data[k].flag) {
|
de_rtmx_set_lay_cfg(screen_id, j, i,
|
&lay_cfg[k]);
|
de_rtmx_set_lay_laddr(screen_id, j, i,
|
lay_cfg[k].fmt,
|
crop[j][i],
|
lay_cfg[k].pitch,
|
data[k].config.info.fb.
|
align,
|
(enum de_3d_in_mode)data[k].config.info.fb.flags,
|
lay_cfg[k].laddr_t,
|
haddr[i]);
|
}
|
if (LAYER_VI_FC_DIRTY & data[k].flag) {
|
de_rtmx_set_lay_fcolor(screen_id, j, i,
|
data[k].config.info.mode,
|
format[j],
|
data[k].config.info.
|
color);
|
}
|
if (LAYER_HADDR_DIRTY & data[k].flag) {
|
lay_cfg[k].haddr_t[0] =
|
((data[k].config.info.fb.
|
addr[0] >> 32) & 0xFF) + haddr[i][0];
|
lay_cfg[k].haddr_t[1] =
|
((data[k].config.info.fb.
|
addr[1] >> 32) & 0xFF) + haddr[i][1];
|
lay_cfg[k].haddr_t[2] =
|
((data[k].config.info.fb.
|
addr[2] >> 32) & 0xFF) + haddr[i][2];
|
|
lay_cfg[k].haddr_b[0] = 0x0;
|
lay_cfg[k].haddr_b[1] = 0x0;
|
lay_cfg[k].haddr_b[2] = 0x0;
|
de_rtmx_set_lay_haddr(screen_id, j, i,
|
lay_cfg[k].top_bot_en,
|
lay_cfg[k].haddr_t,
|
lay_cfg[k].haddr_b);
|
}
|
k++;
|
}
|
}
|
|
/* parse pipe rect */
|
for (i = 0; i < chn; i++) {
|
if (pipe_used[i]) {
|
u32 chn_index = pipe_sel[i];
|
|
memcpy(&pipe_rect[i], &bld_rect[chn_index],
|
sizeof(struct disp_rect));
|
dispsize[i].width = bld_rect[i].w;
|
dispsize[i].height = bld_rect[i].h;
|
}
|
}
|
/* need route information to calculate pipe enable and input size */
|
de_rtmx_set_pf_en(screen_id, pipe_used);
|
for (i = 0; i < chn; i++) {
|
__inf("sel=%d, pipe_rect[%d]=<%d,%d,%d,%d>\n", screen_id, i,
|
pipe_rect[i].x, pipe_rect[i].y, pipe_rect[i].w,
|
pipe_rect[i].h);
|
de_rtmx_set_pipe_cfg(screen_id, i, color, pipe_rect[i]);
|
de_rtmx_set_route(screen_id, i, pipe_sel[i]);
|
de_rtmx_set_premul(screen_id, i, premode[i]);
|
}
|
|
for (i = 0; i < chn - 1; i++)
|
de_rtmx_set_blend_mode(screen_id, i, DE_BLD_SRCOVER);
|
/* de_rtmx_set_colorkey(screen_id,); */
|
|
/* set enhance size */
|
de_enhance_set_size(screen_id, dispsize);
|
de_enhance_set_format(screen_id, (chn_is_yuv[0]) ? DE_YUV : DE_RGB);
|
|
return 0;
|
}
|
|
int de_al_mgr_apply_color(unsigned int screen_id, struct disp_csc_config *cfg)
|
{
|
struct disp_csc_config csc_cfg;
|
|
de_rtmx_set_background_color(screen_id, cfg->color);
|
|
de_dcsc_get_config(screen_id, &csc_cfg);
|
csc_cfg.in_fmt = DISP_CSC_TYPE_RGB;
|
csc_cfg.in_mode = DE_BT601;
|
|
csc_cfg.out_fmt = cfg->out_fmt;
|
csc_cfg.out_mode = cfg->out_mode;
|
csc_cfg.out_color_range = cfg->out_color_range;
|
csc_cfg.brightness = 50;
|
csc_cfg.contrast = 50;
|
csc_cfg.saturation = 50;
|
csc_cfg.hue = 50;
|
de_dcsc_apply(screen_id, &csc_cfg);
|
|
return 0;
|
}
|
|
int de_al_mgr_apply(unsigned int screen_id, struct disp_manager_data *data)
|
{
|
struct disp_csc_config csc_cfg;
|
int color =
|
(data->config.back_color.alpha << 24) | (data->config.back_color.
|
red << 16)
|
| (data->config.back_color.green << 8) | (data->config.back_color.
|
blue << 0);
|
|
g_de_blank[screen_id] = data->config.blank;
|
|
if ((data->flag & MANAGER_ENABLE_DIRTY)
|
|| (data->flag & MANAGER_COLOR_SPACE_DIRTY)) {
|
csc_cfg.color = color;
|
csc_cfg.out_fmt =
|
(data->config.cs == DISP_CSC_TYPE_RGB) ? DE_RGB : DE_YUV;
|
if ((data->config.size.width < 1280)
|
&& (data->config.size.height < 720))
|
csc_cfg.out_mode = DE_BT601;
|
else
|
csc_cfg.out_mode = DE_BT709;
|
csc_cfg.out_color_range = data->config.color_range;
|
de_al_mgr_apply_color(screen_id, &csc_cfg);
|
}
|
|
if (data->flag & MANAGER_SIZE_DIRTY) {
|
de_rtmx_set_blend_size(screen_id, data->config.size.width,
|
data->config.size.height);
|
de_rtmx_set_display_size(screen_id, data->config.size.width,
|
data->config.size.height);
|
}
|
if (data->flag & MANAGER_ENABLE_DIRTY) {
|
de_rtmx_set_enable(screen_id, data->config.enable);
|
#if !defined(HAVE_DEVICE_COMMON_MODULE)
|
de_rtmx_mux(screen_id, data->config.hwdev_index);
|
#endif
|
de_rtmx_set_outitl(screen_id, data->config.interlace);
|
}
|
|
return 0;
|
}
|
|
int de_al_mgr_sync(unsigned int screen_id)
|
{
|
/* double register switch */
|
return de_rtmx_set_dbuff_rdy(screen_id);
|
}
|
|
int de_al_mgr_update_regs(unsigned int screen_id)
|
{
|
int ret = 0;
|
|
de_rtmx_update_regs(screen_id);
|
de_vsu_update_regs(screen_id);
|
de_gsu_update_regs(screen_id);
|
de_ccsc_update_regs(screen_id);
|
de_dcsc_update_regs(screen_id);
|
|
return ret;
|
}
|
|
/* query irq, if irq coming, return 1, and clear irq flga */
|
int de_al_query_irq(unsigned int screen_id)
|
{
|
return de_rtmx_query_irq(screen_id);
|
}
|
|
int de_al_enable_irq(unsigned int screen_id, unsigned int en)
|
{
|
return de_rtmx_enable_irq(screen_id, en);
|
}
|
|
int de_al_init(struct disp_bsp_init_para *para)
|
{
|
int i;
|
int num_screens = de_feat_get_num_screens();
|
|
#if defined(CONFIG_INDEPENDENT_DE)
|
for (i = 0; i < num_screens; i++) {
|
de_rtmx_init(i, para->reg_base[DISP_MOD_DE + i]);
|
de_vsu_init(i, para->reg_base[DISP_MOD_DE + i]);
|
de_gsu_init(i, para->reg_base[DISP_MOD_DE + i]);
|
}
|
#else
|
for (i = 0; i < num_screens; i++) {
|
de_rtmx_init(i, para->reg_base[DISP_MOD_DE]);
|
de_vsu_init(i, para->reg_base[DISP_MOD_DE]);
|
de_gsu_init(i, para->reg_base[DISP_MOD_DE]);
|
}
|
#endif
|
return 0;
|
}
|
|
int de_al_exit(void)
|
{
|
int i;
|
int num_screens = de_feat_get_num_screens();
|
|
for (i = 0; i < num_screens; i++) {
|
de_gsu_exit(i);
|
de_vsu_exit(i);
|
de_rtmx_exit(i);
|
}
|
|
return 0;
|
}
|