Files
test/drivers/source/asw/sdrv_asw_drv.c
2025-11-07 20:19:23 +08:00

860 lines
27 KiB
C

/**
* @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,
};