第一次提交

This commit is contained in:
2025-11-08 13:26:19 +08:00
commit 5854ac5b6e
10570 changed files with 4746154 additions and 0 deletions

View File

@@ -0,0 +1,546 @@
/**
* @file sdrv_asw.c
* @brief sdrv asw driver source.
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <armv7-r/cache.h>
#include <asw/asw.h>
#include <asw/asw_log.h>
#include <dispss/disp_data_type.h>
#include <g2dlite/g2dlite.h>
#include <irq.h>
#include <stdlib.h>
#include <string.h>
#include <udelay/udelay.h>
extern struct asw_operations sdrv_asw_ops;
#define TRI_SRC_W 1024
#define TRI_SRC_H 2
int tri_src[TRI_SRC_W * TRI_SRC_H * 4] = {0};
#define FILL_SRC_W 16
#define FILL_SRC_H 16
int fill_src[FILL_SRC_W * FILL_SRC_H * 4] = {0};
#define FILL_EX_W 35
#define FILL_EX_H 35
int blut_ext[FILL_EX_W * FILL_EX_H * 4 * 6] = {0};
static void asw_done(struct asw_dev *dev)
{
#if CONFIG_OS_FREERTOS
BaseType_t xReturn = xSemaphoreTake(dev->wdone_sema, pdMS_TO_TICKS(2000));
if (pdTRUE != xReturn) {
ASW_LOG_ERR("timeout for 2s !");
}
#else
int cnt = 0;
while (!dev->asw_done) {
udelay(10);
if (++cnt == 200000) {
ASW_LOG_ERR("timeout for 2s !");
break;
}
}
#endif
}
static int is_need_twice(double angle)
{
if ((angle > 45 && angle < 135) || (angle > 225 && angle < 315))
return 1;
return 0;
}
static int get_fmt_bpp(int fmt)
{
switch (fmt) {
case FMT_MONOTONIC_8BIT:
return 1;
case FMT_RGB565:
case FMT_ARGB1555:
case FMT_RGBA5551:
return 2;
case FMT_RGB_YUV888:
return 3;
case FMT_RGBA8888:
case FMT_ARGB8888:
return 4;
default:
ASW_LOG_ERR("can't support this fmt");
return -1;
}
}
static int color_to_bgcolor(int color)
{
int b, g, r, a;
b = (color >> 24) & 0xFF;
g = (color >> 16) & 0xFF;
r = (color >> 8) & 0xFF;
a = color & 0xFF;
return ((a << 24) | (b << 16) | (g << 8) | r);
}
void sdrv_asw_build_input(
struct asw_dev *dev, struct asw_input *input, int work_mode, int lut_mode,
int dst_fmt, int dst_hsize, int dst_vsize, int dst_ba, int dst_stride,
int dst_bg_color, int dst_flip, int src_fmt, int src_hsize, int src_vsize,
int src_ry_ba, int src_gu_ba, int src_bv_ba, int src_ry_stride,
int src_gu_stride, int src_bv_stride, int src_flip, int asw_lut_hsize,
int asw_lut_vsize, int cache_entry_type, int cache_way_n)
{
input->work_mode = work_mode;
input->lut_mode = lut_mode;
input->dst.dst_fmt = dst_fmt;
input->dst.dst_hsize = dst_hsize;
input->dst.dst_vsize = dst_vsize;
input->dst.dst_ba = dst_ba;
input->dst.dst_stride = dst_stride;
input->dst.dst_bg_color = dst_bg_color;
input->dst.dst_flip = dst_flip;
input->src.src_fmt = src_fmt;
input->src.src_hsize = src_hsize;
input->src.src_vsize = src_vsize;
input->src.src_ry_ba = src_ry_ba;
input->src.src_gu_ba = src_gu_ba;
input->src.src_bv_ba = src_bv_ba;
input->src.src_ry_stride = src_ry_stride;
input->src.src_gu_stride = src_gu_stride;
input->src.src_bv_stride = src_bv_stride;
input->src.src_flip = src_flip;
input->lut.asw_lut_hsize = asw_lut_hsize;
input->lut.asw_lut_vsize = asw_lut_vsize;
input->cache_entry_type = cache_entry_type;
input->cache_way_n = cache_way_n;
dev->input = input;
}
void sdrv_asw_bilinear_ftob32(const float *faddr, int *b32, int len)
{
for (int i = 0; i < len; i++) {
int tmp = (int)(faddr[i] * 256);
tmp = (tmp > 524287) ? 524287 : (tmp < -524288) ? -524288 : tmp;
b32[i] = tmp;
}
}
void sdrv_asw_bilinear_ftob16(const float *faddr, short *b16, int len)
{
for (int i = 0; i < len; i++) {
int tmp16 = (int)(faddr[i] * 16);
tmp16 = (tmp16 > 32767) ? 32767 : (tmp16 < -32768) ? -32768 : tmp16;
b16[i] = (short)tmp16;
}
}
void sdrv_asw_probe(struct asw_dev *dev, const struct asw_config *asw_cfg)
{
dev->base = asw_cfg->base;
dev->irq = asw_cfg->irq;
dev->ops = &sdrv_asw_ops;
dev->app.id = 0;
irq_attach(dev->irq, (irq_handler)dev->ops->irq_handler, dev);
irq_enable(dev->irq);
#if CONFIG_OS_FREERTOS
dev->wdone_sema = xSemaphoreCreateBinary();
#endif
}
void sdrv_asw_cubic(struct asw_input *input)
{
struct asw_dev *dev = &aswdev;
dev->ops->soft_reset(dev);
dev->input = input;
dev->ops->cubic_cfg(dev);
asw_done(dev);
}
void sdrv_asw_cubic_with_hvkt(struct asw_input *input, struct hvkt_param *hvkt)
{
struct asw_dev *dev = &aswdev;
dev->ops->soft_reset(dev);
dev->input = input;
dev->ops->cubic_cfg_with_hvkt(dev, hvkt);
asw_done(dev);
}
void sdrv_asw_bilinear(struct asw_input *input)
{
struct asw_dev *dev = &aswdev;
dev->ops->soft_reset(dev);
dev->input = input;
dev->ops->bilinear_cfg(dev);
asw_done(dev);
}
void sdrv_asw_bilinear_noblock(struct asw_input *input)
{
struct asw_dev *dev = &aswdev;
dev->ops->soft_reset(dev);
dev->input = input;
dev->ops->bilinear_cfg(dev);
}
void sdrv_asw_bilinear_with_hvkt(struct asw_input *input,
struct hvkt_param *hvkt)
{
struct asw_dev *dev = &aswdev;
dev->ops->soft_reset(dev);
dev->input = input;
dev->ops->bilinear_cfg_with_hvkt(dev, hvkt);
asw_done(dev);
}
void sdrv_asw_bilinear_rotation(struct asw_rot *rot)
{
struct asw_dev *dev = &aswdev;
struct asw_input input = {0};
struct hvkt_param hvkt = {0};
int twice;
double rot1, rot2;
int offstep;
static void *ext_addr;
static bool inited = false;
rot->angle = (int)rot->angle % 360 + (rot->angle - (int)rot->angle);
rot1 = rot->angle;
input.work_mode = WORK_MODE_M_TO_M;
input.hdsk_mode = BUF_SIZE_16LINES;
input.lut_mode = LUT_MODE_BILINEAR;
input.ext_lut_fmt = EXT_LUT_FORMAT_32BIT;
input.dst.dst_fmt = rot->dst_fmt;
input.dst.dst_hsize = rot->hsize;
input.dst.dst_vsize = rot->vsize;
twice = is_need_twice(rot->angle);
if (twice) {
if (!rot->t_buf) {
ASW_LOG_ERR("t_buf is null when twice operation!");
return;
}
input.dst.dst_ba = rot->t_buf;
input.dst.dst_stride = rot->t_stride;
if ((rot->angle > 45) && (rot->angle <= 90)) rot1 = 45;
else if ((rot->angle > 90) && (rot->angle <=135)) rot1 = 135;
else if ((rot->angle > 225) && (rot->angle <=270)) rot1 = 225;
else rot1 = 315;
rot2 = rot->angle - rot1;
} else {
input.dst.dst_ba = rot->dst_ba;
input.dst.dst_stride = rot->dst_stride;
}
input.dst.dst_bg_color = rot->bg_color;
input.src.src_fmt = rot->src_fmt;
input.src.src_hsize = rot->hsize;
input.src.src_vsize = rot->vsize;
input.src.src_ry_ba = rot->src_ba[0];
input.src.src_gu_ba = rot->src_ba[1];
input.src.src_bv_ba = rot->src_ba[2];
input.src.src_ry_stride = rot->src_stride[0];
input.src.src_gu_stride = rot->src_stride[1];
input.src.src_bv_stride = rot->src_stride[2];
input.lut.asw_lut_hsize = 35;
input.lut.asw_lut_vsize = 35;
offstep = 35 * 35 * 4;
if (!inited) {
ext_addr = (void *)blut_ext;
inited = true;
}
input.ext.ext_mlut_rx_ba = (int)ext_addr;
input.ext.ext_mlut_ry_ba = (int)ext_addr + offstep;
input.ext.ext_mlut_gx_ba = (int)ext_addr + offstep * 2;
input.ext.ext_mlut_gy_ba = (int)ext_addr + offstep * 3;
input.ext.ext_mlut_bx_ba = (int)ext_addr + offstep * 4;
input.ext.ext_mlut_by_ba = (int)ext_addr + offstep * 5;
input.ext.ext_mlut_rx_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_ry_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_gx_stride = input.lut.asw_lut_hsize * 4,
input.ext.ext_mlut_gy_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_bx_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_by_stride = input.lut.asw_lut_hsize * 4;
input.cache_entry_type = C_ENTRY_TYPE_16X4;
input.cache_way_n = 10;
/*hvkt*/
hvkt.chn = 1;
hvkt.is_external_lut = true;
hvkt.fw_map = false;
hvkt.external_lut_format = input.ext_lut_fmt; /* 32bits*/
hvkt.hsize = input.dst.dst_hsize;
hvkt.vsize = input.dst.dst_vsize;
hvkt.hsize_in = input.src.src_hsize;
hvkt.vsize_in = input.src.src_vsize;
hvkt.lut_h_size = input.lut.asw_lut_hsize;
hvkt.lut_v_size = input.lut.asw_lut_vsize;
hvkt.extend = 1;
dev->ops->soft_reset(dev);
dev->input = &input;
dev->ops->bilinear_rotation(dev, rot1, &hvkt);
asw_done(dev);
if (twice) {
input.src.src_fmt = rot->dst_fmt;
input.src.src_ry_ba = input.dst.dst_ba;
input.src.src_ry_stride = input.dst.dst_stride;
input.dst.dst_ba = rot->dst_ba;
input.dst.dst_stride = rot->dst_stride;
dev->ops->bilinear_rotation(dev, rot2, &hvkt);
asw_done(dev);
}
}
void sdrv_asw_ra_triangle(struct asw_ratria *info)
{
struct asw_input input = {0};
float lutx[4], luty[4];
int s_w, s_h, size;
int *src = NULL;
char *src8 = NULL;
int offstep;
int exaddr = 0;
int bpp;
s_w = TRI_SRC_W;
s_h = TRI_SRC_H;
size = s_w * s_h;
src = tri_src;
src8 = (char *)src;
for (int i = 0; i < size; i++) {
if (info->fmt == FMT_MONOTONIC_8BIT)
src8[i] = info->color & 0xFF;
else
src[i] = info->color;
}
arch_clean_cache_range((addr_t)src, size * 4);
bpp = get_fmt_bpp(info->fmt);
input.work_mode = WORK_MODE_M_TO_M;
input.hdsk_mode = BUF_SIZE_16LINES;
input.lut_mode = LUT_MODE_BILINEAR;
input.ext_lut_fmt = EXT_LUT_FORMAT_32BIT;
input.dst.dst_fmt = info->fmt;
input.dst.dst_hsize = info->hsize;
input.dst.dst_vsize = info->vsize;
input.dst.dst_ba =
info->addr + info->pos_y * info->stride + info->pos_x * bpp;
input.dst.dst_stride = info->stride;
input.dst.dst_bg_color = 0x0;
if (info->fmt == FMT_MONOTONIC_8BIT) {
input.src.src_fmt = FMT_MONOTONIC_8BIT;
input.src.src_ry_stride = s_w;
} else {
input.src.src_fmt = FMT_ARGB8888;
input.src.src_ry_stride = s_w * 4;
}
input.src.src_hsize = s_w;
input.src.src_vsize = s_h;
input.src.src_ry_ba = (int)src;
input.src.src_gu_ba = 0;
input.src.src_bv_ba = 0;
input.src.src_gu_stride = 0;
input.src.src_bv_stride = 0;
input.lut.asw_lut_hsize = 2;
input.lut.asw_lut_vsize = 2;
offstep = input.lut.asw_lut_hsize * input.lut.asw_lut_vsize * 4;
exaddr = (int)blut_ext;
input.ext.ext_mlut_rx_ba = exaddr;
input.ext.ext_mlut_ry_ba = exaddr + offstep;
input.ext.ext_mlut_gx_ba = exaddr + offstep * 2;
input.ext.ext_mlut_gy_ba = exaddr + offstep * 3;
input.ext.ext_mlut_bx_ba = exaddr + offstep * 4;
input.ext.ext_mlut_by_ba = exaddr + offstep * 5;
input.ext.ext_mlut_rx_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_ry_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_gx_stride = input.lut.asw_lut_hsize * 4,
input.ext.ext_mlut_gy_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_bx_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_by_stride = input.lut.asw_lut_hsize * 4;
input.cache_entry_type = C_ENTRY_TYPE_16X4;
input.cache_way_n = 6;
switch (info->type) {
case TRIAG_LEFT_TOP:
lutx[0] = 0;
lutx[1] = s_w - 1;
lutx[2] = s_w - 1;
lutx[3] = 2 * s_w - 1;
luty[0] = 0;
luty[1] = 0;
luty[2] = 1;
luty[3] = 1;
break;
case TRIAG_LEFT_BOTTOM:
lutx[0] = s_w - 1;
lutx[1] = 2 * s_w - 1;
lutx[2] = 0;
lutx[3] = s_w - 1;
luty[0] = 0;
luty[1] = 0;
luty[2] = 1;
luty[3] = 1;
break;
case TRIAG_TYPE_RIGHT_TOP:
lutx[0] = 0;
lutx[1] = s_w - 1;
lutx[2] = 1 - s_w;
lutx[3] = 0;
luty[0] = 0;
luty[1] = 0;
luty[2] = 1;
luty[3] = 1;
break;
case TRIAG_TYPE_RIGHT_BOTTOM:
lutx[0] = 1 - s_w;
lutx[1] = 0;
lutx[2] = 0;
lutx[3] = s_w - 1;
luty[0] = 0;
luty[1] = 0;
luty[2] = 1;
luty[3] = 1;
break;
default:
ASW_LOG_ERR("Not Support This TYPE(%d)", info->type);
return;
}
sdrv_asw_bilinear_ftob32(lutx, (int *)input.ext.ext_mlut_rx_ba, 4);
sdrv_asw_bilinear_ftob32(luty, (int *)input.ext.ext_mlut_ry_ba, 4);
arch_clean_cache_range((addr_t)input.ext.ext_mlut_rx_ba, offstep * 6);
sdrv_asw_bilinear(&input);
}
void sdrv_asw_fill_rect(int fmt, int color, int hsize, int vsize, int pos_x,
int pos_y, int addr, int stride)
{
struct asw_input input = {0};
float lutx[4], luty[4];
int s_w, s_h, size;
int *src = NULL;
char *src8 = NULL;
int offstep;
int exaddr = 0;
int bpp;
s_w = FILL_SRC_W;
s_h = FILL_SRC_H;
size = s_w * s_h;
src = fill_src;
src8 = (char *)src;
for (int i = 0; i < size; i++) {
if (fmt == FMT_MONOTONIC_8BIT)
src8[i] = color & 0xFF;
else
src[i] = color;
}
arch_clean_cache_range((addr_t)src, size * 4);
bpp = get_fmt_bpp(fmt);
input.work_mode = WORK_MODE_M_TO_M;
input.hdsk_mode = BUF_SIZE_16LINES;
input.lut_mode = LUT_MODE_BILINEAR;
input.ext_lut_fmt = EXT_LUT_FORMAT_32BIT;
input.dst.dst_fmt = fmt;
input.dst.dst_hsize = hsize;
input.dst.dst_vsize = vsize;
input.dst.dst_ba = addr + pos_y * stride + pos_x * bpp;
input.dst.dst_stride = stride;
input.dst.dst_bg_color = color_to_bgcolor(color);
if (fmt == FMT_MONOTONIC_8BIT) {
input.src.src_fmt = FMT_MONOTONIC_8BIT;
input.src.src_ry_stride = s_w;
} else {
input.src.src_fmt = FMT_ARGB8888;
input.src.src_ry_stride = s_w * 4;
}
input.src.src_hsize = s_w;
input.src.src_vsize = s_h;
input.src.src_ry_ba = (int)src;
input.src.src_gu_ba = 0;
input.src.src_bv_ba = 0;
input.src.src_gu_stride = 0;
input.src.src_bv_stride = 0;
input.lut.asw_lut_hsize = 2;
input.lut.asw_lut_vsize = 2;
offstep = input.lut.asw_lut_hsize * input.lut.asw_lut_vsize * 4;
exaddr = (int)blut_ext;
input.ext.ext_mlut_rx_ba = exaddr;
input.ext.ext_mlut_ry_ba = exaddr + offstep;
input.ext.ext_mlut_gx_ba = exaddr + offstep * 2;
input.ext.ext_mlut_gy_ba = exaddr + offstep * 3;
input.ext.ext_mlut_bx_ba = exaddr + offstep * 4;
input.ext.ext_mlut_by_ba = exaddr + offstep * 5;
input.ext.ext_mlut_rx_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_ry_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_gx_stride = input.lut.asw_lut_hsize * 4,
input.ext.ext_mlut_gy_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_bx_stride = input.lut.asw_lut_hsize * 4;
input.ext.ext_mlut_by_stride = input.lut.asw_lut_hsize * 4;
input.cache_entry_type = C_ENTRY_TYPE_16X4;
input.cache_way_n = 6;
/* top-left*/
lutx[0] = 0;
luty[0] = 0;
/* top-right*/
lutx[1] = s_w - 1;
luty[1] = 0;
/* bottom-left*/
lutx[2] = 0;
luty[2] = s_h - 1;
/* bottom-right*/
lutx[3] = s_w - 1;
luty[3] = s_h - 1;
sdrv_asw_bilinear_ftob32(lutx, (int *)input.ext.ext_mlut_rx_ba, 4);
sdrv_asw_bilinear_ftob32(luty, (int *)input.ext.ext_mlut_ry_ba, 4);
arch_clean_cache_range((addr_t)input.ext.ext_mlut_rx_ba, offstep * 6);
sdrv_asw_bilinear(&input);
}

View File

@@ -0,0 +1,859 @@
/**
* @file sdrv_asw_drv.c
* @brief sdrv asw driver source.
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <asw/asw.h>
#include <asw/asw_log.h>
#include <asw/gama_regs.h>
#include <board.h>
#include <debug.h>
#include <dispss/disp.h>
#include <param.h>
#include <reg.h>
#include <stdlib.h>
#include <string.h>
#include <udelay/udelay.h>
#define LUT_HSIZE_MAX 35
#define LUT_VSIZE_MAX 35
int tblut_ext[LUT_HSIZE_MAX * LUT_VSIZE_MAX * 4 * 6] = {0};
static int sharp_addr[2] = {0x30400, 0x305FF};
static int soft_addr[2] = {0x30600, 0x307FF};
static int sharp_coef[33][5] = {
{0, 0, 32, 0, 0}, {0, 0, 32, 0, 0}, {0, -1, 32, 1, 0},
{0, -1, 32, 1, 0}, {0, -1, 32, 1, 0}, {0, -1, 31, 2, 0},
{0, -2, 32, 2, 0}, {0, -2, 31, 3, 0}, {0, -2, 31, 3, 0},
{0, -2, 30, 4, 0}, {0, -2, 30, 4, 0}, {0, -2, 29, 5, 0},
{0, -2, 29, 5, 0}, {0, -3, 29, 6, 0}, {0, -3, 29, 6, 0},
{0, -3, 29, 7, -1}, {0, -3, 28, 8, -1}, {0, -3, 28, 8, -1},
{0, -3, 27, 9, -1}, {0, -3, 27, 9, -1}, {0, -3, 26, 10, -1},
{-1, -3, 26, 11, -1}, {-1, -3, 26, 11, -1}, {-1, -3, 25, 12, -1},
{-1, -3, 24, 13, -1}, {-1, -3, 24, 13, -1}, {-1, -3, 23, 14, -1},
{-1, -2, 22, 15, -2}, {-1, -2, 21, 16, -2}, {-1, -2, 21, 16, -2},
{-1, -2, 20, 17, -2}, {-1, -2, 19, 18, -2}, {-1, -2, 19, 18, -2}};
static int soft_coef[33][5] = {
{2, 2, 24, 2, 2}, {2, 2, 23, 3, 2}, {2, 2, 23, 3, 2}, {2, 2, 23, 3, 2},
{2, 2, 23, 3, 2}, {2, 2, 22, 4, 2}, {2, 2, 22, 4, 2}, {2, 1, 23, 4, 2},
{2, 1, 23, 4, 2}, {2, 1, 22, 5, 2}, {2, 1, 22, 5, 2}, {2, 1, 22, 5, 2},
{2, 1, 21, 6, 2}, {2, 1, 21, 6, 2}, {2, 1, 21, 6, 2}, {2, 1, 20, 7, 2},
{2, 1, 20, 7, 2}, {2, 1, 20, 7, 2}, {2, 1, 19, 8, 2}, {2, 1, 19, 8, 2},
{2, 1, 18, 9, 2}, {2, 1, 18, 9, 2}, {2, 1, 18, 9, 2}, {2, 1, 17, 10, 2},
{2, 1, 17, 10, 2}, {2, 1, 16, 11, 2}, {2, 1, 16, 11, 2}, {2, 1, 15, 12, 2},
{2, 1, 16, 12, 1}, {2, 1, 16, 12, 1}, {2, 1, 15, 13, 1}, {2, 1, 15, 13, 1},
{2, 1, 14, 14, 1}};
static inline unsigned int reg_value(unsigned int val, unsigned int src,
unsigned int shift, unsigned int mask)
{
return (src & ~mask) | ((val << shift) & mask);
}
static inline unsigned int gama_read(unsigned long base, unsigned int reg)
{
return readl(base + reg);
}
static inline void lb_write(unsigned long base, unsigned int reg,
unsigned int value)
{
writel(value, base + reg);
}
static inline void gama_write(unsigned long base, unsigned int reg,
unsigned int value)
{
writel(value, base + reg);
}
static int get_color_chn(int fmt)
{
switch (fmt) {
case FMT_MONOTONIC_8BIT:
case FMT_RGB565:
case FMT_RGBA5551:
case FMT_ARGB1555:
case FMT_RGB_YUV888:
case FMT_RGBA8888:
case FMT_ARGB8888:
return 1;
case FMT_YUV422_SEMI_U0V0:
case FMT_YUV422_SEMI_V0U0:
return 2;
case FMT_RGB_YUV888_PLANAR:
case FMT_YUV422_PLANAR:
case FMT_YUV420_PLANAR:
return 3;
default:
ASW_LOG_ERR("fmt [%d] is error", fmt);
return -1;
}
}
int get_dst_color_chn(int fmt)
{
/* FMT_MONOTONIC_8BIT */
/* FMT_RGB565 */
/* FMT_RGBA5551 */
/* FMT_ARGB1555 */
/* FMT_RGB_YUV888 */
/* FMT_YUV422_UYVY */
/* FMT_YUV422_VYUY */
/* FMT_RGBA8888 */
/* FMT_ARGB8888 */
/* FMT_YUV422_YUYV */
/* FMT_YUV422_YVYU */
switch (fmt) {
case FMT_MONOTONIC_8BIT:
return 1;
case FMT_RGB565:
case FMT_RGB_YUV888:
case FMT_YUV422_UYVY:
case FMT_YUV422_VYUY:
case FMT_YUV422_YUYV:
case FMT_YUV422_YVYU:
return 3;
case FMT_RGBA5551:
case FMT_ARGB1555:
case FMT_RGBA8888:
case FMT_ARGB8888:
return 4;
default:
ASW_LOG_ERR("fmt [%d] is error", fmt);
return -1;
}
}
static int get_src_color_chn(int fmt)
{
/*SRC FMT support: */
/* FMT_MONOTONIC_8BIT */
/* FMT_RGB_YUV888_PLANAR*/
/* FMT_YUV422_PLANAR */
/* FMT_YUV420_PLANAR */
/* FMT_RGB565 */
/* FMT_RGBA5551 */
/* FMT_ARGB1555 */
/* FMT_RGB_YUV888 */
/* FMT_YUV422_SEMI_U0V0 */
/* FMT_YUV422_SEMI_V0U0 */
/* FMT_RGBA8888 */
/* FMT_ARGB8888 */
switch (fmt) {
case FMT_MONOTONIC_8BIT:
return 1;
case FMT_RGB565:
case FMT_YUV420_PLANAR:
case FMT_YUV422_PLANAR:
case FMT_RGB_YUV888:
case FMT_RGB_YUV888_PLANAR:
case FMT_YUV422_SEMI_U0V0:
case FMT_YUV422_SEMI_V0U0:
return 3;
case FMT_RGBA5551:
case FMT_ARGB1555:
case FMT_RGBA8888:
case FMT_ARGB8888:
return 4;
default:
ASW_LOG_ERR("fmt [%d] is error", fmt);
return -1;
}
}
static int get_cache_entry_vsize(int type)
{
switch (type) {
case C_ENTRY_TYPE_8X4:
case C_ENTRY_TYPE_16X4:
case C_ENTRY_TYPE_32X4:
return 4;
case C_ENTRY_TYPE_8X8:
case C_ENTRY_TYPE_16X8:
return 8;
default:
ASW_LOG_ERR("type [%d] is error", type);
return -1;
}
}
int get_cache_entry_hsize(int type)
{
switch (type) {
case C_ENTRY_TYPE_8X4:
case C_ENTRY_TYPE_8X8:
return 8;
case C_ENTRY_TYPE_16X4:
case C_ENTRY_TYPE_16X8:
return 16;
case C_ENTRY_TYPE_32X4:
return 32;
default:
ASW_LOG_ERR("type [%d] is error", type);
return -1;
}
}
static int get_fmt_h_half(int fmt)
{
switch (fmt) {
case FMT_YUV422_PLANAR:
case FMT_YUV420_PLANAR:
case FMT_YUV422_SEMI_U0V0:
case FMT_YUV422_SEMI_V0U0:
return 1;
default:
return 0;
}
}
static int get_cache_chn_size(struct asw_dev *dev, int index)
{
int hsize, ce_vsize;
switch (index) {
default:
case 0:
hsize = ((dev->input->src.src_hsize + 111) / 128) * 128 + 16;
break;
case 1:
case 2:
if (get_fmt_h_half(dev->input->src.src_fmt))
hsize = ((dev->input->src.src_hsize / 2 + 111) / 128) * 128 + 16;
else
hsize = ((dev->input->src.src_hsize + 111) / 128) * 128 + 16;
break;
}
ce_vsize = get_cache_entry_vsize(dev->input->cache_entry_type);
return hsize * ce_vsize * dev->input->cache_way_n;
}
/*burst_len = tile_hsize * byte_per_pixel / 8*/
/*Using this func can get the byte_per_pixel*/
int get_rdma_bpp_by_fmt(int fmt)
{
switch (fmt) {
case FMT_MONOTONIC_8BIT:
case FMT_YUV422_PLANAR:
case FMT_YUV420_PLANAR:
case FMT_RGB_YUV888_PLANAR:
return 1;
case FMT_RGB565:
case FMT_RGBA5551:
case FMT_ARGB1555:
case FMT_YUV422_SEMI_U0V0:
case FMT_YUV422_SEMI_V0U0:
return 2;
case FMT_RGB_YUV888:
return 3;
case FMT_RGBA8888:
case FMT_ARGB8888:
return 4;
default:
return 1;
}
}
static void lb_component_ba_calc(struct asw_dev *dev)
{
int chn, dchn, lut_shape_size, frb_size, cache_chn_size;
struct asw_ba_info *bas = &dev->bas;
struct asw_input *input = dev->input;
if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) {
/*LUT*/
bas->asw_pos_lut_ba = GAMA_LB_JUMP;
chn = get_color_chn(input->src.src_fmt);
lut_shape_size = 35 * 35 * 2 * chn * 4;
bas->asw_m_v_ba = bas->asw_pos_lut_ba + lut_shape_size;
/*pfile*/
bas->asw_pos_calc_pfile_ba = bas->asw_pos_lut_ba + lut_shape_size * 2;
/*alpha[]*/
bas->asw_alpha_ba = bas->asw_pos_calc_pfile_ba + 16 * 4;
/*y/step_y*/
bas->asw_y_stepy_ba = bas->asw_alpha_ba + 35 * 4;
/*LUT_H[]*/
bas->asw_lut_h_ba = bas->asw_y_stepy_ba + 60 * 4;
/*M_H[]*/
bas->asw_m_h_ba = bas->asw_lut_h_ba + 35 * 4;
/*Filter Result Buffer*/
bas->asw_frb_ba = ALIGN(bas->asw_m_h_ba + 35 * 4, 16);
} else { /*LUT_MODE_BILINEAR*/
bas->asw_frb_ba = GAMA_LB_JUMP;
}
/*CACHE*/
dchn = get_src_color_chn(input->src.src_fmt);
frb_size = (ALIGN(dev->input->dst.dst_hsize, 16) / 4) * 2 * dchn * 4; /*argb*/
bas->asw_cache_ry_ba = ALIGN(bas->asw_frb_ba + frb_size, 128);
cache_chn_size = get_cache_chn_size(dev, 0);
if ((input->src.src_fmt == FMT_YUV422_SEMI_U0V0) ||
((input->src.src_fmt == FMT_YUV422_SEMI_V0U0))) {
bas->asw_cache_gu_ba =
bas->asw_cache_ry_ba + ALIGN(cache_chn_size, 128);
cache_chn_size = get_cache_chn_size(dev, 1);
bas->asw_cache_bv_ba =
bas->asw_cache_gu_ba + ALIGN(cache_chn_size, 128) + 64;
} else {
bas->asw_cache_gu_ba =
bas->asw_cache_ry_ba + ALIGN(cache_chn_size, 128) + 32;
cache_chn_size = get_cache_chn_size(dev, 1);
bas->asw_cache_bv_ba =
bas->asw_cache_gu_ba + ALIGN(cache_chn_size, 128) + 32;
}
cache_chn_size = get_cache_chn_size(dev, 2);
bas->asw_cache_a_ba =
bas->asw_cache_bv_ba + ALIGN(cache_chn_size, 128) + 32;
ASW_LOG_DEBUG("asw_pos_calc_pfile_ba = 0x%08x", bas->asw_pos_calc_pfile_ba);
ASW_LOG_DEBUG("asw_pos_lut_ba = 0x%08x", bas->asw_pos_lut_ba);
ASW_LOG_DEBUG("asw_m_v_ba = 0x%08x", bas->asw_m_v_ba);
ASW_LOG_DEBUG("asw_alpha_ba = 0x%08x", bas->asw_alpha_ba);
ASW_LOG_DEBUG("asw_y_stepy_ba = 0x%08x", bas->asw_y_stepy_ba);
ASW_LOG_DEBUG("asw_lut_h_ba = 0x%08x", bas->asw_lut_h_ba);
ASW_LOG_DEBUG("asw_m_h_ba = 0x%08x", bas->asw_m_h_ba);
ASW_LOG_DEBUG("asw_frb_ba = 0x%08x", bas->asw_frb_ba);
ASW_LOG_DEBUG("asw_cache_ry_ba = 0x%08x", bas->asw_cache_ry_ba);
ASW_LOG_DEBUG("asw_cache_gu_ba = 0x%08x", bas->asw_cache_gu_ba);
ASW_LOG_DEBUG("asw_cache_bv_ba = 0x%08x", bas->asw_cache_bv_ba);
ASW_LOG_DEBUG("asw_cache_a_ba = 0x%08x", bas->asw_cache_a_ba);
}
static void load_lut(struct asw_dev *dev)
{
unsigned long base = dev->base;
int addr;
addr = dev->bas.asw_pos_lut_ba;
for (int i = 0; addr < dev->bas.asw_pos_calc_pfile_ba; i++) {
lb_write(base, addr,
*(unsigned int *)(dev->input->cubic.lut_src_ba + i * 4));
addr += 4;
}
}
static void load_cfg_parameter(struct asw_dev *dev)
{
unsigned long base = dev->base;
int addr;
addr = dev->bas.asw_pos_calc_pfile_ba;
ASW_LOG_INFO("addr = 0x%x", addr);
/*params[0] = (float)1/2*/
lb_write(base, addr, 0x3f000000);
addr += 4;
/*params[1] = (float)1/3*/
lb_write(base, addr, 0x3eaaaa9f);
addr += 4;
/*params[2] = (float)1/6*/
lb_write(base, addr, 0x3e2aaac1);
addr += 4;
/*params[3] = (float)2*/
lb_write(base, addr, 0x40000000);
addr += 4;
/*params[4] = (float)6*/
lb_write(base, addr, 0x40c00000);
addr += 4;
/*params[5] = (float)(-(2^24-1)*256)*/
lb_write(base, addr, 0xcf7fffff);
addr += 4;
/*params[6] = (float)(+(2^24-1)*256)*/
lb_write(base, addr, 0x4f7fffff);
addr += 4;
/*params[7] = (float)256*/
lb_write(base, addr, 0x43800000);
addr += 4;
/*params[8]*/
lb_write(base, addr, dev->bas.asw_alpha_ba - GAMA_LB_JUMP);
addr += 4;
/*params[9]*/
addr += 4;
/*params[10]*/
lb_write(base, addr, dev->bas.asw_y_stepy_ba - GAMA_LB_JUMP);
addr += 4;
/*params[11][12]*/
addr += 8;
/*params[13]*/
lb_write(base, addr, dev->bas.asw_lut_h_ba - GAMA_LB_JUMP);
addr += 4;
/*params[14]*/
lb_write(base, addr, dev->bas.asw_m_h_ba - GAMA_LB_JUMP);
addr += 4;
}
static void load_alpha(struct asw_dev *dev)
{
unsigned long base = dev->base;
int addr;
addr = dev->bas.asw_alpha_ba;
for (int i = 0; addr < dev->bas.asw_y_stepy_ba; i++) {
lb_write(base, addr,
*(unsigned int *)(dev->input->cubic.alpha_src_ba + i * 4));
addr += 4;
}
}
static void load_y_stepy(struct asw_dev *dev)
{
unsigned long base = dev->base;
int step, addr;
step = (dev->input->dst.dst_vsize + 31) / 32;
addr = dev->bas.asw_y_stepy_ba;
for (int i = 0; i < step; i++) {
float val = (float)i / (float)step;
int *pos = (int *)(&val);
int value = *pos;
lb_write(base, addr, value);
addr += 4;
}
}
static void gama_rwdma_init(struct asw_dev *dev)
{
unsigned long base = dev->base;
unsigned int val;
/*set dma circular buffer mode*/
gama_write(base, ASW_RD01C(0), dev->input->cbuf.low_limit_addr);
gama_write(base, ASW_RD020(0), dev->input->cbuf.high_limit_addr);
val = reg_value(dev->input->cbuf.range, 0, ASW_SHIFT01_RD024,
ASW_MASK01_RD024);
val = reg_value(dev->input->cbuf.enable, val, ASW_SHIFT00_RD024,
ASW_MASK00_RD024);
gama_write(base, ASW_RD024(0), val);
gama_write(base, 0x20000, 0x200000);
gama_write(base, 0x2000c, 0x200000);
}
static void gama_asw_set_hwmode(struct asw_dev *dev)
{
unsigned long base = dev->base;
unsigned int val;
gama_rwdma_init(dev);
/*mode configs*/
val = gama_read(base, ASW_RB010);
val = reg_value(1, val, ASW_SHIFT02_RB010, ASW_MASK02_RB010);
val =
reg_value(LB_LAYOUT_B, val, ASW_SHIFT01_RB010, ASW_MASK01_RB010);
val = reg_value(1, val, ASW_SHIFT00_RB010, ASW_MASK00_RB010);
gama_write(base, ASW_RB010, val);
}
static void gama_asw_cfg(struct asw_dev *dev)
{
unsigned long base = dev->base;
unsigned int c_chn;
unsigned int val;
int asw_lut_hstep, asw_lut_vstep;
c_chn = get_color_chn(dev->input->src.src_fmt);
/*LUT parameters*/
val = reg_value(dev->input->lut.asw_lut_hsize - 1, 0, ASW_SHIFT00_RA020,
ASW_MASK00_RA020);
val = reg_value(dev->input->lut.asw_lut_vsize - 1, val,
ASW_SHIFT16_RA020, ASW_MASK16_RA020);
gama_write(base, ASW_RA020, val);
if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) {
asw_lut_hstep = (dev->input->dst.dst_hsize + 31) / 32;
asw_lut_vstep = (dev->input->dst.dst_vsize + 31) / 32;
} else { /*LUT_MODE_BILINEAR*/
asw_lut_hstep =
(dev->input->dst.dst_hsize + dev->input->lut.asw_lut_hsize - 2) /
(dev->input->lut.asw_lut_hsize - 1);
asw_lut_vstep =
(dev->input->dst.dst_vsize + dev->input->lut.asw_lut_vsize - 2) /
(dev->input->lut.asw_lut_vsize - 1);
}
val = reg_value(asw_lut_hstep - 1, 0, ASW_SHIFT00_RA024,
ASW_MASK00_RA024);
val = reg_value(asw_lut_vstep - 1, val, ASW_SHIFT16_RA024,
ASW_MASK16_RA024);
gama_write(base, ASW_RA024, val);
val = 0x100000 / asw_lut_hstep; /*(int)((1/lut_step_h)*2^20)*/
gama_write(base, ASW_RA028, val);
val = 0x100000 / asw_lut_vstep; /*(int)((1/lut_step_v)*2^20)*/
gama_write(base, ASW_RA02C, val);
if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) {
gama_write(base, ASW_RA030,
dev->bas.asw_pos_calc_pfile_ba - GAMA_LB_JUMP);
int jump =
dev->input->lut.asw_lut_hsize * 2 * c_chn * 4; /*jump one line*/
gama_write(base, ASW_RA034,
dev->bas.asw_pos_lut_ba + jump - GAMA_LB_JUMP);
gama_write(base, ASW_RA038,
dev->bas.asw_m_v_ba + jump - GAMA_LB_JUMP);
} else { /*LUT_MODE_BILINEAR*/
gama_write(base, ASW_RA090, dev->input->ext.ext_mlut_rx_ba);
gama_write(base, ASW_RA0A8,
dev->input->ext.ext_mlut_rx_stride - 1);
gama_write(base, ASW_RA094, dev->input->ext.ext_mlut_ry_ba);
gama_write(base, ASW_RA0AC,
dev->input->ext.ext_mlut_ry_stride - 1);
if (c_chn > 1) {
gama_write(base, ASW_RA098,
dev->input->ext.ext_mlut_gx_ba);
gama_write(base, ASW_RA0B0,
dev->input->ext.ext_mlut_gx_stride - 1);
gama_write(base, ASW_RA09C,
dev->input->ext.ext_mlut_gy_ba);
gama_write(base, ASW_RA0B4,
dev->input->ext.ext_mlut_gy_stride - 1);
}
if (c_chn > 2) {
gama_write(base, ASW_RA0A0,
dev->input->ext.ext_mlut_bx_ba);
gama_write(base, ASW_RA0B8,
dev->input->ext.ext_mlut_bx_stride - 1);
gama_write(base, ASW_RA0A4,
dev->input->ext.ext_mlut_by_ba);
gama_write(base, ASW_RA0BC,
dev->input->ext.ext_mlut_by_stride - 1);
}
}
/*ASW Cache parameters*/
gama_write(base, ASW_RA040, dev->bas.asw_cache_ry_ba - GAMA_LB_JUMP);
gama_write(base, ASW_RA044, dev->bas.asw_cache_gu_ba - GAMA_LB_JUMP);
gama_write(base, ASW_RA048, dev->bas.asw_cache_bv_ba - GAMA_LB_JUMP);
gama_write(base, ASW_RA04C, dev->bas.asw_cache_a_ba - GAMA_LB_JUMP);
gama_write(base, ASW_RA050, dev->bas.asw_frb_ba - GAMA_LB_JUMP);
gama_write(base, ASW_RA058,
ALIGN(dev->input->dst.dst_hsize, 16) - 1);
/*src/des image formats*/
val = reg_value(dev->input->src.src_vsize - 1, 0, ASW_SHIFT16_RA010,
ASW_MASK16_RA010);
val = reg_value(dev->input->src.src_hsize - 1, val, ASW_SHIFT00_RA010,
ASW_MASK00_RA010);
gama_write(base, ASW_RA010, val);
val = reg_value(dev->input->dst.dst_vsize - 1, 0, ASW_SHIFT16_RA014,
ASW_MASK16_RA014);
val = reg_value(dev->input->dst.dst_hsize - 1, val, ASW_SHIFT00_RA014,
ASW_MASK00_RA014);
gama_write(base, ASW_RA014, val);
val = gama_read(base, ASW_RA018);
val = reg_value((dev->input->dst.dst_flip & FLIP_TYPE_HFLIP) ? 1 : 0, val,
ASW_SHIFT24_RA018, ASW_MASK24_RA018);
val = reg_value((dev->input->dst.dst_flip & FLIP_TYPE_VFLIP) ? 1 : 0, val,
ASW_SHIFT25_RA018, ASW_MASK25_RA018);
val = reg_value(dev->input->dst.dst_fmt, val, ASW_SHIFT16_RA018, ASW_MASK16_RA018);
val = reg_value((dev->input->src.src_flip & FLIP_TYPE_HFLIP) ? 1 : 0, val,
ASW_SHIFT08_RA018, ASW_MASK08_RA018);
val = reg_value((dev->input->src.src_flip & FLIP_TYPE_VFLIP) ? 1 : 0, val,
ASW_SHIFT09_RA018, ASW_MASK09_RA018);
val = reg_value(dev->input->src.src_fmt, val, ASW_SHIFT00_RA018, ASW_MASK00_RA018);
gama_write(base, ASW_RA018, val);
gama_write(base, ASW_RA060, dev->input->src.src_ry_ba);
gama_write(base, ASW_RA06C, dev->input->src.src_ry_stride - 1);
if (c_chn > 1) {
gama_write(base, ASW_RA064, dev->input->src.src_gu_ba);
gama_write(base, ASW_RA070, dev->input->src.src_gu_stride - 1);
}
if (c_chn > 2) {
gama_write(base, ASW_RA068, dev->input->src.src_bv_ba);
gama_write(base, ASW_RA074, dev->input->src.src_bv_stride - 1);
}
gama_write(base, ASW_RA080, dev->input->dst.dst_ba);
gama_write(base, ASW_RA084, dev->input->dst.dst_stride - 1);
/*ohter parameters*/
val = gama_read(base, ASW_RA00C);
if (dev->input->adb.dirty) {
val = reg_value(dev->input->adb.offset, val, ASW_SHIFT04_RA00C,
ASW_MASK04_RA00C);
val = reg_value(dev->input->adb.slope, val, ASW_SHIFT00_RA00C,
ASW_MASK00_RA00C);
} else {
val = reg_value(0x18, val, ASW_SHIFT04_RA00C, ASW_MASK04_RA00C);
val = reg_value(0x7, val, ASW_SHIFT00_RA00C, ASW_MASK00_RA00C);
}
gama_write(base, ASW_RA00C, val);
gama_write(base, ASW_RA088, dev->input->dst.dst_bg_color);
val = gama_read(base, ASW_RA008);
val = reg_value(dev->input->lut_mode, val, ASW_SHIFT00_RA008,
ASW_MASK00_RA008);
if (dev->input->lut_mode == LUT_MODE_BILINEAR) {
val = reg_value(dev->input->ext_lut_fmt, val, ASW_SHIFT11_RA008,
ASW_MASK11_RA008);
}
if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) {
val = reg_value(CUBIC_MODE_INT_ASM, val, ASW_SHIFT10_RA008,
ASW_MASK10_RA008);
}
val =
reg_value(dev->input->work_mode, val, ASW_SHIFT08_RA008, ASW_MASK08_RA008);
val = reg_value(dev->input->cache_entry_type, val, ASW_SHIFT01_RA008,
ASW_MASK01_RA008);
val = reg_value(dev->input->cache_way_n, val, ASW_SHIFT04_RA008,
ASW_MASK04_RA008);
gama_write(base, ASW_RA008, val);
gama_write(base, ASW_RC028, 0xFFE);
dev->asw_done = 0;
switch (dev->input->work_mode) {
case WORK_MODE_M_TO_M:
default:
gama_write(base, ASW_RA01C, 0x3); /*using prepare shadow load.*/
ASW_LOG_DEBUG("m2m cfg fctrl");
gama_write(base, ASW_RA000, 0x1); /*ASW frame start(when m_to_m mode)*/
break;
case WORK_MODE_CSI_HS:
val = gama_read(base, ASW_RA008);
val = reg_value(dev->input->csi_start_ln, val, ASW_SHIFT20_RA008,
ASW_MASK20_RA008);
val = reg_value(dev->input->hdsk_mode, val, ASW_SHIFT12_RA008,
ASW_MASK12_RA008);
gama_write(base, ASW_RA008, val);
gama_write(base, ASW_RA01C, 0x3);
break;
case WORK_MODE_DC_HS:
val = gama_read(base, ASW_RA008);
val = reg_value(dev->input->hdsk_mode, val, ASW_SHIFT12_RA008,
ASW_MASK12_RA008);
gama_write(base, ASW_RA008, val);
gama_write(base, ASW_RA01C, 0x3);
break;
case WORK_MODE_CSI_DC_HS:
val = gama_read(base, ASW_RA008);
val = reg_value(dev->input->csi_start_ln, val, ASW_SHIFT20_RA008,
ASW_MASK20_RA008);
val = reg_value(dev->input->hdsk_mode, val, ASW_SHIFT12_RA008,
ASW_MASK12_RA008);
gama_write(base, ASW_RA008, val);
gama_write(base, ASW_RA01C, 0x3);
break;
}
}
static void gama_fliter_set(struct asw_dev *dev)
{
unsigned long base = dev->base;
unsigned int head, tail;
for (int i = 0; i < 33; i++) {
head = (sharp_coef[i][0] & 0xff) | ((sharp_coef[i][1] & 0xff) << 8) |
((sharp_coef[i][2] & 0xff) << 16);
tail = ((sharp_coef[i][3] & 0xff)) | ((sharp_coef[i][4] & 0xff) << 8);
gama_write(base, sharp_addr[0] + (i * 2) * 4, head);
gama_write(base, sharp_addr[0] + (i * 2 + 1) * 4, tail);
}
for (int i = 0; i < 33; i++) {
head = (soft_coef[i][0] & 0xff) | ((soft_coef[i][1] & 0xff) << 8) |
((soft_coef[i][2] & 0xff) << 16);
tail = ((soft_coef[i][3] & 0xff)) | ((soft_coef[i][4] & 0xff) << 8);
gama_write(base, soft_addr[0] + (i * 2) * 4, head);
gama_write(base, soft_addr[0] + (i * 2 + 1) * 4, tail);
}
}
static void asw_soft_reset(struct asw_dev *dev)
{
unsigned long base = dev->base;
gama_write(base, ASW_RA004, 1);
udelay(10);
gama_write(base, ASW_RA004, 0);
}
/*cubic spline*/
static void asw_cubic(struct asw_dev *dev)
{
lb_component_ba_calc(dev);
gama_asw_set_hwmode(dev);
load_lut(dev);
load_cfg_parameter(dev);
load_alpha(dev);
load_y_stepy(dev);
gama_fliter_set(dev);
gama_asw_cfg(dev);
}
static void asw_cubic_with_hvkt(struct asw_dev *dev, struct hvkt_param *hvkt)
{
lb_component_ba_calc(dev);
gama_asw_set_hwmode(dev);
hvkt->lut_addr = dev->base + dev->bas.asw_pos_lut_ba;
hvkt->m_v_addr = dev->base + dev->bas.asw_m_v_ba;
hvkt->alpha_addr = dev->base + dev->bas.asw_alpha_ba;
hvkt->lut_h_step =
(dev->input->dst.dst_hsize + (dev->input->lut.asw_lut_hsize - 2)) /
(dev->input->lut.asw_lut_hsize - 1);
hvkt->lut_v_step =
(dev->input->dst.dst_vsize + (dev->input->lut.asw_lut_vsize - 2)) /
(dev->input->lut.asw_lut_vsize - 1);
lut_hvk_ops.lut_table_gen(hvkt);
lut_hvk_ops.lut_m_v_gen(hvkt);
load_cfg_parameter(dev);
load_y_stepy(dev);
gama_fliter_set(dev);
gama_asw_cfg(dev);
}
/*bilinear*/
static void asw_bilinear(struct asw_dev *dev)
{
lb_component_ba_calc(dev);
gama_asw_set_hwmode(dev);
gama_fliter_set(dev);
gama_asw_cfg(dev);
}
static void asw_bilinear_with_hvkt(struct asw_dev *dev, struct hvkt_param *hvkt)
{
lb_component_ba_calc(dev);
gama_asw_set_hwmode(dev);
hvkt->lut_addr = (int)tblut_ext;
hvkt->lut_real_addr[0] = dev->input->ext.ext_mlut_rx_ba;
hvkt->lut_real_addr[1] = dev->input->ext.ext_mlut_ry_ba;
hvkt->lut_real_addr[2] = dev->input->ext.ext_mlut_gx_ba;
hvkt->lut_real_addr[3] = dev->input->ext.ext_mlut_gy_ba;
hvkt->lut_real_addr[4] = dev->input->ext.ext_mlut_bx_ba;
hvkt->lut_real_addr[5] = dev->input->ext.ext_mlut_by_ba;
hvkt->lut_h_step =
(dev->input->dst.dst_hsize + (dev->input->lut.asw_lut_hsize - 2)) /
(dev->input->lut.asw_lut_hsize - 1);
hvkt->lut_v_step =
(dev->input->dst.dst_vsize + (dev->input->lut.asw_lut_vsize - 2)) /
(dev->input->lut.asw_lut_vsize - 1);
lut_hvk_ops.lut_table_gen(hvkt);
gama_fliter_set(dev);
gama_asw_cfg(dev);
}
static int asw_irq_handler(unsigned int irq, void *data)
{
struct asw_dev *dev = (struct asw_dev *)data;
unsigned int val;
val = gama_read(dev->base, ASW_RC024);
gama_write(dev->base, ASW_RC030, val);
if (val & WRITE_OUT_FRM_DONE_MASK) {
dev->asw_done = 1;
#if CONFIG_OS_FREERTOS
xSemaphoreGiveFromISR(dev->wdone_sema, NULL);
#endif
}
return 0;
}
static void asw_cubic_rotation(struct asw_dev *dev, double rotate_angle,
struct hvkt_param *hvkt)
{
lb_component_ba_calc(dev);
gama_asw_set_hwmode(dev);
hvkt->lut_addr = dev->base + dev->bas.asw_pos_lut_ba;
hvkt->m_v_addr = dev->base + dev->bas.asw_m_v_ba;
hvkt->alpha_addr = dev->base + dev->bas.asw_alpha_ba;
lut_hvk_ops.lut_rotate_table_gen(rotate_angle, hvkt);
lut_hvk_ops.lut_m_v_gen(hvkt);
dev->input->dst.dst_flip = hvkt->flip_type;
load_cfg_parameter(dev);
load_y_stepy(dev);
gama_fliter_set(dev);
gama_asw_cfg(dev);
}
static void asw_bilinear_rotation(struct asw_dev *dev, double rotate_angle,
struct hvkt_param *hvkt)
{
lb_component_ba_calc(dev);
gama_asw_set_hwmode(dev);
hvkt->lut_addr = (int)tblut_ext;
hvkt->lut_real_addr[0] = dev->input->ext.ext_mlut_rx_ba;
hvkt->lut_real_addr[1] = dev->input->ext.ext_mlut_ry_ba;
hvkt->lut_real_addr[2] = dev->input->ext.ext_mlut_gx_ba;
hvkt->lut_real_addr[3] = dev->input->ext.ext_mlut_gy_ba;
hvkt->lut_real_addr[4] = dev->input->ext.ext_mlut_bx_ba;
hvkt->lut_real_addr[5] = dev->input->ext.ext_mlut_by_ba;
hvkt->lut_h_step =
(dev->input->dst.dst_hsize + (dev->input->lut.asw_lut_hsize - 2)) /
(dev->input->lut.asw_lut_hsize - 1);
hvkt->lut_v_step =
(dev->input->dst.dst_vsize + (dev->input->lut.asw_lut_vsize - 2)) /
(dev->input->lut.asw_lut_vsize - 1);
lut_hvk_ops.lut_rotate_table_gen(rotate_angle, hvkt);
dev->input->dst.dst_flip = hvkt->flip_type;
gama_fliter_set(dev);
gama_asw_cfg(dev);
}
struct asw_operations sdrv_asw_ops = {
.soft_reset = asw_soft_reset,
.cubic_cfg = asw_cubic,
.cubic_cfg_with_hvkt = asw_cubic_with_hvkt,
.cubic_rotation = asw_cubic_rotation,
.bilinear_cfg = asw_bilinear,
.bilinear_cfg_with_hvkt = asw_bilinear_with_hvkt,
.bilinear_rotation = asw_bilinear_rotation,
.irq_handler = asw_irq_handler,
};

View File

@@ -0,0 +1,426 @@
/**
* @file sdrv_asw_lut_hvk.c
* @brief sdrv asw driver source.
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <armv7-r/cache.h>
#include <asw/asw_log.h>
#include <asw/asw_lut_hvk.h>
#include <debug.h>
#include <math.h>
#include <reg.h>
#include <stdlib.h>
#include <string.h>
#define LUT_SIZE_MAX 1024
float TEMPAA[LUT_SIZE_MAX] = {0};
float TEMPAB[LUT_SIZE_MAX] = {0};
static int m_parameter_calc_alpha(int lut_size, float *alpha)
{
for (int i = 0; i < lut_size; i++) {
if ((i < 2) || (i >= (lut_size - 2)))
alpha[i] = 1.0;
else if (i == 2)
alpha[i] = 0.25;
else
alpha[i] = 1.0 / (4.0 - alpha[i - 1]);
}
return 0;
}
static int m_parameter_calc_1d(float *lut_ld, float *m_param_ld, float *alpha,
int lut_size, bool is_rt1)
{
float *delta = TEMPAA;
float *beta = TEMPAB;
float c_one_third = 1.0 / 3.0;
float c_one_sixth = 1.0 / 6.0;
for (int i = 0; i < lut_size; i++) {
if ((i == 0) || (i == (lut_size - 1))) {
delta[i] = 0.0;
} else {
if (!is_rt1) {
delta[i] =
6.0 * (lut_ld[i + 1] + lut_ld[i - 1] - 2.0 * lut_ld[i]);
} else {
delta[i] = lut_ld[i + 1] + lut_ld[i - 1];
delta[i] = fma(-2.0, lut_ld[i], delta[i]);
delta[i] = 6.0 * delta[i];
}
}
}
for (int i = 0; i < lut_size; i++) {
if (i == 0) {
beta[i] = delta[1] * c_one_third;
} else if (i == 1) {
beta[i] = delta[1] * c_one_sixth;
} else if (i == (lut_size - 2)) {
beta[i] = delta[lut_size - 2] * c_one_sixth;
} else if (i == (lut_size - 1)) {
beta[i] = delta[lut_size - 2] * c_one_third;
} else {
if (!is_rt1) {
beta[i] = (delta[i] - beta[i - 1]) * alpha[i];
} else {
beta[i] = delta[i] * alpha[i];
beta[i] = fma(-beta[i - 1], alpha[i], beta[i]);
}
}
}
for (int i = lut_size - 2; i >= 0; i--) {
if (i == 0) {
m_param_ld[i] = beta[i] - m_param_ld[i + 2];
} else if (i == 1) {
m_param_ld[i] = beta[i];
} else if (i == (lut_size - 2)) {
m_param_ld[i] = beta[i];
} else {
if (!is_rt1) {
m_param_ld[i] = beta[i] - m_param_ld[i + 1] * alpha[i];
} else {
m_param_ld[i] = fma(-m_param_ld[i + 1], alpha[i], beta[i]);
}
}
}
m_param_ld[lut_size - 1] = beta[lut_size - 1] - m_param_ld[lut_size - 3];
return 0;
}
static float hvk_pos_calc(float x, float y, struct hvkt_param *hvkt,
bool calc_x, int c_sel)
{
float pa, pb, pc, pd, pe, pf;
float x_mag, y_mag;
struct hvkt_fabc *fabc = hvkt->fabc;
pa = fabc->fc0[c_sel] * x - fabc->fa0[c_sel];
pb = fabc->fc1[c_sel] * x - fabc->fa1[c_sel];
pc = fabc->fa2[c_sel] - fabc->fc2[c_sel] * x;
pd = fabc->fc0[c_sel] * y - fabc->fb0[c_sel];
pe = fabc->fc1[c_sel] * y - fabc->fb1[c_sel];
pf = fabc->fb2[c_sel] - fabc->fc2[c_sel] * y;
if (calc_x) {
if (hvkt->fw_map)
x_mag = (fabc->fa0[c_sel] * x + fabc->fa1[c_sel] * y +
fabc->fa2[c_sel]) /
(fabc->fc0[c_sel] * x + fabc->fc1[c_sel] * y +
fabc->fc2[c_sel]);
else
x_mag = (pc * pe - pb * pf) / (pa * pe - pb * pd);
return x_mag * (float)(hvkt->hsize_in - 1) / (float)(hvkt->hsize - 1);
} else {
if (hvkt->fw_map)
y_mag = (fabc->fb0[c_sel] * x + fabc->fb1[c_sel] * y +
fabc->fb2[c_sel]) /
(fabc->fc0[c_sel] * x + fabc->fc1[c_sel] * y +
fabc->fc2[c_sel]);
else
y_mag = (pa * pf - pc * pd) / (pa * pe - pb * pd);
return y_mag * (float)(hvkt->vsize_in - 1) / (float)(hvkt->vsize - 1);
}
}
static int hvk_table_gen(struct hvkt_param *hvkt)
{
float delta_x0, delta_y0;
float delta_x1, delta_y1;
float sum_x, sum_y;
float poly0, poly1;
float a0, a1, a2;
float b0, b1, b2;
float c0, c1, c2;
int lut_hsize, lut_vsize;
float n, m;
int extend;
int chn;
float *lut;
int *lut_32[6];
short *lut_16[6];
struct hvkt_fabc fabc = {0};
hvkt->fabc = &fabc;
lut_hsize = hvkt->lut_h_size;
lut_vsize = hvkt->lut_v_size;
lut = (float *)hvkt->lut_addr;
chn = hvkt->chn;
for (int i = 0; i < chn; i++) {
delta_x0 = hvkt->top_right_x[i] - hvkt->bottom_right_x[i];
delta_y0 = hvkt->top_right_y[i] - hvkt->bottom_right_y[i];
delta_x1 = hvkt->bottom_left_x[i] - hvkt->bottom_right_x[i];
delta_y1 = hvkt->bottom_left_y[i] - hvkt->bottom_right_y[i];
sum_x = hvkt->top_left_x[i] - hvkt->top_right_x[i] +
hvkt->bottom_right_x[i] - hvkt->bottom_left_x[i];
sum_y = hvkt->top_left_y[i] - hvkt->top_right_y[i] +
hvkt->bottom_right_y[i] - hvkt->bottom_left_y[i];
poly0 = (sum_x * delta_y1 - sum_y * delta_x1);
poly0 = poly0 / (delta_x0 * delta_y1 - delta_x1 * delta_y0);
poly1 = (sum_y * delta_x0 - sum_x * delta_y0) /
(delta_x0 * delta_y1 - delta_x1 * delta_y0);
a0 = ((hvkt->top_right_x[i] - hvkt->top_left_x[i]) +
poly0 * hvkt->top_right_x[i]) /
(hvkt->hsize - 1);
a1 = ((hvkt->bottom_left_x[i] - hvkt->top_left_x[i]) +
poly1 * hvkt->bottom_left_x[i]) /
(hvkt->vsize - 1);
a2 = hvkt->top_left_x[i];
b0 = ((hvkt->top_right_y[i] - hvkt->top_left_y[i]) +
poly0 * hvkt->top_right_y[i]) /
(hvkt->hsize - 1);
b1 = ((hvkt->bottom_left_y[i] - hvkt->top_left_y[i]) +
poly1 * hvkt->bottom_left_y[i]) /
(hvkt->vsize - 1);
b2 = hvkt->top_left_y[i];
c0 = poly0 / (hvkt->hsize - 1);
c1 = poly1 / (hvkt->vsize - 1);
c2 = 1;
fabc.fa0[i] = a0;
fabc.fa1[i] = a1;
fabc.fa2[i] = a2;
fabc.fb0[i] = b0;
fabc.fb1[i] = b1;
fabc.fb2[i] = b2;
fabc.fc0[i] = c0;
fabc.fc1[i] = c1;
fabc.fc2[i] = c2;
}
m = (float)hvkt->lut_h_step;
n = (float)hvkt->lut_v_step;
if (!hvkt->is_external_lut) {
extend = hvkt->extend;
for (int v = -extend; v < lut_vsize - extend; v++) {
for (int i = 0; i < chn; i++) {
for (int h = -extend; h < lut_hsize - extend; h++) {
float x = h * m;
float y = v * n;
int c_sel = i;
/*lut[v][i][0][h]*/
int pos_x = (v + extend) * (lut_hsize * chn * 2) +
i * (lut_hsize * 2) + (h + extend);
/*lut[v][i][1][h]*/
int pos_y = (v + extend) * (lut_hsize * chn * 2) +
i * (lut_hsize * 2) + lut_hsize + (h + extend);
// printf("pos_x=%d, pos_y=%d\n", pos_x, pos_y);
lut[pos_x] = hvk_pos_calc(x, y, hvkt, true, c_sel); /*x*/
lut[pos_y] = hvk_pos_calc(x, y, hvkt, false, c_sel); /*y*/
}
}
}
} else { /*bilinear*/
for (int i = 0; i < 6; i++) {
lut_32[i] = (int *)hvkt->lut_real_addr[i];
lut_16[i] = (short *)hvkt->lut_real_addr[i];
}
for (int i = 0; i < chn; i++) {
for (int v = 0; v < lut_vsize; v++) {
for (int h = 0; h < lut_hsize; h++) {
float x = h * m;
float y = v * n;
int c_sel = i;
lut[h] = hvk_pos_calc(x, y, hvkt, true, c_sel); /*x*/
lut[lut_hsize + h] =
hvk_pos_calc(x, y, hvkt, false, c_sel); /*y*/
if (hvkt->external_lut_format == 1) { /*32bits*/
int tmp = (int)(lut[h] * 256);
tmp = (tmp > 524287) ? 524287
: (tmp < -524288) ? -524288 : tmp;
lut_32[i * 2][v * lut_hsize + h] = tmp;
tmp = (int)(lut[lut_hsize + h] * 256);
tmp = (tmp > 524287) ? 524287
: (tmp < -524288) ? -524288 : tmp;
lut_32[i * 2 + 1][v * lut_hsize + h] = tmp;
} else {
int tmp16 = (int)(lut[h] * 16);
tmp16 = (tmp16 > 32767)
? 32767
: (tmp16 < -32768) ? -32768 : tmp16;
lut_16[i * 2][v * lut_hsize + h] = (short)tmp16;
tmp16 = (int)(lut[lut_hsize + h] * 16);
tmp16 = (tmp16 > 32767)
? 32767
: (tmp16 < -32768) ? -32768 : tmp16;
lut_16[i * 2 + 1][v * lut_hsize + h] = (short)tmp16;
}
}
}
}
for (int i = 0; i < 6; i++) {
if (hvkt->external_lut_format == 1) /*32bits*/
arch_clean_cache_range((int)lut_32[i],
lut_hsize * lut_vsize * 4);
else
arch_clean_cache_range((int)lut_16[i],
lut_hsize * lut_vsize * 2);
}
}
return 0;
}
static int m_v_parameter_calc(struct hvkt_param *hvkt)
{
int lut_hsize, lut_vsize;
float *lut_ld = TEMPAA;
float *m_param_ld = TEMPAB;
float *lut = (float *)hvkt->lut_addr;
float *m_v = (float *)hvkt->m_v_addr;
float *alpha_addr = (float *)hvkt->alpha_addr;
int chn = hvkt->chn;
lut_hsize = hvkt->lut_h_size;
lut_vsize = hvkt->lut_v_size;
m_parameter_calc_alpha(lut_vsize, alpha_addr);
for (int h = 0; h < lut_hsize; h++) {
for (int i = 0; i < chn; i++) {
/*x*/
for (int v = 0; v < lut_vsize; v++) {
lut_ld[v] = lut[v * lut_hsize * chn * 2 + i * lut_hsize * 2 +
h]; /*lut[v][i][0][h]*/
}
m_parameter_calc_1d(lut_ld, m_param_ld, alpha_addr, lut_vsize,
false);
for (int v = 0; v < lut_vsize; v++) {
/*m_v[i][v][0][h]*/
m_v[v * lut_hsize * chn * 2 + i * lut_hsize * 2 + h] =
m_param_ld[i];
}
/*y*/
for (int v = 0; v < lut_vsize; v++) {
lut_ld[v] = lut[v * lut_hsize * chn * 2 + i * lut_hsize * 2 +
lut_hsize + h]; /*lut[v][i][1][h]*/
}
m_parameter_calc_1d(lut_ld, m_param_ld, alpha_addr, lut_vsize,
false);
for (int v = 0; v < lut_vsize; v++) {
/*m_v[i][v][1][h]*/
m_v[v * lut_hsize * chn * 2 + i * lut_hsize * 2 + lut_hsize +
h] = m_param_ld[i];
}
}
}
return 0;
}
double sinc(double phase)
{
if (fabs(phase) < 0.0001)
return 1.0;
else
return sin(phase) / phase;
}
static int rotation(double angle, struct hvkt_param *hvkt)
{
double r, theta, rot;
double x, y;
int transpose_en;
double rotate_angle;
double PI = acos(-1);
rotate_angle = (angle * PI) / 180.0;
x = (hvkt->hsize_in - 1.0) / 2.0;
y = (hvkt->vsize_in - 1.0) / 2.0;
theta = atan(y / x);
r = sqrt(x * x + y * y);
if ((rotate_angle >= 0.0 && rotate_angle <= (PI / 4.0)) ||
(rotate_angle > (PI * 7.0 / 4.0) && rotate_angle < (PI * 8.0 / 4.0))) {
rot = rotate_angle;
hvkt->flip_type = 0;
transpose_en = 0;
} else if (rotate_angle >= (3.0 * PI / 4.0) &&
rotate_angle <= (5.0 * PI / 4.0)) {
rot = rotate_angle - PI;
hvkt->flip_type = 3;
transpose_en = 0;
} else if (rotate_angle > (PI / 4.0) && rotate_angle < (PI * 3.0 / 4.0)) {
rot = PI / 2.0 - rotate_angle;
hvkt->flip_type = 1;
transpose_en = 1;
} else if (rotate_angle > (PI * 5.0 / 4.0) &&
rotate_angle < (PI * 7.0 / 4.0)) {
rot = 6.0 * PI / 4.0 - rotate_angle;
hvkt->flip_type = 2;
transpose_en = 1;
} else { /*illigal*/
rot = rotate_angle;
hvkt->flip_type = 0;
transpose_en = 0;
}
rot = -rot;
hvkt->top_left_x[0] = cos(1.0 * PI + theta - rot) * r + x;
hvkt->top_left_y[0] = sin(1.0 * PI + theta - rot) * r + y;
hvkt->top_right_x[0] = cos(-theta - rot) * r + x;
hvkt->top_right_y[0] = sin(-theta - rot) * r + y;
hvkt->bottom_left_x[0] = cos(PI - theta - rot) * r + x;
hvkt->bottom_left_y[0] = sin(PI - theta - rot) * r + y;
hvkt->bottom_right_x[0] = cos(theta - rot) * r + x;
hvkt->bottom_right_y[0] = sin(theta - rot) * r + y;
ASW_LOG_DEBUG("top-left(%f, %f), top-right(%f, %f), bottom-left(%f, %f), "
"bottom-right(%f, %f)",
hvkt->top_left_x[0], hvkt->top_left_y[0],
hvkt->top_right_x[0], hvkt->top_right_y[0],
hvkt->bottom_left_x[0], hvkt->bottom_left_y[0],
hvkt->bottom_right_x[0], hvkt->bottom_right_y[0]);
return transpose_en;
}
static int rotate_lut_table_gen(double angle, struct hvkt_param *hvkt)
{
rotation(angle, hvkt);
hvk_table_gen(hvkt);
return 0;
}
struct sdrv_lut_hvk_ops lut_hvk_ops = {
.lut_table_gen = hvk_table_gen,
.lut_m_v_gen = m_v_parameter_calc,
.lut_rotate_table_gen = rotate_lut_table_gen,
};