2025-09-30 11:56:06 +08:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*
|
|
|
|
|
* Authors: Ning Fang <ning.fang@artinchip.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <aic_core.h>
|
|
|
|
|
#include "ge_ops.h"
|
|
|
|
|
#include "ge_reg.h"
|
|
|
|
|
#include "mpp_list.h"
|
|
|
|
|
#include "mpp_ge.h"
|
|
|
|
|
|
|
|
|
|
#define DEFAULT_CMD_SIZE (32*1024 / 4)
|
|
|
|
|
#define CSC_COEFFS_NUM 12
|
|
|
|
|
#define VALID_SPACE (1024 / 4)
|
|
|
|
|
#define MAX_WIDTH 4096
|
|
|
|
|
#define MAX_HEIGHT 4096
|
|
|
|
|
|
|
|
|
|
#define ALIGN_8B(x) (((x) + (7)) & ~(7))
|
|
|
|
|
#define ALIGN_2B(x) (((x) + (1)) & ~(1))
|
|
|
|
|
#define BIT_SHIFT(bit) (1 << (bit))
|
|
|
|
|
#define INIT_PHASE(step) (((step) >= BIT_SHIFT(16)) ? \
|
|
|
|
|
(((step) >> 1) - BIT_SHIFT(15)) :\
|
|
|
|
|
((step) >> 1))
|
|
|
|
|
|
|
|
|
|
struct ge_dmabuf_head {
|
|
|
|
|
struct mpp_list list;
|
|
|
|
|
struct dma_buf_info dma_info;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ge_data {
|
|
|
|
|
unsigned int src_phy_addr[3];
|
|
|
|
|
unsigned int dst_phy_addr[3];
|
|
|
|
|
unsigned int src_premul_en;
|
|
|
|
|
unsigned int src_de_premul_en;
|
|
|
|
|
unsigned int dst_de_premul_en;
|
|
|
|
|
unsigned int out_premul_en;
|
|
|
|
|
unsigned int src_alpha_coef;
|
|
|
|
|
unsigned int dst_alpha_coef;
|
|
|
|
|
unsigned int csc0_en;
|
|
|
|
|
unsigned int csc1_en;
|
|
|
|
|
unsigned int csc2_en;
|
|
|
|
|
unsigned int blend_is_rgb;
|
|
|
|
|
unsigned int src_ctrl;
|
|
|
|
|
unsigned int out_ctrl;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct cmd_queue {
|
|
|
|
|
unsigned int *cmd_buf;
|
|
|
|
|
struct mpp_list dma_list;
|
|
|
|
|
unsigned int total_size;
|
|
|
|
|
unsigned int write_offset;
|
|
|
|
|
struct ge_data data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const unsigned int yuv2rgb_bt601[CSC_COEFFS_NUM] = {
|
|
|
|
|
0x04a8, 0x0000, 0x0662, 0x3212,
|
|
|
|
|
0x04a8, 0x1e70, 0x1cc0, 0x087a,
|
|
|
|
|
0x04a8, 0x0811, 0x0000, 0x2eb4
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const unsigned int yuv2rgb_bt709[CSC_COEFFS_NUM] = {
|
|
|
|
|
0x04a8, 0x0000, 0x0722, 0x3093,
|
|
|
|
|
0x04a8, 0x1f27, 0x1ddf, 0x04ce,
|
|
|
|
|
0x04a8, 0x0873, 0x0000, 0x2df2
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const unsigned int yuv2rgb_bt601_full[CSC_COEFFS_NUM] = {
|
|
|
|
|
0x0400, 0x0000, 0x059c, 0x34ca,
|
|
|
|
|
0x0400, 0x1ea1, 0x1d26, 0x0877,
|
|
|
|
|
0x0400, 0x0717, 0x0000, 0x31d4
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const unsigned int yuv2rgb_bt709_full[CSC_COEFFS_NUM] = {
|
|
|
|
|
0x0400, 0x0000, 0x064d, 0x3368,
|
|
|
|
|
0x0400, 0x1f41, 0x1e22, 0x053e,
|
|
|
|
|
0x0400, 0x076c, 0x0000, 0x3129
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const int rgb2yuv_bt601[CSC_COEFFS_NUM] = {
|
|
|
|
|
66, 129, 25, 16,
|
|
|
|
|
-38, -74, 112, 128,
|
|
|
|
|
112, -94, -18, 128
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const int rgb2yuv_bt709[CSC_COEFFS_NUM] = {
|
|
|
|
|
47, 157, 16, 16,
|
|
|
|
|
-26, -87, 112, 128,
|
|
|
|
|
112, -102, -10, 128
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const int rgb2yuv_bt601_full[CSC_COEFFS_NUM] = {
|
|
|
|
|
77, 150, 29, 0,
|
|
|
|
|
-42, -84, 128, 128,
|
|
|
|
|
128, -106, -20, 128
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const int rgb2yuv_bt709_full[CSC_COEFFS_NUM] = {
|
|
|
|
|
54, 183, 18, 0,
|
|
|
|
|
-28, -98, 128, 128,
|
|
|
|
|
128, -115, -11, 128
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void scaler0_en_cmd(struct mpp_ge *ge, unsigned int enable);
|
|
|
|
|
|
|
|
|
|
static inline void update_scaler0_cmd(struct mpp_ge *ge,
|
|
|
|
|
unsigned int input_w,
|
|
|
|
|
unsigned int input_h,
|
|
|
|
|
unsigned int output_w,
|
|
|
|
|
unsigned int output_h,
|
|
|
|
|
int dx, int dy,
|
|
|
|
|
int h_phase, int v_phase,
|
|
|
|
|
unsigned int channel);
|
|
|
|
|
|
|
|
|
|
static int set_premuliply(struct ge_data *data,
|
|
|
|
|
enum mpp_pixel_format src_format,
|
|
|
|
|
enum mpp_pixel_format dst_format,
|
|
|
|
|
int src_premul,
|
|
|
|
|
int dst_premul,
|
|
|
|
|
int is_fill_color,
|
|
|
|
|
struct ge_ctrl *ctrl);
|
|
|
|
|
|
|
|
|
|
static inline unsigned int ge_set_src_ctrl(unsigned int global_alpha,
|
|
|
|
|
unsigned int alpha_mode,
|
|
|
|
|
unsigned int premul_en,
|
|
|
|
|
unsigned int scan_order,
|
|
|
|
|
unsigned int func_select,
|
|
|
|
|
unsigned int fmt,
|
|
|
|
|
unsigned int v_flip,
|
|
|
|
|
unsigned int h_flip,
|
|
|
|
|
unsigned int rot0_ctrl,
|
|
|
|
|
unsigned int source_mode,
|
|
|
|
|
unsigned int csc0_en);
|
|
|
|
|
|
|
|
|
|
static void update_src_fillrect_cmd(struct mpp_ge *ge, unsigned int src_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int start_color);
|
|
|
|
|
|
|
|
|
|
static void set_alpha_rules(struct ge_data *data,
|
|
|
|
|
enum ge_pd_rules rules);
|
|
|
|
|
|
|
|
|
|
static void update_output_cmd(struct mpp_ge *ge, unsigned int out_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int stride0, unsigned int stride1,
|
|
|
|
|
unsigned int addr[]);
|
|
|
|
|
|
|
|
|
|
static void update_dst_cmd(struct mpp_ge *ge, unsigned int dst_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int stride0, unsigned int stride1,
|
|
|
|
|
unsigned int addr[]);
|
|
|
|
|
|
|
|
|
|
static void update_dst_disable_cmd(struct mpp_ge *ge);
|
|
|
|
|
|
|
|
|
|
static void update_src_cmd(struct mpp_ge *ge, unsigned int src_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int stride0, unsigned int stride1,
|
|
|
|
|
unsigned int addr[]);
|
|
|
|
|
|
|
|
|
|
static inline struct cmd_queue *to_cmdq(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
return (struct cmd_queue *)ge->priv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*@addr[]: in/out addr
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static int ge_buf_crop(unsigned int addr[], unsigned int stride[],
|
|
|
|
|
enum mpp_pixel_format format,
|
|
|
|
|
unsigned int x_offset,
|
|
|
|
|
unsigned int y_offset,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
unsigned int height)
|
|
|
|
|
{
|
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
|
case MPP_FMT_ARGB_8888:
|
|
|
|
|
case MPP_FMT_ABGR_8888:
|
|
|
|
|
case MPP_FMT_RGBA_8888:
|
|
|
|
|
case MPP_FMT_BGRA_8888:
|
|
|
|
|
case MPP_FMT_XRGB_8888:
|
|
|
|
|
case MPP_FMT_XBGR_8888:
|
|
|
|
|
case MPP_FMT_RGBX_8888:
|
|
|
|
|
case MPP_FMT_BGRX_8888:
|
|
|
|
|
addr[0] += x_offset * 4 + y_offset * stride[0];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_RGB_888:
|
|
|
|
|
case MPP_FMT_BGR_888:
|
|
|
|
|
addr[0] += x_offset * 3 + y_offset * stride[0];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_ARGB_1555:
|
|
|
|
|
case MPP_FMT_ABGR_1555:
|
|
|
|
|
case MPP_FMT_RGBA_5551:
|
|
|
|
|
case MPP_FMT_BGRA_5551:
|
|
|
|
|
case MPP_FMT_RGB_565:
|
|
|
|
|
case MPP_FMT_BGR_565:
|
|
|
|
|
case MPP_FMT_ARGB_4444:
|
|
|
|
|
case MPP_FMT_ABGR_4444:
|
|
|
|
|
case MPP_FMT_RGBA_4444:
|
|
|
|
|
case MPP_FMT_BGRA_4444:
|
|
|
|
|
addr[0] += x_offset * 2 + y_offset * stride[0];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV420P:
|
|
|
|
|
addr[0] += x_offset + y_offset * stride[0];
|
|
|
|
|
offset = (x_offset >> 1) + (y_offset >> 1) * stride[1];
|
|
|
|
|
addr[1] += offset;
|
|
|
|
|
addr[2] += offset;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_NV12:
|
|
|
|
|
case MPP_FMT_NV21:
|
|
|
|
|
addr[0] += x_offset + y_offset * stride[0];
|
|
|
|
|
addr[1] += x_offset + (y_offset >> 1) * stride[1];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV400:
|
|
|
|
|
addr[0] += x_offset + y_offset * stride[0];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV422P:
|
|
|
|
|
addr[0] += x_offset + y_offset * stride[0];
|
|
|
|
|
offset = (x_offset >> 1) + y_offset * stride[1];
|
|
|
|
|
addr[1] += offset;
|
|
|
|
|
addr[2] += offset;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_NV16:
|
|
|
|
|
case MPP_FMT_NV61:
|
|
|
|
|
addr[0] += x_offset + y_offset * stride[0];
|
|
|
|
|
addr[1] += x_offset + y_offset * stride[1];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUYV:
|
|
|
|
|
case MPP_FMT_YVYU:
|
|
|
|
|
case MPP_FMT_UYVY:
|
|
|
|
|
case MPP_FMT_VYUY:
|
|
|
|
|
addr[0] += (x_offset << 1) + y_offset * stride[0];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV444P:
|
|
|
|
|
addr[0] += x_offset + y_offset * stride[0];
|
|
|
|
|
addr[1] += x_offset + y_offset * stride[1];
|
|
|
|
|
addr[2] += x_offset + y_offset * stride[1];
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int dma_fd_to_addr(struct mpp_ge *ge, int dma_fd,
|
|
|
|
|
unsigned int *phy_addr)
|
|
|
|
|
{
|
|
|
|
|
int ret = -1;
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
struct ge_dmabuf_head *node = NULL, *head = NULL;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
mpp_list_for_each_entry_safe(head, node, &cmdq->dma_list, list) {
|
|
|
|
|
if (head->dma_info.fd == dma_fd) {
|
|
|
|
|
*phy_addr = head->dma_info.phy_addr;
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int is_rgb(enum mpp_pixel_format format)
|
|
|
|
|
{
|
|
|
|
|
switch (format) {
|
|
|
|
|
case MPP_FMT_ARGB_8888:
|
|
|
|
|
case MPP_FMT_ABGR_8888:
|
|
|
|
|
case MPP_FMT_RGBA_8888:
|
|
|
|
|
case MPP_FMT_BGRA_8888:
|
|
|
|
|
case MPP_FMT_XRGB_8888:
|
|
|
|
|
case MPP_FMT_XBGR_8888:
|
|
|
|
|
case MPP_FMT_RGBX_8888:
|
|
|
|
|
case MPP_FMT_BGRX_8888:
|
|
|
|
|
case MPP_FMT_RGB_888:
|
|
|
|
|
case MPP_FMT_BGR_888:
|
|
|
|
|
case MPP_FMT_ARGB_1555:
|
|
|
|
|
case MPP_FMT_ABGR_1555:
|
|
|
|
|
case MPP_FMT_RGBA_5551:
|
|
|
|
|
case MPP_FMT_BGRA_5551:
|
|
|
|
|
case MPP_FMT_RGB_565:
|
|
|
|
|
case MPP_FMT_BGR_565:
|
|
|
|
|
case MPP_FMT_ARGB_4444:
|
|
|
|
|
case MPP_FMT_ABGR_4444:
|
|
|
|
|
case MPP_FMT_RGBA_4444:
|
|
|
|
|
case MPP_FMT_BGRA_4444:
|
|
|
|
|
return 1;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef AIC_GE_DRV_V11
|
|
|
|
|
static inline bool is_rgb_or_yuv400(enum mpp_pixel_format format)
|
|
|
|
|
{
|
|
|
|
|
if (is_rgb(format) || format == MPP_FMT_YUV400)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static inline int need_blend(struct ge_ctrl *ctrl)
|
|
|
|
|
{
|
|
|
|
|
if (ctrl->alpha_en || ctrl->ck_en)
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int check_bitblt(struct mpp_ge *ge, struct ge_bitblt *blt)
|
|
|
|
|
{
|
|
|
|
|
enum mpp_pixel_format src_format = blt->src_buf.format;
|
|
|
|
|
enum mpp_pixel_format dst_format = blt->dst_buf.format;
|
|
|
|
|
struct mpp_rect *src_rect = &blt->src_buf.crop;
|
|
|
|
|
struct mpp_rect *dst_rect = &blt->dst_buf.crop;
|
|
|
|
|
struct mpp_size *src_size = &blt->src_buf.size;
|
|
|
|
|
struct mpp_size *dst_size = &blt->dst_buf.size;
|
|
|
|
|
|
|
|
|
|
(void)ge;
|
|
|
|
|
|
|
|
|
|
if (MPP_SCAN_ORDER_GET(blt->ctrl.flags)) {
|
|
|
|
|
if (MPP_ROTATION_GET(blt->ctrl.flags)) {
|
|
|
|
|
printf("scan order unsupport rot0\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (blt->ctrl.dither_en) {
|
|
|
|
|
printf("scan order unsupport dither\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (!is_rgb(src_format) || !is_rgb(dst_format)) {
|
|
|
|
|
printf("scan order just support rgb format\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (blt->src_buf.crop_en) {
|
|
|
|
|
if (src_rect->x < 0 ||
|
|
|
|
|
src_rect->y < 0 ||
|
|
|
|
|
src_rect->x >= src_size->width ||
|
|
|
|
|
src_rect->y >= src_size->height) {
|
|
|
|
|
printf("%s failed, invalid src crop\n", __func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (blt->ctrl.dither_en) {
|
|
|
|
|
if (!is_rgb(dst_format)) {
|
|
|
|
|
printf( "%s failed, invalid dst format with the dither func on\n",
|
|
|
|
|
__func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
#ifndef AIC_GE_DITHER
|
|
|
|
|
printf("%s failed, dither function is closed and cannot be used\n",
|
|
|
|
|
__func__);
|
|
|
|
|
blt->ctrl.dither_en = 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
if (blt->dst_buf.crop_en) {
|
|
|
|
|
if (dst_rect->x < 0 ||
|
|
|
|
|
dst_rect->y < 0 ||
|
|
|
|
|
dst_rect->x >= dst_size->width ||
|
|
|
|
|
dst_rect->y >= dst_size->height) {
|
|
|
|
|
printf("%s failed, invalid dst crop\n", __func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!blt->src_buf.crop_en) {
|
|
|
|
|
src_rect->x = 0;
|
|
|
|
|
src_rect->y = 0;
|
|
|
|
|
src_rect->width = src_size->width;
|
|
|
|
|
src_rect->height = src_size->height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!blt->dst_buf.crop_en) {
|
|
|
|
|
dst_rect->x = 0;
|
|
|
|
|
dst_rect->y = 0;
|
|
|
|
|
dst_rect->width = dst_size->width;
|
|
|
|
|
dst_rect->height = dst_size->height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (src_format) {
|
|
|
|
|
case MPP_FMT_YUV420P:
|
|
|
|
|
case MPP_FMT_NV12:
|
|
|
|
|
case MPP_FMT_NV21:
|
|
|
|
|
src_rect->x = src_rect->x & (~1);
|
|
|
|
|
src_rect->y = src_rect->y & (~1);
|
|
|
|
|
src_rect->width = src_rect->width & (~1);
|
|
|
|
|
src_rect->height = src_rect->height & (~1);
|
|
|
|
|
src_size->width = src_size->width & (~1);
|
|
|
|
|
src_size->height = src_size->height & (~1);
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV422P:
|
|
|
|
|
case MPP_FMT_NV16:
|
|
|
|
|
case MPP_FMT_NV61:
|
|
|
|
|
case MPP_FMT_YUYV:
|
|
|
|
|
case MPP_FMT_YVYU:
|
|
|
|
|
case MPP_FMT_UYVY:
|
|
|
|
|
case MPP_FMT_VYUY:
|
|
|
|
|
src_rect->x = src_rect->x & (~1);
|
|
|
|
|
src_rect->width = src_rect->width & (~1);
|
|
|
|
|
src_size->height = src_size->height & (~1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (dst_format) {
|
|
|
|
|
case MPP_FMT_YUV420P:
|
|
|
|
|
case MPP_FMT_NV12:
|
|
|
|
|
case MPP_FMT_NV21:
|
|
|
|
|
dst_rect->x = dst_rect->x & (~1);
|
|
|
|
|
dst_rect->y = dst_rect->y & (~1);
|
|
|
|
|
dst_rect->width = dst_rect->width & (~1);
|
|
|
|
|
dst_rect->height = dst_rect->height & (~1);
|
|
|
|
|
dst_size->width = dst_size->width & (~1);
|
|
|
|
|
dst_size->height = dst_size->height & (~1);
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV422P:
|
|
|
|
|
case MPP_FMT_NV16:
|
|
|
|
|
case MPP_FMT_NV61:
|
|
|
|
|
case MPP_FMT_YUYV:
|
|
|
|
|
case MPP_FMT_YVYU:
|
|
|
|
|
case MPP_FMT_UYVY:
|
|
|
|
|
case MPP_FMT_VYUY:
|
|
|
|
|
dst_rect->x = dst_rect->x & (~1);
|
|
|
|
|
dst_rect->width = dst_rect->width & (~1);
|
|
|
|
|
dst_size->width = dst_size->width & (~1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* crop src invalid region */
|
|
|
|
|
if ((src_rect->x + src_rect->width) > src_size->width)
|
|
|
|
|
src_rect->width = src_size->width - src_rect->x;
|
|
|
|
|
|
|
|
|
|
if ((src_rect->y + src_rect->height) > src_size->height)
|
|
|
|
|
src_rect->height = src_size->height - src_rect->y;
|
|
|
|
|
|
|
|
|
|
/* crop dst invalid region */
|
|
|
|
|
if ((dst_rect->x + dst_rect->width) > dst_size->width)
|
|
|
|
|
dst_rect->width = dst_size->width - dst_rect->x;
|
|
|
|
|
|
|
|
|
|
if ((dst_rect->y + dst_rect->height) > dst_size->height)
|
|
|
|
|
dst_rect->height = dst_size->height - dst_rect->y;
|
|
|
|
|
|
|
|
|
|
if (src_rect->height > MAX_HEIGHT ||
|
|
|
|
|
src_rect->width > MAX_WIDTH) {
|
|
|
|
|
printf("invalid src size, over the largest\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dst_rect->height > MAX_HEIGHT ||
|
|
|
|
|
dst_rect->width > MAX_WIDTH) {
|
|
|
|
|
printf("invalid dst size, over the largest\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_rgb(src_format) &&
|
|
|
|
|
(src_rect->width < 8 || src_rect->height < 8)) {
|
|
|
|
|
printf("invalid src size, the min size of yuv is 8x8\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_rgb(dst_format) &&
|
|
|
|
|
(dst_rect->width < 8 || dst_rect->height < 8)) {
|
|
|
|
|
printf("invalid dst size, the min size of yuv is 8x8\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int check_fillrect(struct mpp_ge *ge,
|
|
|
|
|
struct ge_fillrect *fill)
|
|
|
|
|
{
|
|
|
|
|
enum mpp_pixel_format dst_format = fill->dst_buf.format;
|
|
|
|
|
struct mpp_rect *dst_rect = &fill->dst_buf.crop;
|
|
|
|
|
struct mpp_size *dst_size = &fill->dst_buf.size;
|
|
|
|
|
|
|
|
|
|
(void)ge;
|
|
|
|
|
|
|
|
|
|
if (fill->dst_buf.crop_en) {
|
|
|
|
|
if (dst_rect->x < 0 ||
|
|
|
|
|
dst_rect->y < 0 ||
|
|
|
|
|
dst_rect->x >= dst_size->width ||
|
|
|
|
|
dst_rect->y >= dst_size->height) {
|
|
|
|
|
printf("%s failed, invalid dst crop\n", __func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (fill->type) {
|
|
|
|
|
case GE_NO_GRADIENT:
|
|
|
|
|
case GE_H_LINEAR_GRADIENT:
|
|
|
|
|
case GE_V_LINEAR_GRADIENT:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
printf("invalid type: %08x\n", fill->type);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!fill->dst_buf.crop_en) {
|
|
|
|
|
dst_rect->x = 0;
|
|
|
|
|
dst_rect->y = 0;
|
|
|
|
|
dst_rect->width = dst_size->width;
|
|
|
|
|
dst_rect->height = dst_size->height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (dst_format) {
|
|
|
|
|
case MPP_FMT_YUV420P:
|
|
|
|
|
case MPP_FMT_NV12:
|
|
|
|
|
case MPP_FMT_NV21:
|
|
|
|
|
dst_rect->x = dst_rect->x & (~1);
|
|
|
|
|
dst_rect->y = dst_rect->y & (~1);
|
|
|
|
|
dst_rect->width = dst_rect->width & (~1);
|
|
|
|
|
dst_rect->height = dst_rect->height & (~1);
|
|
|
|
|
dst_size->width = dst_size->width & (~1);
|
|
|
|
|
dst_size->height = dst_size->height & (~1);
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV422P:
|
|
|
|
|
case MPP_FMT_NV16:
|
|
|
|
|
case MPP_FMT_NV61:
|
|
|
|
|
case MPP_FMT_YUYV:
|
|
|
|
|
case MPP_FMT_YVYU:
|
|
|
|
|
case MPP_FMT_UYVY:
|
|
|
|
|
case MPP_FMT_VYUY:
|
|
|
|
|
dst_rect->x = dst_rect->x & (~1);
|
|
|
|
|
dst_rect->width = dst_rect->width & (~1);
|
|
|
|
|
dst_size->width = dst_size->width & (~1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* crop dst invalid region */
|
|
|
|
|
if ((dst_rect->x + dst_rect->width) > dst_size->width)
|
|
|
|
|
dst_rect->width = dst_size->width - dst_rect->x;
|
|
|
|
|
|
|
|
|
|
if ((dst_rect->y + dst_rect->height) > dst_size->height)
|
|
|
|
|
dst_rect->height = dst_size->height - dst_rect->y;
|
|
|
|
|
|
|
|
|
|
if (dst_rect->width > MAX_WIDTH ||
|
|
|
|
|
dst_rect->height > MAX_HEIGHT) {
|
|
|
|
|
printf("invalid dst size, over the largest\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_rgb(dst_format) &&
|
|
|
|
|
(dst_rect->width < 8 ||
|
|
|
|
|
dst_rect->height < 8)) {
|
|
|
|
|
printf("invalid dst size, the min size of yuv is 8x8\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int check_format_and_size(struct mpp_ge *ge,
|
|
|
|
|
struct mpp_buf *src_buf,
|
|
|
|
|
struct mpp_buf *dst_buf)
|
|
|
|
|
{
|
|
|
|
|
enum mpp_pixel_format src_format = src_buf->format;
|
|
|
|
|
enum mpp_pixel_format dst_format = dst_buf->format;
|
|
|
|
|
|
|
|
|
|
struct mpp_rect *src_rect = &src_buf->crop;
|
|
|
|
|
struct mpp_rect *dst_rect = &dst_buf->crop;
|
|
|
|
|
|
|
|
|
|
(void)ge;
|
|
|
|
|
|
|
|
|
|
if (src_buf->crop_en) {
|
|
|
|
|
if (src_rect->x < 0 ||
|
|
|
|
|
src_rect->y < 0 ||
|
|
|
|
|
src_rect->x >= src_buf->size.width ||
|
|
|
|
|
src_rect->y >= src_buf->size.height) {
|
|
|
|
|
printf("%s failed, invalid src crop\n", __func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dst_buf->crop_en) {
|
|
|
|
|
if (dst_rect->x < 0 ||
|
|
|
|
|
dst_rect->y < 0 ||
|
|
|
|
|
dst_rect->x >= dst_buf->size.width ||
|
|
|
|
|
dst_rect->y >= dst_buf->size.height) {
|
|
|
|
|
printf("%s failed, invalid dst crop\n", __func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!src_buf->crop_en) {
|
|
|
|
|
src_rect->x = 0;
|
|
|
|
|
src_rect->y = 0;
|
|
|
|
|
src_rect->width = src_buf->size.width;
|
|
|
|
|
src_rect->height = src_buf->size.height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dst_buf->crop_en) {
|
|
|
|
|
dst_rect->x = 0;
|
|
|
|
|
dst_rect->y = 0;
|
|
|
|
|
dst_rect->width = dst_buf->size.width;
|
|
|
|
|
dst_rect->height = dst_buf->size.height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (src_format) {
|
|
|
|
|
case MPP_FMT_ARGB_8888:
|
|
|
|
|
case MPP_FMT_ABGR_8888:
|
|
|
|
|
case MPP_FMT_RGBA_8888:
|
|
|
|
|
case MPP_FMT_BGRA_8888:
|
|
|
|
|
case MPP_FMT_XRGB_8888:
|
|
|
|
|
case MPP_FMT_XBGR_8888:
|
|
|
|
|
case MPP_FMT_RGBX_8888:
|
|
|
|
|
case MPP_FMT_BGRX_8888:
|
|
|
|
|
case MPP_FMT_RGB_888:
|
|
|
|
|
case MPP_FMT_BGR_888:
|
|
|
|
|
case MPP_FMT_ARGB_1555:
|
|
|
|
|
case MPP_FMT_ABGR_1555:
|
|
|
|
|
case MPP_FMT_RGBA_5551:
|
|
|
|
|
case MPP_FMT_BGRA_5551:
|
|
|
|
|
case MPP_FMT_RGB_565:
|
|
|
|
|
case MPP_FMT_BGR_565:
|
|
|
|
|
case MPP_FMT_ARGB_4444:
|
|
|
|
|
case MPP_FMT_ABGR_4444:
|
|
|
|
|
case MPP_FMT_RGBA_4444:
|
|
|
|
|
case MPP_FMT_BGRA_4444:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
printf("unsupport src format:%d\n", src_format);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (dst_format) {
|
|
|
|
|
case MPP_FMT_ARGB_8888:
|
|
|
|
|
case MPP_FMT_ABGR_8888:
|
|
|
|
|
case MPP_FMT_RGBA_8888:
|
|
|
|
|
case MPP_FMT_BGRA_8888:
|
|
|
|
|
case MPP_FMT_XRGB_8888:
|
|
|
|
|
case MPP_FMT_XBGR_8888:
|
|
|
|
|
case MPP_FMT_RGBX_8888:
|
|
|
|
|
case MPP_FMT_BGRX_8888:
|
|
|
|
|
case MPP_FMT_RGB_888:
|
|
|
|
|
case MPP_FMT_BGR_888:
|
|
|
|
|
case MPP_FMT_ARGB_1555:
|
|
|
|
|
case MPP_FMT_ABGR_1555:
|
|
|
|
|
case MPP_FMT_RGBA_5551:
|
|
|
|
|
case MPP_FMT_BGRA_5551:
|
|
|
|
|
case MPP_FMT_RGB_565:
|
|
|
|
|
case MPP_FMT_BGR_565:
|
|
|
|
|
case MPP_FMT_ARGB_4444:
|
|
|
|
|
case MPP_FMT_ABGR_4444:
|
|
|
|
|
case MPP_FMT_RGBA_4444:
|
|
|
|
|
case MPP_FMT_BGRA_4444:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
printf("unsupport dst format:%d\n", dst_format);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* crop src invalid region */
|
|
|
|
|
if ((src_rect->x + src_rect->width) >
|
|
|
|
|
src_buf->size.width)
|
|
|
|
|
src_rect->width = src_buf->size.width -
|
|
|
|
|
src_rect->x;
|
|
|
|
|
|
|
|
|
|
if ((src_rect->y + src_rect->height) >
|
|
|
|
|
src_buf->size.height)
|
|
|
|
|
src_rect->height = src_buf->size.height -
|
|
|
|
|
src_rect->y;
|
|
|
|
|
|
|
|
|
|
if (src_rect->width < 4 || src_rect->height < 4 ||
|
|
|
|
|
src_rect->width > MAX_WIDTH ||
|
|
|
|
|
src_rect->height > MAX_HEIGHT) {
|
|
|
|
|
printf("unsupport src size\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* crop dst invalid region */
|
|
|
|
|
if ((dst_rect->x + dst_rect->width) >
|
|
|
|
|
dst_buf->size.width)
|
|
|
|
|
dst_rect->width = dst_buf->size.width -
|
|
|
|
|
dst_rect->x;
|
|
|
|
|
|
|
|
|
|
if ((dst_rect->y + dst_rect->height) >
|
|
|
|
|
dst_buf->size.height)
|
|
|
|
|
dst_rect->height = dst_buf->size.height -
|
|
|
|
|
dst_rect->y;
|
|
|
|
|
|
|
|
|
|
if (dst_rect->width < 4 || dst_rect->height < 4 ||
|
|
|
|
|
dst_rect->width > MAX_WIDTH ||
|
|
|
|
|
dst_rect->height > MAX_HEIGHT) {
|
|
|
|
|
printf("unsupport dst size\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int update_scaler_cmd(struct mpp_ge *ge,
|
|
|
|
|
struct ge_bitblt *blt)
|
|
|
|
|
{
|
|
|
|
|
enum mpp_pixel_format format;
|
|
|
|
|
int in_w[2];
|
|
|
|
|
int in_h[2];
|
|
|
|
|
int out_w;
|
|
|
|
|
int out_h;
|
|
|
|
|
int channel_num;
|
|
|
|
|
int scaler_en;
|
|
|
|
|
int rot0_degree;
|
|
|
|
|
int i;
|
|
|
|
|
int dx[2];
|
|
|
|
|
int dy[2];
|
|
|
|
|
int h_phase[2];
|
|
|
|
|
int v_phase[2];
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
channel_num = 1;
|
|
|
|
|
scaler_en = 1;
|
|
|
|
|
format = blt->src_buf.format;
|
|
|
|
|
rot0_degree = MPP_ROTATION_GET(blt->ctrl.flags);
|
|
|
|
|
|
|
|
|
|
in_w[0] = blt->src_buf.crop.width;
|
|
|
|
|
in_h[0] = blt->src_buf.crop.height;
|
|
|
|
|
|
|
|
|
|
if (rot0_degree == MPP_ROTATION_90 ||
|
|
|
|
|
rot0_degree == MPP_ROTATION_270) {
|
|
|
|
|
out_w = blt->dst_buf.crop.height;
|
|
|
|
|
out_h = blt->dst_buf.crop.width;
|
|
|
|
|
} else {
|
|
|
|
|
out_w = blt->dst_buf.crop.width;
|
|
|
|
|
out_h = blt->dst_buf.crop.height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
|
case MPP_FMT_ARGB_8888:
|
|
|
|
|
case MPP_FMT_ABGR_8888:
|
|
|
|
|
case MPP_FMT_RGBA_8888:
|
|
|
|
|
case MPP_FMT_BGRA_8888:
|
|
|
|
|
case MPP_FMT_XRGB_8888:
|
|
|
|
|
case MPP_FMT_XBGR_8888:
|
|
|
|
|
case MPP_FMT_RGBX_8888:
|
|
|
|
|
case MPP_FMT_BGRX_8888:
|
|
|
|
|
case MPP_FMT_RGB_888:
|
|
|
|
|
case MPP_FMT_BGR_888:
|
|
|
|
|
case MPP_FMT_ARGB_1555:
|
|
|
|
|
case MPP_FMT_ABGR_1555:
|
|
|
|
|
case MPP_FMT_RGBA_5551:
|
|
|
|
|
case MPP_FMT_BGRA_5551:
|
|
|
|
|
case MPP_FMT_RGB_565:
|
|
|
|
|
case MPP_FMT_BGR_565:
|
|
|
|
|
case MPP_FMT_ARGB_4444:
|
|
|
|
|
case MPP_FMT_ABGR_4444:
|
|
|
|
|
case MPP_FMT_RGBA_4444:
|
|
|
|
|
case MPP_FMT_BGRA_4444:
|
|
|
|
|
if (in_w[0] == out_w && in_h[0] == out_h) {
|
|
|
|
|
scaler_en = 0;
|
|
|
|
|
} else {
|
|
|
|
|
dx[0] = (in_w[0] << 16) / out_w;
|
|
|
|
|
dy[0] = (in_h[0] << 16) / out_h;
|
|
|
|
|
h_phase[0] = INIT_PHASE(dx[0]);
|
|
|
|
|
v_phase[0] = INIT_PHASE(dy[0]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV400:
|
|
|
|
|
dx[0] = (in_w[0] << 16) / out_w;
|
|
|
|
|
dy[0] = (in_h[0] << 16) / out_h;
|
|
|
|
|
h_phase[0] = INIT_PHASE(dx[0]);
|
|
|
|
|
v_phase[0] = INIT_PHASE(dy[0]);
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV420P:
|
|
|
|
|
case MPP_FMT_NV12:
|
|
|
|
|
case MPP_FMT_NV21:
|
|
|
|
|
channel_num = 2;
|
|
|
|
|
in_w[1] = in_w[0] >> 1;
|
|
|
|
|
in_h[1] = in_h[0] >> 1;
|
|
|
|
|
|
|
|
|
|
dx[0] = (in_w[0] << 16) / out_w;
|
|
|
|
|
dy[0] = (in_h[0] << 16) / out_h;
|
|
|
|
|
h_phase[0] = INIT_PHASE(dx[0]);
|
|
|
|
|
v_phase[0] = INIT_PHASE(dy[0]);
|
|
|
|
|
|
|
|
|
|
dx[0] = dx[0] & (~1);
|
|
|
|
|
dy[0] = dy[0] & (~1);
|
|
|
|
|
h_phase[0] = h_phase[0] & (~1);
|
|
|
|
|
v_phase[0] = v_phase[0] & (~1);
|
|
|
|
|
|
|
|
|
|
/* change init phase */
|
|
|
|
|
if (((dx[0] - h_phase[0]) >> 16) > 4) {
|
|
|
|
|
h_phase[0] += (((dx[0] - h_phase[0]) >> 16) - 4) << 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (((dy[0] - v_phase[0]) >> 16) > 3) {
|
|
|
|
|
v_phase[0] += (((dy[0] - v_phase[0]) >> 16) - 4) << 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dx[1] = dx[0] >> 1;
|
|
|
|
|
dy[1] = dy[0] >> 1;
|
|
|
|
|
h_phase[1] = h_phase[0] >> 1;
|
|
|
|
|
v_phase[1] = v_phase[0] >> 1;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV422P:
|
|
|
|
|
case MPP_FMT_NV16:
|
|
|
|
|
case MPP_FMT_NV61:
|
|
|
|
|
case MPP_FMT_YUYV:
|
|
|
|
|
case MPP_FMT_YVYU:
|
|
|
|
|
case MPP_FMT_UYVY:
|
|
|
|
|
case MPP_FMT_VYUY:
|
|
|
|
|
channel_num = 2;
|
|
|
|
|
|
|
|
|
|
in_w[1] = in_w[0] >> 1;
|
|
|
|
|
in_h[1] = in_h[0];
|
|
|
|
|
|
|
|
|
|
dx[0] = (in_w[0] << 16) / out_w;
|
|
|
|
|
dy[0] = (in_h[0] << 16) / out_h;
|
|
|
|
|
h_phase[0] = INIT_PHASE(dx[0]);
|
|
|
|
|
v_phase[0] = INIT_PHASE(dy[0]);
|
|
|
|
|
|
|
|
|
|
dx[0] = dx[0] & (~1);
|
|
|
|
|
h_phase[0] = h_phase[0] & (~1);
|
|
|
|
|
|
|
|
|
|
/* change init phase */
|
|
|
|
|
if (((dx[0] - h_phase[0]) >> 16) > 4) {
|
|
|
|
|
h_phase[0] += (((dx[0] - h_phase[0]) >> 16) - 4) << 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dx[1] = dx[0] >> 1;
|
|
|
|
|
dy[1] = dy[0];
|
|
|
|
|
h_phase[1] = h_phase[0] >> 1;
|
|
|
|
|
v_phase[1] = v_phase[0];
|
|
|
|
|
break;
|
|
|
|
|
case MPP_FMT_YUV444P:
|
|
|
|
|
channel_num = 2;
|
|
|
|
|
in_w[1] = in_w[0];
|
|
|
|
|
in_h[1] = in_h[0];
|
|
|
|
|
|
|
|
|
|
dx[0] = (in_w[0] << 16) / out_w;
|
|
|
|
|
dy[0] = (in_h[0] << 16) / out_h;
|
|
|
|
|
h_phase[0] = INIT_PHASE(dx[0]);
|
|
|
|
|
v_phase[0] = INIT_PHASE(dy[0]);
|
|
|
|
|
|
|
|
|
|
dx[1] = dx[0];
|
|
|
|
|
dy[1] = dy[0];
|
|
|
|
|
h_phase[1] = h_phase[0];
|
|
|
|
|
v_phase[1] = v_phase[0];
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
scaler_en = 0;
|
|
|
|
|
printf("scale invalid format: %d\n", format);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scaler_en) {
|
|
|
|
|
if (MPP_SCAN_ORDER_GET(blt->ctrl.flags)) {
|
|
|
|
|
printf("unsupport scan order\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_rgb(format) &&
|
|
|
|
|
(in_w[0] < 4 || in_h[0] < 4)) {
|
|
|
|
|
printf("the min size of rgb is 4x4, when scaler enable\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_rgb(blt->dst_buf.format) &&
|
|
|
|
|
(out_h < 4 || out_w < 4)) {
|
|
|
|
|
printf("the min size of rgb is 4x4, when scaler enable\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scaler0_en_cmd(ge, 1);
|
|
|
|
|
for (i = 0; i < channel_num; i++)
|
|
|
|
|
update_scaler0_cmd(ge, in_w[i], in_h[i],
|
|
|
|
|
out_w, out_h,
|
|
|
|
|
dx[i], dy[i],
|
|
|
|
|
h_phase[i], v_phase[i],
|
|
|
|
|
i);
|
|
|
|
|
} else {
|
|
|
|
|
scaler0_en_cmd(ge, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int flush_cmd(struct cmd_queue *cmdq, struct aic_ge_client *dev_fd)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (cmdq->write_offset) {
|
|
|
|
|
ret = aic_ge_write(dev_fd, (char *)cmdq->cmd_buf, cmdq->write_offset * 4);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
printf( "flush_cmd: write() failed!\n" );
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
cmdq->write_offset = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int clean_dma_buf_list(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
struct ge_dmabuf_head *node = NULL, *head = NULL;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
mpp_list_for_each_entry_safe(head, node, &cmdq->dma_list, list) {
|
|
|
|
|
mpp_list_del(&head->list);
|
|
|
|
|
aicos_free(0, head);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_plane_num(enum mpp_pixel_format format)
|
|
|
|
|
{
|
|
|
|
|
switch (format) {
|
|
|
|
|
case MPP_FMT_NV12:
|
|
|
|
|
case MPP_FMT_NV21:
|
|
|
|
|
case MPP_FMT_NV16:
|
|
|
|
|
case MPP_FMT_NV61:
|
|
|
|
|
return 2;
|
|
|
|
|
case MPP_FMT_YUV420P:
|
|
|
|
|
case MPP_FMT_YUV422P:
|
|
|
|
|
case MPP_FMT_YUV444P:
|
|
|
|
|
return 3;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int get_src_phy_addr(struct mpp_ge *ge,
|
|
|
|
|
struct mpp_buf *video_buf)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
int plane_num;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
plane_num = ge_plane_num(video_buf->format);
|
|
|
|
|
|
|
|
|
|
if (video_buf->buf_type == MPP_DMA_BUF_FD) {
|
|
|
|
|
for (i = 0; i < plane_num; i++) {
|
|
|
|
|
if (dma_fd_to_addr(ge, video_buf->fd[i],
|
|
|
|
|
&cmdq->data.src_phy_addr[i]) < 0) {
|
|
|
|
|
printf("can't find src dma fd: %d\n", video_buf->fd[0]);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < plane_num; i++) {
|
|
|
|
|
|
|
|
|
|
cmdq->data.src_phy_addr[i] = video_buf->phy_addr[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int get_dst_phy_addr(struct mpp_ge *ge,
|
|
|
|
|
struct mpp_buf *video_buf)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
int plane_num;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
plane_num = ge_plane_num(video_buf->format);
|
|
|
|
|
|
|
|
|
|
if (video_buf->buf_type == MPP_DMA_BUF_FD) {
|
|
|
|
|
for (i = 0; i < plane_num; i++) {
|
|
|
|
|
if(dma_fd_to_addr(ge, video_buf->fd[i],
|
|
|
|
|
&cmdq->data.dst_phy_addr[i]) < 0) {
|
|
|
|
|
printf("can't find dst dma fd: %d\n", video_buf->fd[0]);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < plane_num; i++) {
|
|
|
|
|
|
|
|
|
|
cmdq->data.dst_phy_addr[i] = video_buf->phy_addr[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void make_cmd_buf_valid(struct cmd_queue *cmdq, struct aic_ge_client *dev_fd)
|
|
|
|
|
{
|
|
|
|
|
/* cur task need enough buf */
|
|
|
|
|
if (cmdq->write_offset + VALID_SPACE > cmdq->total_size) {
|
|
|
|
|
flush_cmd(cmdq, dev_fd);
|
|
|
|
|
cmdq->write_offset = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int *get_cmd_buf(struct cmd_queue *cmdq, struct aic_ge_client *dev_fd)
|
|
|
|
|
{
|
|
|
|
|
// reserved space for cmd group header
|
|
|
|
|
return &cmdq->cmd_buf[cmdq->write_offset + 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int update_cmd_group(struct cmd_queue *cmdq,
|
|
|
|
|
unsigned int offset,
|
|
|
|
|
unsigned int length,
|
|
|
|
|
unsigned int task_end)
|
|
|
|
|
{
|
|
|
|
|
cmdq->cmd_buf[cmdq->write_offset] = (offset << 16)
|
|
|
|
|
| (length << 2) | task_end;
|
|
|
|
|
|
|
|
|
|
/* cmd groud should be 8 bytes aligned */
|
|
|
|
|
cmdq->write_offset += ALIGN_2B(length + 1);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_alpha_rules_and_premul(struct ge_data *data,
|
|
|
|
|
struct ge_ctrl *ctrl,
|
|
|
|
|
enum mpp_pixel_format src_format,
|
|
|
|
|
enum mpp_pixel_format dst_format,
|
|
|
|
|
unsigned int src_buf_flags,
|
|
|
|
|
unsigned int dst_buf_flags,
|
|
|
|
|
int is_fill_color)
|
|
|
|
|
{
|
|
|
|
|
if (ctrl->alpha_en)
|
|
|
|
|
set_alpha_rules(data, ctrl->alpha_rules);
|
|
|
|
|
|
|
|
|
|
set_premuliply(data, src_format, dst_format,
|
|
|
|
|
MPP_BUF_PREMULTIPLY_GET(src_buf_flags),
|
|
|
|
|
MPP_BUF_PREMULTIPLY_GET(dst_buf_flags),
|
|
|
|
|
is_fill_color, ctrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_csc_flow(struct ge_data *data,
|
|
|
|
|
struct ge_ctrl *ctrl,
|
|
|
|
|
enum mpp_pixel_format src_format,
|
|
|
|
|
enum mpp_pixel_format dst_format)
|
|
|
|
|
{
|
|
|
|
|
int src_is_rgb = is_rgb(src_format);
|
|
|
|
|
int dst_is_rgb = is_rgb(dst_format);
|
|
|
|
|
int is_blending = need_blend(ctrl);
|
|
|
|
|
|
|
|
|
|
data->blend_is_rgb = 1;
|
|
|
|
|
|
|
|
|
|
if (!src_is_rgb &&
|
|
|
|
|
(is_blending || dst_is_rgb)) {
|
|
|
|
|
data->csc0_en = 1;
|
|
|
|
|
} else if (!src_is_rgb) {
|
|
|
|
|
data->blend_is_rgb = 0;
|
|
|
|
|
data->csc0_en = 0;
|
|
|
|
|
} else {
|
|
|
|
|
data->csc0_en = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_blending && !dst_is_rgb)
|
|
|
|
|
data->csc1_en = 1;
|
|
|
|
|
else
|
|
|
|
|
data->csc1_en = 0;
|
|
|
|
|
|
|
|
|
|
if (data->blend_is_rgb && !dst_is_rgb)
|
|
|
|
|
data->csc2_en = 1;
|
|
|
|
|
else
|
|
|
|
|
data->csc2_en = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_alpha_rules(struct ge_data *data,
|
|
|
|
|
enum ge_pd_rules rules)
|
|
|
|
|
{
|
|
|
|
|
switch (rules) {
|
|
|
|
|
case GE_PD_NONE:
|
|
|
|
|
data->src_alpha_coef = 2;
|
|
|
|
|
data->dst_alpha_coef = 3;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_CLEAR:
|
|
|
|
|
data->src_alpha_coef = 0;
|
|
|
|
|
data->dst_alpha_coef = 0;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_SRC:
|
|
|
|
|
data->src_alpha_coef = 1;
|
|
|
|
|
data->dst_alpha_coef = 0;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_SRC_OVER:
|
|
|
|
|
data->src_alpha_coef = 1;
|
|
|
|
|
data->dst_alpha_coef = 3;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_DST_OVER:
|
|
|
|
|
data->src_alpha_coef = 5;
|
|
|
|
|
data->dst_alpha_coef = 1;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_SRC_IN:
|
|
|
|
|
data->src_alpha_coef = 4;
|
|
|
|
|
data->dst_alpha_coef = 0;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_DST_IN:
|
|
|
|
|
data->src_alpha_coef = 0;
|
|
|
|
|
data->dst_alpha_coef = 2;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_SRC_OUT:
|
|
|
|
|
data->src_alpha_coef = 5;
|
|
|
|
|
data->dst_alpha_coef = 0;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_DST_OUT:
|
|
|
|
|
data->src_alpha_coef = 0;
|
|
|
|
|
data->dst_alpha_coef = 3;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_SRC_ATOP:
|
|
|
|
|
data->src_alpha_coef = 4;
|
|
|
|
|
data->dst_alpha_coef = 3;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_DST_ATOP:
|
|
|
|
|
data->src_alpha_coef = 5;
|
|
|
|
|
data->dst_alpha_coef = 2;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_ADD:
|
|
|
|
|
data->src_alpha_coef = 1;
|
|
|
|
|
data->dst_alpha_coef = 1;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_XOR:
|
|
|
|
|
data->src_alpha_coef = 5;
|
|
|
|
|
data->dst_alpha_coef = 3;
|
|
|
|
|
break;
|
|
|
|
|
case GE_PD_DST:
|
|
|
|
|
data->src_alpha_coef = 0;
|
|
|
|
|
data->dst_alpha_coef = 1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
data->src_alpha_coef = 2;
|
|
|
|
|
data->dst_alpha_coef = 3;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* must call set_premuliply after set_alpha_rules */
|
|
|
|
|
static int set_premuliply(struct ge_data *data,
|
|
|
|
|
enum mpp_pixel_format src_format,
|
|
|
|
|
enum mpp_pixel_format dst_format,
|
|
|
|
|
int src_premul,
|
|
|
|
|
int dst_premul,
|
|
|
|
|
int is_fill_color,
|
|
|
|
|
struct ge_ctrl *ctrl)
|
|
|
|
|
{
|
|
|
|
|
if (src_format > MPP_FMT_BGRA_4444)
|
|
|
|
|
src_premul = 0;
|
|
|
|
|
|
|
|
|
|
if (dst_format > MPP_FMT_BGRA_4444)
|
|
|
|
|
dst_premul = 0;
|
|
|
|
|
|
|
|
|
|
if (src_premul == 0 && dst_premul == 0) {
|
|
|
|
|
data->src_premul_en = 0;
|
|
|
|
|
data->src_de_premul_en = 0;
|
|
|
|
|
data->dst_de_premul_en = 0;
|
|
|
|
|
data->out_premul_en = 0;
|
|
|
|
|
|
|
|
|
|
if (is_fill_color == 0 &&
|
|
|
|
|
ctrl->src_alpha_mode == 0 &&
|
|
|
|
|
ctrl->alpha_en &&
|
|
|
|
|
ctrl->ck_en == 0 &&
|
|
|
|
|
data->src_alpha_coef == 2 &&
|
|
|
|
|
data->dst_alpha_coef == 3) {
|
|
|
|
|
data->src_premul_en = 1;
|
|
|
|
|
data->src_alpha_coef = 1;
|
|
|
|
|
}
|
|
|
|
|
} else if (src_premul == 1 && dst_premul == 0) {
|
|
|
|
|
data->src_premul_en = 0;
|
|
|
|
|
data->src_de_premul_en = 1;
|
|
|
|
|
data->dst_de_premul_en = 0;
|
|
|
|
|
data->out_premul_en = 0;
|
|
|
|
|
|
|
|
|
|
if (ctrl->src_alpha_mode == 0 &&
|
|
|
|
|
ctrl->alpha_en &&
|
|
|
|
|
ctrl->ck_en == 0 &&
|
|
|
|
|
data->src_alpha_coef == 2 &&
|
|
|
|
|
data->dst_alpha_coef == 3) {
|
|
|
|
|
data->src_de_premul_en = 0;
|
|
|
|
|
data->src_alpha_coef = 1;
|
|
|
|
|
}
|
|
|
|
|
} else if (src_premul == 1 && dst_premul == 1) {
|
|
|
|
|
data->src_premul_en = 0;
|
|
|
|
|
data->src_de_premul_en = 1;
|
|
|
|
|
data->dst_de_premul_en = 1;
|
|
|
|
|
data->out_premul_en = 1;
|
|
|
|
|
} else if (src_premul == 0 && dst_premul == 1) {
|
|
|
|
|
data->src_premul_en = 0;
|
|
|
|
|
data->src_de_premul_en = 0;
|
|
|
|
|
data->dst_de_premul_en = 1;
|
|
|
|
|
data->out_premul_en = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int ge_set_src_ctrl(unsigned int global_alpha,
|
|
|
|
|
unsigned int alpha_mode,
|
|
|
|
|
unsigned int premul_en,
|
|
|
|
|
unsigned int scan_order,
|
|
|
|
|
unsigned int func_select,
|
|
|
|
|
unsigned int fmt,
|
|
|
|
|
unsigned int v_flip,
|
|
|
|
|
unsigned int h_flip,
|
|
|
|
|
unsigned int rot0_ctrl,
|
|
|
|
|
unsigned int source_mode,
|
|
|
|
|
unsigned int csc0_en)
|
|
|
|
|
{
|
|
|
|
|
unsigned int value = SRC_SURFACE_G_ALPHA_MODE(global_alpha) |
|
|
|
|
|
SRC_SURFACE_ALPHA_MODE(alpha_mode) |
|
|
|
|
|
SRC_SURFACE_P_MUL(premul_en) |
|
|
|
|
|
SRC_SURFACE_SCAN_ORDER(scan_order) |
|
|
|
|
|
SRC_SURFACE_FUNC_SELECT(func_select) |
|
|
|
|
|
SRC_SURFACE_FORMAT(fmt) |
|
|
|
|
|
SRC_SURFACE_V_FLIP_EN(v_flip) |
|
|
|
|
|
SRC_SURFACE_H_FLIP_EN(h_flip) |
|
|
|
|
|
SRC_SURFACE_ROT0_CTRL(rot0_ctrl) |
|
|
|
|
|
SRC_SURFACE_SOURCE_MODE(source_mode) |
|
|
|
|
|
SRC_SURFACE_CSC0_EN(csc0_en) |
|
|
|
|
|
SRC_SURFACE_EN;
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int ge_src_simple_ctrl(unsigned int global_alpha, unsigned int alpha_mode,
|
|
|
|
|
unsigned int premul_en, unsigned int func_select,
|
|
|
|
|
unsigned int fmt, unsigned int source_mode)
|
|
|
|
|
{
|
|
|
|
|
unsigned int value = SRC_SURFACE_G_ALPHA_MODE(global_alpha) |
|
|
|
|
|
SRC_SURFACE_ALPHA_MODE(alpha_mode) |
|
|
|
|
|
SRC_SURFACE_P_MUL(premul_en) |
|
|
|
|
|
SRC_SURFACE_FUNC_SELECT(func_select) |
|
|
|
|
|
SRC_SURFACE_FORMAT(fmt) |
|
|
|
|
|
SRC_SURFACE_SOURCE_MODE(source_mode) |
|
|
|
|
|
SRC_SURFACE_EN;
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int ge_output_ctrl(unsigned int premul, int fmt,
|
|
|
|
|
unsigned int dither_en, unsigned int csc2_en)
|
|
|
|
|
{
|
|
|
|
|
unsigned int value = OUTPUT_P_MUL(premul) |
|
|
|
|
|
OUTPUT_FORMAT(fmt) |
|
|
|
|
|
DITHER_EN(dither_en) |
|
|
|
|
|
OUTPUT_CSC2_EN(csc2_en);
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int ge_dst_ctrl(unsigned int global_alpha,
|
|
|
|
|
unsigned int alpha_mode, int fmt, unsigned int csc1_en)
|
|
|
|
|
{
|
|
|
|
|
unsigned int value = DST_SURFACE_G_ALPHA_MODE(global_alpha) |
|
|
|
|
|
DST_SURFACE_ALPHA_MODE(alpha_mode) |
|
|
|
|
|
DST_SURFACE_FORMAT(fmt) |
|
|
|
|
|
DST_SURFACE_CSC1_EN(csc1_en) |
|
|
|
|
|
DST_SURFACE_EN;
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void update_gradient_cmd(struct mpp_ge *ge, int width, int height,
|
|
|
|
|
unsigned start_color, unsigned end_color,
|
|
|
|
|
unsigned direction)
|
|
|
|
|
{
|
|
|
|
|
int a_step, r_step, g_step, b_step;
|
|
|
|
|
int length;
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
unsigned char start_a = (unsigned char)((start_color >> 24) & 0xff);
|
|
|
|
|
unsigned char start_r = (unsigned char)((start_color >> 16) & 0xff);
|
|
|
|
|
unsigned char start_g = (unsigned char)((start_color >> 8) & 0xff);
|
|
|
|
|
unsigned char start_b = (unsigned char)(start_color & 0xff);
|
|
|
|
|
|
|
|
|
|
unsigned char end_a = (unsigned char)((end_color >> 24) & 0xff);
|
|
|
|
|
unsigned char end_r = (unsigned char)((end_color >> 16) & 0xff);
|
|
|
|
|
unsigned char end_g = (unsigned char)((end_color >> 8) & 0xff);
|
|
|
|
|
unsigned char end_b = (unsigned char)(end_color & 0xff);
|
|
|
|
|
|
|
|
|
|
if (direction == 0)
|
|
|
|
|
length = width;
|
|
|
|
|
else
|
|
|
|
|
length = height;
|
|
|
|
|
|
|
|
|
|
a_step = length > 1 ?
|
|
|
|
|
((end_a - start_a) << 16) / (length - 1) : 0;
|
|
|
|
|
r_step = length > 1 ?
|
|
|
|
|
((end_r - start_r) << 16) / (length - 1) : 0;
|
|
|
|
|
g_step = length > 1 ?
|
|
|
|
|
((end_g - start_g) << 16) / (length - 1) : 0;
|
|
|
|
|
b_step = length > 1 ?
|
|
|
|
|
((end_b - start_b) << 16) / (length - 1) : 0;
|
|
|
|
|
|
|
|
|
|
cmd[0] = SRC_GRADIENT_STEP_SET(a_step);
|
|
|
|
|
cmd[1] = SRC_GRADIENT_STEP_SET(r_step);
|
|
|
|
|
cmd[3] = SRC_GRADIENT_STEP_SET(g_step);
|
|
|
|
|
cmd[3] = SRC_GRADIENT_STEP_SET(b_step);
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x30, 4, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_rot1_cmd(struct mpp_ge *ge,
|
|
|
|
|
int angle_sin, int angle_cos,
|
|
|
|
|
int src_center_x, int src_center_y,
|
|
|
|
|
int dst_center_x, int dst_center_y)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd[0] = SRC_ROT1_CENTER_SET(src_center_x, src_center_y); //FIXME
|
|
|
|
|
cmd[1] = SRC_ROT1_DEGREE_SET(angle_sin, angle_cos);
|
|
|
|
|
cmd[2] = DST_ROT1_CENTER_SET(dst_center_x, dst_center_y);
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x70, 3, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* must call blend at the end, because update_cmd_group()
|
|
|
|
|
* emit end task flag in this function
|
|
|
|
|
*/
|
|
|
|
|
static void update_blend_cmd(struct mpp_ge *ge,
|
|
|
|
|
unsigned int src_de_premul,
|
|
|
|
|
unsigned int dst_de_premul,
|
|
|
|
|
unsigned int alpha_ctrl,
|
|
|
|
|
unsigned int src_alpha_coef,
|
|
|
|
|
unsigned int dst_alpha_coef,
|
|
|
|
|
unsigned int ck_en,
|
|
|
|
|
unsigned int ck_value,
|
|
|
|
|
unsigned int alpha_en)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = SRC_DE_P_MUL(src_de_premul) |
|
|
|
|
|
DST_DE_P_MUL(dst_de_premul) |
|
|
|
|
|
OUTPUT_ALPHA_CTRL(alpha_ctrl) |
|
|
|
|
|
SRC_ALPHA_COEF(src_alpha_coef) |
|
|
|
|
|
DST_ALPHA_COEF(dst_alpha_coef) |
|
|
|
|
|
CK_EN(ck_en) |
|
|
|
|
|
ALPHA_BLEND_EN(alpha_en);
|
|
|
|
|
|
|
|
|
|
cmd[1] = ck_value;
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x90, 2, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void update_scaler0_cmd(struct mpp_ge *ge,
|
|
|
|
|
unsigned int input_w,
|
|
|
|
|
unsigned int input_h,
|
|
|
|
|
unsigned int output_w,
|
|
|
|
|
unsigned int output_h,
|
|
|
|
|
int dx, int dy,
|
|
|
|
|
int h_phase, int v_phase,
|
|
|
|
|
unsigned int channel)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = SCALER0_INPUT_SIZE_SET(input_w, input_h);
|
|
|
|
|
cmd[1] = SCALER0_OUTPUT_SIZE_SET(output_w, output_h);
|
|
|
|
|
cmd[2] = SCALER0_H_INIT_PHASE_SET(h_phase);
|
|
|
|
|
cmd[3] = SCALER0_H_RATIO_SET(dx);
|
|
|
|
|
cmd[4] = SCALER0_V_INIT_PHASE_SET(v_phase);
|
|
|
|
|
cmd[5] = SCALER0_V_RATIO_SET(dy);
|
|
|
|
|
|
|
|
|
|
if (channel == 0)
|
|
|
|
|
update_cmd_group(cmdq, 0x210, 6, 0);
|
|
|
|
|
else
|
|
|
|
|
update_cmd_group(cmdq, 0x230, 6, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int update_fillrect_cmd(struct mpp_ge *ge,
|
|
|
|
|
struct ge_fillrect *fill)
|
|
|
|
|
{
|
|
|
|
|
struct ge_data *data;
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
unsigned int dst_w;
|
|
|
|
|
unsigned int dst_h;
|
|
|
|
|
unsigned int dst_addr[3];
|
|
|
|
|
unsigned int dst_stride[2];
|
|
|
|
|
unsigned int src_ctrl;
|
|
|
|
|
unsigned int dst_ctrl;
|
|
|
|
|
unsigned int out_ctrl;
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* src cmd */
|
|
|
|
|
data = &cmdq->data;
|
|
|
|
|
dst_w = fill->dst_buf.crop.width;
|
|
|
|
|
dst_h = fill->dst_buf.crop.height;
|
|
|
|
|
|
|
|
|
|
src_ctrl = ge_src_simple_ctrl(fill->ctrl.src_global_alpha,
|
|
|
|
|
fill->ctrl.src_alpha_mode,
|
|
|
|
|
data->src_premul_en,
|
|
|
|
|
0, /* func_select */
|
|
|
|
|
MPP_FMT_ARGB_8888,
|
|
|
|
|
fill->type + 1); /* source_mode */
|
|
|
|
|
|
|
|
|
|
update_src_fillrect_cmd(ge, src_ctrl,
|
|
|
|
|
dst_w, dst_h,
|
|
|
|
|
fill->start_color);
|
|
|
|
|
|
|
|
|
|
/* out cmd */
|
|
|
|
|
out_ctrl = ge_output_ctrl(data->out_premul_en,
|
|
|
|
|
fill->dst_buf.format,
|
|
|
|
|
fill->ctrl.dither_en,
|
|
|
|
|
data->csc2_en);
|
|
|
|
|
|
|
|
|
|
dst_addr[0] = cmdq->data.dst_phy_addr[0];
|
|
|
|
|
dst_addr[1] = cmdq->data.dst_phy_addr[1];
|
|
|
|
|
dst_addr[2] = cmdq->data.dst_phy_addr[2];
|
|
|
|
|
|
|
|
|
|
dst_stride[0] = fill->dst_buf.stride[0];
|
|
|
|
|
dst_stride[1] = fill->dst_buf.stride[1];
|
|
|
|
|
|
|
|
|
|
ge_buf_crop(dst_addr, dst_stride,
|
|
|
|
|
fill->dst_buf.format,
|
|
|
|
|
fill->dst_buf.crop.x,
|
|
|
|
|
fill->dst_buf.crop.y,
|
|
|
|
|
dst_w,
|
|
|
|
|
dst_h);
|
|
|
|
|
|
|
|
|
|
update_output_cmd(ge, out_ctrl, dst_w, dst_h,
|
|
|
|
|
dst_stride[0], dst_stride[1],
|
|
|
|
|
dst_addr);
|
|
|
|
|
|
|
|
|
|
/* dst cmd */
|
|
|
|
|
if (need_blend(&fill->ctrl)) {
|
|
|
|
|
dst_ctrl = ge_dst_ctrl(fill->ctrl.dst_global_alpha,
|
|
|
|
|
fill->ctrl.dst_alpha_mode,
|
|
|
|
|
fill->dst_buf.format,
|
|
|
|
|
data->csc1_en);
|
|
|
|
|
|
|
|
|
|
update_dst_cmd(ge, dst_ctrl, dst_w, dst_h,
|
|
|
|
|
dst_stride[0], dst_stride[1],
|
|
|
|
|
dst_addr);
|
|
|
|
|
} else {
|
|
|
|
|
update_dst_disable_cmd(ge);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int update_basic_cmd(struct mpp_ge *ge,
|
|
|
|
|
struct mpp_buf *src_buf,
|
|
|
|
|
struct mpp_buf *dst_buf,
|
|
|
|
|
struct ge_ctrl *ctrl)
|
|
|
|
|
{
|
|
|
|
|
struct ge_data *data;
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
unsigned int src_w;
|
|
|
|
|
unsigned int src_h;
|
|
|
|
|
unsigned int dst_w;
|
|
|
|
|
unsigned int dst_h;
|
|
|
|
|
unsigned int src_addr[3];
|
|
|
|
|
unsigned int dst_addr[3];
|
|
|
|
|
unsigned int src_stride[2];
|
|
|
|
|
unsigned int dst_stride[2];
|
|
|
|
|
unsigned int src_ctrl;
|
|
|
|
|
unsigned int dst_ctrl;
|
|
|
|
|
unsigned int out_ctrl;
|
|
|
|
|
struct mpp_rect *src_rect;
|
|
|
|
|
struct mpp_rect *dst_rect;
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
data = &cmdq->data;
|
|
|
|
|
src_rect = &src_buf->crop;
|
|
|
|
|
dst_rect = &dst_buf->crop;
|
|
|
|
|
src_w = src_rect->width;
|
|
|
|
|
src_h = src_rect->height;
|
|
|
|
|
dst_w = dst_rect->width;
|
|
|
|
|
dst_h = dst_rect->height;
|
|
|
|
|
|
|
|
|
|
src_addr[0] = data->src_phy_addr[0];
|
|
|
|
|
src_addr[1] = data->src_phy_addr[1];
|
|
|
|
|
src_addr[2] = data->src_phy_addr[2];
|
|
|
|
|
|
|
|
|
|
dst_addr[0] = data->dst_phy_addr[0];
|
|
|
|
|
dst_addr[1] = data->dst_phy_addr[1];
|
|
|
|
|
dst_addr[2] = data->dst_phy_addr[2];
|
|
|
|
|
|
|
|
|
|
src_stride[0] = src_buf->stride[0];
|
|
|
|
|
src_stride[1] = src_buf->stride[1];
|
|
|
|
|
dst_stride[0] = dst_buf->stride[0];
|
|
|
|
|
dst_stride[1] = dst_buf->stride[1];
|
|
|
|
|
|
|
|
|
|
src_ctrl = data->src_ctrl;
|
|
|
|
|
out_ctrl = data->out_ctrl;
|
|
|
|
|
|
|
|
|
|
ge_buf_crop(src_addr, src_stride,
|
|
|
|
|
src_buf->format,
|
|
|
|
|
src_rect->x,
|
|
|
|
|
src_rect->y,
|
|
|
|
|
src_w,
|
|
|
|
|
src_h);
|
|
|
|
|
|
|
|
|
|
ge_buf_crop(dst_addr, dst_stride,
|
|
|
|
|
dst_buf->format,
|
|
|
|
|
dst_rect->x,
|
|
|
|
|
dst_rect->y,
|
|
|
|
|
dst_w,
|
|
|
|
|
dst_h);
|
|
|
|
|
|
|
|
|
|
/* src cmd */
|
|
|
|
|
update_src_cmd(ge, src_ctrl, src_w, src_h,
|
|
|
|
|
src_stride[0], src_stride[1],
|
|
|
|
|
src_addr);
|
|
|
|
|
|
|
|
|
|
/* out cmd */
|
|
|
|
|
update_output_cmd(ge, out_ctrl, dst_w, dst_h,
|
|
|
|
|
dst_stride[0], dst_stride[1],
|
|
|
|
|
dst_addr);
|
|
|
|
|
|
|
|
|
|
/* dst cmd */
|
|
|
|
|
if (need_blend(ctrl)) {
|
|
|
|
|
dst_ctrl = ge_dst_ctrl(ctrl->dst_global_alpha,
|
|
|
|
|
ctrl->dst_alpha_mode,
|
|
|
|
|
dst_buf->format,
|
|
|
|
|
data->csc1_en);
|
|
|
|
|
|
|
|
|
|
update_dst_cmd(ge, dst_ctrl, dst_w, dst_h,
|
|
|
|
|
dst_stride[0], dst_stride[1],
|
|
|
|
|
dst_addr);
|
|
|
|
|
} else {
|
|
|
|
|
update_dst_disable_cmd(ge);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void ge_dst_disable(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = 0;
|
|
|
|
|
update_cmd_group(cmdq, 0x50, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void scaler0_en_cmd(struct mpp_ge *ge, unsigned int enable)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = enable;
|
|
|
|
|
update_cmd_group(cmdq, 0x200, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* csc:
|
|
|
|
|
* 0: csc0
|
|
|
|
|
* 1: csc1
|
|
|
|
|
*/
|
|
|
|
|
static void update_csc_cmd(struct mpp_ge *ge, int color_space,
|
|
|
|
|
unsigned int csc)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int *coefs;
|
|
|
|
|
int i;
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
switch (color_space) {
|
|
|
|
|
case MPP_COLOR_SPACE_BT601:
|
|
|
|
|
coefs = yuv2rgb_bt601;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_COLOR_SPACE_BT709:
|
|
|
|
|
coefs = yuv2rgb_bt709;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_COLOR_SPACE_BT601_FULL_RANGE:
|
|
|
|
|
coefs = yuv2rgb_bt601_full;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_COLOR_SPACE_BT709_FULL_RANGE:
|
|
|
|
|
coefs = yuv2rgb_bt709_full;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
coefs = yuv2rgb_bt601;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < CSC_COEFFS_NUM; i++)
|
|
|
|
|
cmd[i] = coefs[i];
|
|
|
|
|
|
|
|
|
|
if (csc == 0)
|
|
|
|
|
update_cmd_group(cmdq, 0x140, 12, 0);
|
|
|
|
|
else
|
|
|
|
|
update_cmd_group(cmdq, 0x170, 12, 0);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_csc2_cmd(struct mpp_ge *ge, int color_space)
|
|
|
|
|
{
|
|
|
|
|
const int *coefs;
|
|
|
|
|
int i;
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
/* get cmd buf */
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
switch (color_space) {
|
|
|
|
|
case MPP_COLOR_SPACE_BT601:
|
|
|
|
|
coefs = rgb2yuv_bt601;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_COLOR_SPACE_BT709:
|
|
|
|
|
coefs = rgb2yuv_bt709;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_COLOR_SPACE_BT601_FULL_RANGE:
|
|
|
|
|
coefs = rgb2yuv_bt601_full;
|
|
|
|
|
break;
|
|
|
|
|
case MPP_COLOR_SPACE_BT709_FULL_RANGE:
|
|
|
|
|
coefs = rgb2yuv_bt709_full;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
coefs = rgb2yuv_bt601;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < CSC_COEFFS_NUM; i++)
|
|
|
|
|
cmd[i] = coefs[i];
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x1a0, 12, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_src_cmd(struct mpp_ge *ge, unsigned int src_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int stride0, unsigned int stride1,
|
|
|
|
|
unsigned int addr[])
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = src_ctrl;
|
|
|
|
|
cmd[1] = SRC_INPUT_SIZE_SET(w, h);
|
|
|
|
|
cmd[2] = SRC_STRIDE_SET(stride0, stride1);
|
|
|
|
|
cmd[3] = 0;
|
|
|
|
|
cmd[4] = addr[0];
|
|
|
|
|
cmd[5] = addr[1];
|
|
|
|
|
cmd[6] = addr[2];
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x10, 7, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_src_fillrect_cmd(struct mpp_ge *ge, unsigned int src_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int start_color)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = src_ctrl;
|
|
|
|
|
cmd[1] = SRC_INPUT_SIZE_SET(w, h);
|
|
|
|
|
cmd[2] = 0;
|
|
|
|
|
cmd[3] = start_color;
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x10, 4, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_dst_cmd(struct mpp_ge *ge, unsigned int dst_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int stride0, unsigned int stride1,
|
|
|
|
|
unsigned int addr[])
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = dst_ctrl;
|
|
|
|
|
cmd[1] = DST_INPUT_SIZE_SET(w, h);
|
|
|
|
|
cmd[2] = DST_STRIDE_SET(stride0, stride1);
|
|
|
|
|
cmd[3] = 0;
|
|
|
|
|
cmd[4] = addr[0];
|
|
|
|
|
cmd[5] = addr[1];
|
|
|
|
|
cmd[6] = addr[2];
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x50, 7, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_dst_disable_cmd(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = 0;
|
|
|
|
|
update_cmd_group(cmdq, 0x50, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_output_cmd(struct mpp_ge *ge, unsigned int out_ctrl,
|
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
|
unsigned int stride0, unsigned int stride1,
|
|
|
|
|
unsigned int addr[])
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq = to_cmdq(ge);
|
|
|
|
|
unsigned int *cmd = get_cmd_buf(cmdq, ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
cmd[0] = out_ctrl;
|
|
|
|
|
cmd[1] = OUTPUT_SIZE_SET(w, h);
|
|
|
|
|
cmd[2] = OUTPUT_STRIDE_SET(stride0, stride1);
|
|
|
|
|
cmd[3] = 0;
|
|
|
|
|
cmd[4] = addr[0];
|
|
|
|
|
cmd[5] = addr[1];
|
|
|
|
|
cmd[6] = addr[2];
|
|
|
|
|
|
|
|
|
|
update_cmd_group(cmdq, 0x100, 7, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_cmd_buf_size(struct mpp_ge *ge, unsigned int *buf_size)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ret = aic_ge_ioctl(ge->dev_fd, IOC_GE_CMD_BUF_SIZE, buf_size);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
printf("ge_cmd_buf_size failed %d\n", ret);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_open(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
cmdq = (struct cmd_queue *)aicos_malloc(0, sizeof(struct cmd_queue));
|
|
|
|
|
|
|
|
|
|
if (!cmdq) {
|
|
|
|
|
printf("cmdq aicos_malloc failed!\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(cmdq, 0, sizeof(struct cmd_queue));
|
|
|
|
|
ge->priv = cmdq;
|
|
|
|
|
|
|
|
|
|
if (ge_cmd_buf_size(ge, &cmdq->total_size) < 0)
|
|
|
|
|
cmdq->total_size = ALIGN_8B(DEFAULT_CMD_SIZE);
|
|
|
|
|
|
|
|
|
|
cmdq->cmd_buf = (unsigned int *)aicos_malloc(0, cmdq->total_size);
|
|
|
|
|
if (!cmdq->cmd_buf) {
|
|
|
|
|
printf("cmd_buf aicos_malloc failed!\n");
|
|
|
|
|
aicos_free(0, cmdq);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(cmdq->cmd_buf, 0, cmdq->total_size);
|
|
|
|
|
|
|
|
|
|
/* init dma info lists */
|
|
|
|
|
mpp_list_init(&cmdq->dma_list);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_close(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
|
|
|
|
|
if (cmdq) {
|
|
|
|
|
clean_dma_buf_list(ge);
|
|
|
|
|
if (cmdq->cmd_buf)
|
|
|
|
|
aicos_free(0, cmdq->cmd_buf);
|
|
|
|
|
|
|
|
|
|
aicos_free(0, cmdq);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_fillrect(struct mpp_ge *ge, struct ge_fillrect *fill)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
int en_alpha_out_oxff;
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
struct ge_data *data;
|
|
|
|
|
enum mpp_pixel_format src_fmt;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
#ifdef AIC_GE_DRV_V11
|
|
|
|
|
/* check rgb type */
|
|
|
|
|
if (!is_rgb_or_yuv400(fill->dst_buf.format)) {
|
|
|
|
|
printf("fill rectangle not support yuv format, except yuv400\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
data = &cmdq->data;
|
|
|
|
|
src_fmt = MPP_FMT_ARGB_8888;
|
|
|
|
|
en_alpha_out_oxff = 0;
|
|
|
|
|
|
|
|
|
|
if (check_fillrect(ge, fill) < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (get_dst_phy_addr(ge, &fill->dst_buf) < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
make_cmd_buf_valid(cmdq, ge->dev_fd);
|
|
|
|
|
set_alpha_rules_and_premul(data, &fill->ctrl,
|
|
|
|
|
src_fmt, fill->dst_buf.format,
|
|
|
|
|
0, fill->dst_buf.flags,
|
|
|
|
|
1);
|
|
|
|
|
set_csc_flow(data, &fill->ctrl,
|
|
|
|
|
src_fmt, fill->dst_buf.format);
|
|
|
|
|
|
|
|
|
|
/* csc1 cmd */
|
|
|
|
|
if (data->csc1_en)
|
|
|
|
|
update_csc_cmd(ge,
|
|
|
|
|
MPP_BUF_COLOR_SPACE_GET(fill->dst_buf.flags),
|
|
|
|
|
1);
|
|
|
|
|
|
|
|
|
|
/* csc2 cmd */
|
|
|
|
|
if (data->csc2_en)
|
|
|
|
|
update_csc2_cmd(ge,
|
|
|
|
|
MPP_BUF_COLOR_SPACE_GET(fill->dst_buf.flags));
|
|
|
|
|
|
|
|
|
|
switch (fill->type) {
|
|
|
|
|
case GE_NO_GRADIENT:
|
|
|
|
|
break;
|
|
|
|
|
case GE_H_LINEAR_GRADIENT:
|
|
|
|
|
update_gradient_cmd(ge,
|
|
|
|
|
fill->dst_buf.crop.width,
|
|
|
|
|
fill->dst_buf.crop.height,
|
|
|
|
|
fill->start_color,
|
|
|
|
|
fill->end_color,
|
|
|
|
|
0);
|
|
|
|
|
break;
|
|
|
|
|
case GE_V_LINEAR_GRADIENT:
|
|
|
|
|
update_gradient_cmd(ge,
|
|
|
|
|
fill->dst_buf.crop.width,
|
|
|
|
|
fill->dst_buf.crop.height,
|
|
|
|
|
fill->start_color,
|
|
|
|
|
fill->end_color,
|
|
|
|
|
1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
update_fillrect_cmd(ge, fill);
|
|
|
|
|
scaler0_en_cmd(ge, 0);
|
|
|
|
|
|
|
|
|
|
/* must call update_blend_cmd at the end */
|
|
|
|
|
update_blend_cmd(ge,
|
|
|
|
|
data->src_de_premul_en,
|
|
|
|
|
data->dst_de_premul_en,
|
|
|
|
|
en_alpha_out_oxff,
|
|
|
|
|
data->src_alpha_coef,
|
|
|
|
|
data->dst_alpha_coef,
|
|
|
|
|
fill->ctrl.ck_en,
|
|
|
|
|
fill->ctrl.ck_value,
|
|
|
|
|
fill->ctrl.alpha_en);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_bitblt(struct mpp_ge *ge, struct ge_bitblt *blt)
|
|
|
|
|
{
|
|
|
|
|
int en_alpha_out_oxff;
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
struct ge_data *data;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
#ifdef AIC_GE_DRV_V11
|
|
|
|
|
/* check rgb type */
|
|
|
|
|
if (!is_rgb_or_yuv400(blt->src_buf.format) ||
|
|
|
|
|
!is_rgb(blt->dst_buf.format)) {
|
|
|
|
|
printf("bitblt not support yuv format, except src format yuv400\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
data = &cmdq->data;
|
|
|
|
|
en_alpha_out_oxff = 0;
|
|
|
|
|
|
|
|
|
|
if (check_bitblt(ge, blt) != 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (get_src_phy_addr(ge, &blt->src_buf) < 0 ||
|
|
|
|
|
get_dst_phy_addr(ge, &blt->dst_buf) < 0) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
make_cmd_buf_valid(cmdq, ge->dev_fd);
|
|
|
|
|
set_alpha_rules_and_premul(data, &blt->ctrl,
|
|
|
|
|
blt->src_buf.format, blt->dst_buf.format,
|
|
|
|
|
blt->src_buf.flags, blt->dst_buf.flags,
|
|
|
|
|
0);
|
|
|
|
|
set_csc_flow(data, &blt->ctrl,
|
|
|
|
|
blt->src_buf.format, blt->dst_buf.format);
|
|
|
|
|
|
|
|
|
|
/* csc0 cmd */
|
|
|
|
|
if (data->csc0_en)
|
|
|
|
|
update_csc_cmd(ge,
|
|
|
|
|
MPP_BUF_COLOR_SPACE_GET(blt->src_buf.flags),
|
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
/* csc1 cmd */
|
|
|
|
|
if (data->csc1_en)
|
|
|
|
|
update_csc_cmd(ge,
|
|
|
|
|
MPP_BUF_COLOR_SPACE_GET(blt->dst_buf.flags),
|
|
|
|
|
1);
|
|
|
|
|
|
|
|
|
|
/* csc2 cmd */
|
|
|
|
|
if (data->csc2_en)
|
|
|
|
|
update_csc2_cmd(ge,
|
|
|
|
|
MPP_BUF_COLOR_SPACE_GET(blt->dst_buf.flags));
|
|
|
|
|
|
|
|
|
|
data->src_ctrl = ge_set_src_ctrl(blt->ctrl.src_global_alpha,
|
|
|
|
|
blt->ctrl.src_alpha_mode,
|
|
|
|
|
data->src_premul_en,
|
|
|
|
|
MPP_SCAN_ORDER_GET(blt->ctrl.flags),
|
|
|
|
|
0, /* func_select */
|
|
|
|
|
blt->src_buf.format,
|
|
|
|
|
MPP_FLIP_V_GET(blt->ctrl.flags),
|
|
|
|
|
MPP_FLIP_H_GET(blt->ctrl.flags),
|
|
|
|
|
MPP_ROTATION_GET(blt->ctrl.flags),
|
|
|
|
|
0, /* fill buffer mode */
|
|
|
|
|
data->csc0_en);
|
|
|
|
|
|
|
|
|
|
data->out_ctrl = ge_output_ctrl(data->out_premul_en,
|
|
|
|
|
blt->dst_buf.format,
|
|
|
|
|
blt->ctrl.dither_en,
|
|
|
|
|
data->csc2_en);
|
|
|
|
|
|
|
|
|
|
update_basic_cmd(ge, &blt->src_buf, &blt->dst_buf, &blt->ctrl);
|
|
|
|
|
|
|
|
|
|
if (update_scaler_cmd(ge, blt) < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
/* must call update_blend_cmd at the end */
|
|
|
|
|
update_blend_cmd(ge,
|
|
|
|
|
data->src_de_premul_en,
|
|
|
|
|
data->dst_de_premul_en,
|
|
|
|
|
en_alpha_out_oxff,
|
|
|
|
|
data->src_alpha_coef,
|
|
|
|
|
data->dst_alpha_coef,
|
|
|
|
|
blt->ctrl.ck_en,
|
|
|
|
|
blt->ctrl.ck_value,
|
|
|
|
|
blt->ctrl.alpha_en);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_rotate(struct mpp_ge *ge, struct ge_rotation *rot)
|
|
|
|
|
{
|
|
|
|
|
int en_alpha_out_oxff;
|
|
|
|
|
struct cmd_queue *cmdq;
|
|
|
|
|
struct ge_data *data;
|
|
|
|
|
|
|
|
|
|
if(!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
/* check rgb type */
|
|
|
|
|
if (!is_rgb(rot->src_buf.format) ||
|
|
|
|
|
!is_rgb(rot->dst_buf.format)) {
|
|
|
|
|
printf("rotation does not support yuv format\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (MPP_SCAN_ORDER_GET(rot->ctrl.flags)) {
|
|
|
|
|
printf("starting scan order is not supported " \
|
|
|
|
|
"using the rotation\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmdq = to_cmdq(ge);
|
|
|
|
|
data = &cmdq->data;
|
|
|
|
|
en_alpha_out_oxff = 0;
|
|
|
|
|
|
|
|
|
|
if (check_format_and_size(ge, &rot->src_buf, &rot->dst_buf)!= 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (get_src_phy_addr(ge, &rot->src_buf) < 0 ||
|
|
|
|
|
get_dst_phy_addr(ge, &rot->dst_buf) < 0) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
make_cmd_buf_valid(cmdq, ge->dev_fd);
|
|
|
|
|
set_alpha_rules_and_premul(data, &rot->ctrl,
|
|
|
|
|
rot->src_buf.format, rot->dst_buf.format,
|
|
|
|
|
rot->src_buf.flags, rot->dst_buf.flags,
|
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
/* rot1 only support rgb format */
|
|
|
|
|
data->csc0_en = 0;
|
|
|
|
|
data->csc1_en = 0;
|
|
|
|
|
data->csc2_en = 0;
|
|
|
|
|
|
|
|
|
|
if(rot->ctrl.ck_en) {
|
|
|
|
|
printf("warning: rot does't support color key\n");
|
|
|
|
|
/* color must disable */
|
|
|
|
|
rot->ctrl.ck_en = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data->src_ctrl = ge_src_simple_ctrl(rot->ctrl.src_global_alpha,
|
|
|
|
|
rot->ctrl.src_alpha_mode,
|
|
|
|
|
data->src_premul_en,
|
|
|
|
|
1, /* rot1 */
|
|
|
|
|
rot->src_buf.format,
|
|
|
|
|
0); /* fill buffer mode */
|
|
|
|
|
|
|
|
|
|
data->out_ctrl = ge_output_ctrl(data->out_premul_en,
|
|
|
|
|
rot->dst_buf.format,
|
|
|
|
|
0, /* rot1 does't support dither */
|
|
|
|
|
data->csc2_en);
|
|
|
|
|
|
|
|
|
|
update_basic_cmd(ge, &rot->src_buf, &rot->dst_buf, &rot->ctrl);
|
|
|
|
|
|
|
|
|
|
update_rot1_cmd(ge, rot->angle_sin, rot->angle_cos,
|
|
|
|
|
rot->src_rot_center.x, rot->src_rot_center.y,
|
|
|
|
|
rot->dst_rot_center.x, rot->dst_rot_center.y);
|
|
|
|
|
|
|
|
|
|
scaler0_en_cmd(ge, 0);
|
|
|
|
|
|
|
|
|
|
/* must call update_blend_cmd at the end */
|
|
|
|
|
update_blend_cmd(ge,
|
|
|
|
|
data->src_de_premul_en,
|
|
|
|
|
data->dst_de_premul_en,
|
|
|
|
|
en_alpha_out_oxff,
|
|
|
|
|
data->src_alpha_coef,
|
|
|
|
|
data->dst_alpha_coef,
|
|
|
|
|
rot->ctrl.ck_en,
|
|
|
|
|
rot->ctrl.ck_value,
|
|
|
|
|
rot->ctrl.alpha_en);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_emit(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
ret = flush_cmd(to_cmdq(ge), ge->dev_fd);
|
|
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ge_sync(struct mpp_ge *ge)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (!ge)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
ret = aic_ge_ioctl(ge->dev_fd, IOC_GE_SYNC, NULL);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
printf("ge_sync failed %d\n", ret);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ge_ops ge_cmdq_ops = {
|
|
|
|
|
.name = "cmd queue",
|
|
|
|
|
.open = ge_open,
|
|
|
|
|
.close = ge_close,
|
|
|
|
|
.fillrect = ge_fillrect,
|
|
|
|
|
.bitblt = ge_bitblt,
|
|
|
|
|
.rotate = ge_rotate,
|
|
|
|
|
.emit = ge_emit,
|
|
|
|
|
.sync = ge_sync,
|
|
|
|
|
};
|