Files
1CAR/drivers/source/g2dlite/sdrv_g2dlite_drv.c
2025-10-25 21:11:06 +08:00

1852 lines
63 KiB
C

/**
* @file sdrv_g2dlite_drv.c
* @brief SemiDrive G2DLite driver file.
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <armv7-r/cache.h>
#include <g2dlite/g2dlite.h>
#include <g2dlite/g2dlite_core.h>
#include <g2dlite/g2dlite_log.h>
#include <g2dlite/g2dlite_reg.h>
#include <stdlib.h>
#include <udelay/udelay.h>
#if CONFIG_OS_FREERTOS
#include <FreeRTOS.h>
#include <semphr.h>
extern SemaphoreHandle_t done_sema;
#endif
#define G2DLITE_CLUT_SADDR 0x5400
#define G2DLITE_CLUT_EADDR 0x57FF
#define G2DLITE_PD_IDX 3
static const u8 r_wml_cfgs[8][5] = {
/*fastcopy*/
{0x00, 0x00, 0x00, 0x00, 0x40},
/*GPipe Only(1palne)*/
{0x30, 0x00, 0x00, 0x00, 0x10},
/*GPipe Only(2palnes)*/
{0x18, 0x18, 0x00, 0x00, 0x10},
/*GPipe Only(3palnes)*/
{0x18, 0x10, 0x10, 0x00, 0x08},
/*SPipe Only(1palne)*/
{0x00, 0x00, 0x00, 0x30, 0x10},
/*GPipe(1palne) + Spipe*/
{0x18, 0x00, 0x00, 0x18, 0x10},
/*GPipe(2palnes) + Spipe*/
{0x10, 0x10, 0x00, 0x10, 0x10},
/*GPipe(3palnes) + Spipe*/
{0x10, 0x08, 0x08, 0x10, 0x10}};
static const u8 r_d_depth_cfgs[8][5] = {
/*fastcopy*/
{0x00, 0x00, 0x00, 0x00, 0x08},
/*GPipe Only(1palne)*/
{0x06, 0x00, 0x00, 0x00, 0x02},
/*GPipe Only(2palnes)*/
{0x03, 0x03, 0x00, 0x00, 0x02},
/*GPipe Only(3palnes)*/
{0x03, 0x02, 0x02, 0x00, 0x01},
/*SPipe Only(1palne)*/
{0x00, 0x00, 0x00, 0x06, 0x02},
/*GPipe(1palne) + Spipe*/
{0x03, 0x00, 0x00, 0x03, 0x02},
/*GPipe(2palnes) + Spipe*/
{0x02, 0x02, 0x00, 0x03, 0x01},
/*GPipe(3palnes) + Spipe*/
{0x02, 0x01, 0x01, 0x03, 0x01}};
static const u8 r_c_depth_cfgs[8][5] = {
/*fastcopy*/
{0x00, 0x00, 0x00, 0x00, 0x08},
/*GPipe Only(1palne)*/
{0x06, 0x00, 0x00, 0x00, 0x02},
/*GPipe Only(2palnes)*/
{0x03, 0x03, 0x00, 0x00, 0x02},
/*GPipe Only(3palnes)*/
{0x03, 0x02, 0x02, 0x00, 0x01},
/*SPipe Only(1palne)*/
{0x00, 0x00, 0x00, 0x06, 0x02},
/*GPipe(1palne) + Spipe*/
{0x03, 0x00, 0x00, 0x03, 0x02},
/*GPipe(2palnes) + Spipe*/
{0x02, 0x02, 0x00, 0x03, 0x01},
/*GPipe(3palnes) + Spipe*/
{0x02, 0x01, 0x01, 0x03, 0x01}};
static const u8 w_wml_cfgs[3][3] = {
/*fastcopy && Wipe(1plane)*/
{0x40, 0x00, 0x00},
/*Wipe(2planes)*/
{0x20, 0x20, 0x00},
/*Wipe(3planes)*/
{0x20, 0x10, 0x10}};
static const u8 w_d_depth_cfgs[3][3] = {
/*fastcopy && Wipe(1plane)*/
{0x08, 0x00, 0x00},
/*Wipe(2planes)*/
{0x04, 0x04, 0x00},
/*Wipe(3planes)*/
{0x04, 0x02, 0x02}};
static const u8 w_c_depth_cfgs[3][3] = {
/*fastcopy && Wipe(1plane)*/
{0x08, 0x00, 0x00},
/*Wipe(2planes)*/
{0x04, 0x04, 0x00},
/*Wipe(3planes)*/
{0x04, 0x02, 0x02}};
static const uint32_t csc_param[5][15] = {
{/*YCbCr to RGB*/
0x094F, 0x0000, 0x0CC4, 0x094F, 0x3CE0, 0x397F, 0x094F, 0x1024, 0x0000,
0x0000, 0x0000, 0x0000, 0x0040, 0x0200, 0x0200},
{/*bt709 YCbCr to RGB(16-235)*/
0x0800, 0x0000, 0x0C99, 0x0800, 0x3E81, 0x3C42, 0x0800, 0x0ED8, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0200},
{/*YUV to RGB*/
0x0800, 0x0000, 0x091E, 0x0800, 0x3CD8, 0x3B5B, 0x0800, 0x1041, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{/*RGB to YCbCr*/
0x0264, 0x04B2, 0x00E9, 0x3EA0, 0x3D4A, 0x0416, 0x0416, 0x3C94, 0x3F57,
0x0000, 0x0200, 0x0200, 0x0000, 0x0000, 0x0000},
{/*RGB to YUV*/
0x0000}};
static uint32_t G2DLITE_HSCALER[3][2] = {
{0x2600, 0x29ff}, /**< {HS_0_SADDR, HS_0_EADDR}*/
{0x3600, 0x39ff}, /**< {HS_1_SADDR, HS_1_EADDR}*/
{0x4600, 0x49ff} /**< {HS_2_SADDR, HS_2_EADDR}*/
};
static uint32_t G2DLITE_VSCALER[3][2] = {
{0x2a00, 0x2dff}, /**< {VS_0_SADDR, VS_0_EADDR}*/
{0x3a00, 0x3dff}, /**< {VS_1_SADDR, VS_1_EADDR}*/
{0x4a00, 0x4dff} /**< {VS_2_SADDR, VS_2_EADDR}*/
};
static unsigned int get_l_addr(unsigned long addr)
{
unsigned int addr_l;
addr_l = (unsigned int)(addr & 0x00000000FFFFFFFF);
return addr_l;
}
static unsigned int get_h_addr(unsigned long addr)
{
unsigned int addr_h;
addr_h = (unsigned int)(addr & 0xFFFFFFFF00000000);
return addr_h;
}
static void get_bpp_by_format(unsigned int format, unsigned char *bpp)
{
switch (format) {
case COLOR_MONOTONIC_8BIT:
bpp[0] = 8;
bpp[1] = bpp[2] = 0;
break;
case COLOR_RGB565:
case COLOR_BGR565:
case COLOR_ARGB4444:
case COLOR_BGRA4444:
case COLOR_ARGB1555:
case COLOR_BGRA5551:
case COLOR_ABGR1555:
case COLOR_YUYV:
bpp[0] = 16;
bpp[1] = bpp[2] = 0;
break;
case COLOR_RGB666:
case COLOR_BGR666:
bpp[0] = 18;
bpp[1] = bpp[2] = 0;
break;
case COLOR_RGB888:
case COLOR_BGR888:
bpp[0] = 24;
bpp[1] = bpp[2] = 0;
break;
case COLOR_ARGB8888:
case COLOR_BGRA8888:
case COLOR_ABGR8888:
case COLOR_ARGB2101010:
case COLOR_BGRA1010102:
bpp[0] = 32;
bpp[1] = bpp[2] = 0;
break;
case COLOR_NV21:
case COLOR_NV12:
case COLOR_NV61:
case COLOR_NV16:
bpp[0] = 8;
bpp[1] = 8;
bpp[2] = 0;
break;
case COLOR_YUV420P:
case COLOR_YUV422P:
case COLOR_YUV444P:
bpp[0] = 8;
bpp[1] = 8;
bpp[2] = 8;
break;
default:
bpp[0] = bpp[1] = bpp[2] = 0;
break;
}
}
static void g2dlite_com_regs_init(struct g2dlite_device *dev)
{
unsigned long base = dev->reg_base;
/* G2DLITE_INT_MASK */
/*g2dlite mask:1-disable irq, 0-enable irq */
/*bit[6]: G2DLITE_FRM_DONE */
/*bit[5]: G2DLITE_TASK_DONE */
/*bit[4]: WDMA */
/*bit[3]: RLE_1 */
/*bit[2]: MLC */
/*bit[1]: RLE_0 */
/*bit[0]: RDMA */
g2dlite_write(base, G2D_RA020,
0x3F); /*set G2DLITE_FRM_DONE enable*/
}
static void g2dlite_rdma_init(struct g2dlite_device *dev)
{
int i = 0;
const unsigned short wml_cfg[] = {0x08, 0x08, 0x08, 0x08, 0x08};
const unsigned short d_depth_cfg[] = {0x01, 0x01, 0x01, 0x01, 0x01};
const unsigned short c_depth_cfg[] = {0x01, 0x01, 0x01, 0x01, 0x01};
const unsigned char sche_cfg[] = {0x04, 0x04, 0x04, 0x04, 0x04};
const unsigned char p1_cfg[] = {0x30, 0x30, 0x30, 0x30, 0x30};
const unsigned char p0_cfg[] = {0x10, 0x10, 0x10, 0x10, 0x10};
const unsigned char burst_mode_cfg[] = {0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char burst_len_cfg[] = {0x04, 0x04, 0x04, 0x04, 0x04};
unsigned int val;
unsigned long base = dev->reg_base;
for (i = 0; i < CHN_COUNT; i++)
g2dlite_write(base, G2D_RB000(i), wml_cfg[i]);
for (i = 0; i < CHN_COUNT; i++)
g2dlite_write(base, G2D_RB004(i), d_depth_cfg[i]);
for (i = 0; i < CHN_COUNT; i++)
g2dlite_write(base, G2D_RB008(i), c_depth_cfg[i]);
for (i = 0; i < CHN_COUNT; i++) {
val = reg_value(sche_cfg[i], 0, G2D_SHIFT16_RB00C,
G2D_MASK16_RB00C);
val = reg_value(p1_cfg[i], val, G2D_SHIFT08_RB00C,
G2D_MASK08_RB00C);
val = reg_value(p0_cfg[i], val, G2D_SHIFT00_RB00C,
G2D_MASK00_RB00C);
g2dlite_write(base, G2D_RB00C(i), val);
}
for (i = 0; i < CHN_COUNT; i++) {
val = reg_value(burst_mode_cfg[i], 0, G2D_SHIFT03_RB010,
G2D_MASK03_RB010);
val = reg_value(burst_len_cfg[i], val, G2D_SHIFT00_RB010,
G2D_MASK00_RB010);
g2dlite_write(base, G2D_RB010(i), val);
}
g2dlite_write(base, G2D_RB520, 0);
val = reg_value(1, 0, G2D_SHIFT01_RB400, G2D_MASK01_RB400);
val = reg_value(1, val, G2D_SHIFT00_RB400, G2D_MASK00_RB400);
g2dlite_write(base, G2D_RB400, val);
}
static void g2dlite_gpipe_init(struct g2dlite_device *dev)
{
const unsigned char hs_nor_para = 0x09;
const unsigned char hs_ratio_int = 0x01;
const unsigned char hs_ratio_fra = 0x00;
const unsigned char vs_nor_para = 0x06;
unsigned int val;
unsigned long base = dev->reg_base;
/*YUVUP Bypass*/
val = reg_value(1, 0, G2D_SHIFT00_RC044,
G2D_MASK00_RC044);
g2dlite_write(base, G2D_RC044, val);
/*CSC Bypass*/
val = reg_value(1, 0, G2D_SHIFT00_RC200, G2D_MASK00_RC200);
g2dlite_write(base, G2D_RC200, val);
val = reg_value(csc_param[0][1], 0, G2D_SHIFT16_RC204,
G2D_MASK16_RC204);
val = reg_value(csc_param[0][0], val, G2D_SHIFT00_RC204,
G2D_MASK00_RC204);
g2dlite_write(base, G2D_RC204, val);
val = reg_value(csc_param[0][3], 0, G2D_SHIFT16_RC208,
G2D_MASK16_RC208);
val = reg_value(csc_param[0][2], val, G2D_SHIFT00_RC208,
G2D_MASK00_RC208);
g2dlite_write(base, G2D_RC208, val);
val = reg_value(csc_param[0][5], 0, G2D_SHIFT16_RC20C,
G2D_MASK16_RC20C);
val = reg_value(csc_param[0][4], val, G2D_SHIFT00_RC20C,
G2D_MASK00_RC20C);
g2dlite_write(base, G2D_RC20C, val);
val = reg_value(csc_param[0][7], 0, G2D_SHIFT16_RC210,
G2D_MASK16_RC210);
val = reg_value(csc_param[0][6], val, G2D_SHIFT00_RC210,
G2D_MASK00_RC210);
g2dlite_write(base, G2D_RC210, val);
val = reg_value(csc_param[0][9], 0, G2D_SHIFT16_RC214,
G2D_MASK16_RC214);
val = reg_value(csc_param[0][8], val, G2D_SHIFT00_RC214,
G2D_MASK00_RC214);
g2dlite_write(base, G2D_RC214, val);
val = reg_value(csc_param[0][11], 0, G2D_SHIFT16_RC218,
G2D_MASK16_RC218);
val = reg_value(csc_param[0][10], val, G2D_SHIFT00_RC218,
G2D_MASK00_RC218);
g2dlite_write(base, G2D_RC218, val);
val = reg_value(csc_param[0][13], 0, G2D_SHIFT16_RC21C,
G2D_MASK16_RC21C);
val = reg_value(csc_param[0][12], val, G2D_SHIFT00_RC21C,
G2D_MASK00_RC21C);
g2dlite_write(base, G2D_RC21C, val);
val = reg_value(csc_param[0][14], 0, G2D_SHIFT00_RC220,
G2D_MASK00_RC220);
g2dlite_write(base, G2D_RC220, val);
/*HSCALER*/
val = reg_value(hs_nor_para, 0, G2D_SHIFT08_RC300,
G2D_MASK08_RC300);
g2dlite_write(base, G2D_RC300, val);
g2dlite_write(base, G2D_RC304, 0);
val =
reg_value(hs_ratio_int, 0, G2D_SHIFT19_RC308, G2D_MASK19_RC308);
val = reg_value(hs_ratio_fra, val, G2D_SHIFT00_RC308,
G2D_MASK00_RC308);
g2dlite_write(base, G2D_RC308, val);
/*VSCALER*/
val = reg_value(vs_nor_para, val, G2D_SHIFT04_RC400,
G2D_MASK04_RC400);
g2dlite_write(base, G2D_RC400, val);
g2dlite_write(base, G2D_RC408, 0);
g2dlite_write(base, G2D_RC40C, 0);
g2dlite_write(base, G2D_RC410, 0);
}
static void g2dlite_spipe_init(struct g2dlite_device *dev)
{
unsigned int val;
unsigned long base = dev->reg_base;
val = g2dlite_read(base, G2D_RD200);
val = reg_value(1, val, G2D_SHIFT18_RD200, G2D_MASK18_RD200);
val = reg_value(1, val, G2D_SHIFT16_RD200, G2D_MASK16_RD200);
g2dlite_write(base, G2D_RD200, val);
val = g2dlite_read(base, G2D_RD204);
val = reg_value(1, val, G2D_SHIFT16_RD204, G2D_MASK16_RD204);
g2dlite_write(base, G2D_RD204, val);
val = g2dlite_read(base, G2D_RD208);
val = reg_value(1, val, G2D_SHIFT16_RD208, G2D_MASK16_RD208);
g2dlite_write(base, G2D_RD208, val);
val = g2dlite_read(base, G2D_RD20C);
val = reg_value(1, val, G2D_SHIFT16_RD20C, G2D_MASK16_RD20C);
g2dlite_write(base, G2D_RD20C, val);
}
static void g2dlite_mlc_init(struct g2dlite_device *dev)
{
int i = 0;
unsigned int val;
unsigned long base = dev->reg_base;
const unsigned char prot_val[] = {0x7, 0x7};
const unsigned char alpha_bld[] = {0xF, 0xF, 0xF};
const unsigned char pd_out[] = {0x7, 0x7, 0x7};
const unsigned char pd_des[] = {0x7, 0x7, 0x7};
const unsigned char pd_src[] = {0x7, 0x7, 0x7};
const unsigned char layer_out[] = {0xF, 0xF, 0xF};
/*LAYER related*/
for (i = 0; i < MLC_LAYER_COUNT; i++) {
val = reg_value(prot_val[i], 0, G2D_SHIFT08_RE000,
G2D_MASK08_RE000);
val =
reg_value(1, val, G2D_SHIFT02_RE000, G2D_MASK02_RE000);
g2dlite_write(base, G2D_RE000(i), val);
g2dlite_write(base, G2D_RE018(i), 0xFF);
}
/*PATH related*/
for (i = 0; i < MLC_PATH_COUNT; i++) {
val =
reg_value(alpha_bld[i], 0, G2D_SHIFT16_RE200, G2D_MASK16_RE200);
val = reg_value(pd_out[i], val, G2D_SHIFT12_RE200, G2D_MASK12_RE200);
val = reg_value(pd_des[i], val, G2D_SHIFT08_RE200, G2D_MASK08_RE200);
val = reg_value(pd_src[i], val, G2D_SHIFT04_RE200, G2D_MASK04_RE200);
val = reg_value(layer_out[i], val, G2D_SHIFT00_RE200,
G2D_MASK00_RE200);
g2dlite_write(base, G2D_RE200(i), val);
}
g2dlite_write(base, G2D_RE234, 0xFFFF);
g2dlite_write(base, G2D_RE240, 0);
}
static void g2dlite_wdma_init(struct g2dlite_device *dev)
{
int i = 0;
const unsigned short wml_cfg[] = {0x20, 0x10, 0x10};
const unsigned short d_depth_cfg[] = {0x04, 0x02, 0x02};
const unsigned short c_depth_cfg[] = {0x04, 0x02, 0x02};
const unsigned char sche_cfg[] = {0x04, 0x02, 0x02};
const unsigned char p1_cfg[] = {0x30, 0x30, 0x30};
const unsigned char p0_cfg[] = {0x10, 0x10, 0x10};
const unsigned char burst_mode_cfg[] = {0x00, 0x00, 0x00};
const unsigned char burst_len_cfg[] = {0x04, 0x04, 0x04};
unsigned int val;
unsigned long base = dev->reg_base;
for (i = 0; i < WCHN_COUNT; i++)
g2dlite_write(base, G2D_RG000(i), wml_cfg[i]);
for (i = 0; i < WCHN_COUNT; i++)
g2dlite_write(base, G2D_RG004(i), d_depth_cfg[i]);
for (i = 0; i < WCHN_COUNT; i++)
g2dlite_write(base, G2D_RG008(i), c_depth_cfg[i]);
for (i = 0; i < WCHN_COUNT; i++) {
val = reg_value(sche_cfg[i], 0, G2D_SHIFT16_RG00C,
G2D_MASK16_RG00C);
val = reg_value(p1_cfg[i], val, G2D_SHIFT08_RG00C,
G2D_MASK08_RG00C);
val = reg_value(p0_cfg[i], val, G2D_SHIFT00_RG00C,
G2D_MASK00_RG00C);
g2dlite_write(base, G2D_RG00C(i), val);
}
for (i = 0; i < WCHN_COUNT; i++) {
val = reg_value(burst_mode_cfg[i], 0, G2D_SHIFT03_RG010,
G2D_MASK03_RG010);
val = reg_value(burst_len_cfg[i], val, G2D_SHIFT00_RG010,
G2D_MASK00_RG010);
g2dlite_write(base, G2D_RG010(i), val);
}
g2dlite_write(base, G2D_RG520, 0);
}
static void g2dlite_wpipe_init(struct g2dlite_device *dev)
{
unsigned int val;
unsigned long base = dev->reg_base;
/*YUVDOWN Bypass*/
val = reg_value(1, 0, G2D_SHIFT08_RH008,
G2D_MASK08_RH008);
g2dlite_write(base, G2D_RH008, val);
/*CSC Bypass*/
val = reg_value(1, 0, G2D_SHIFT00_RH040, G2D_MASK00_RH040);
g2dlite_write(base, G2D_RH040, val);
val = reg_value(csc_param[3][1], 0, G2D_SHIFT16_RH044,
G2D_MASK16_RH044);
val = reg_value(csc_param[3][0], val, G2D_SHIFT00_RH044,
G2D_MASK00_RH044);
g2dlite_write(base, G2D_RH044, val);
val = reg_value(csc_param[3][3], 0, G2D_SHIFT16_RH048,
G2D_MASK16_RH048);
val = reg_value(csc_param[3][2], val, G2D_SHIFT00_RH048,
G2D_MASK00_RH048);
g2dlite_write(base, G2D_RH048, val);
val = reg_value(csc_param[3][5], 0, G2D_SHIFT16_RH04C,
G2D_MASK16_RH04C);
val = reg_value(csc_param[3][4], val, G2D_SHIFT00_RH04C,
G2D_MASK00_RH04C);
g2dlite_write(base, G2D_RH04C, val);
val = reg_value(csc_param[3][7], 0, G2D_SHIFT16_RH050,
G2D_MASK16_RH050);
val = reg_value(csc_param[3][6], val, G2D_SHIFT00_RH050,
G2D_MASK00_RH050);
g2dlite_write(base, G2D_RH050, val);
val = reg_value(csc_param[3][9], 0, G2D_SHIFT16_RH054,
G2D_MASK16_RH054);
val = reg_value(csc_param[3][8], val, G2D_SHIFT00_RH054,
G2D_MASK00_RH054);
g2dlite_write(base, G2D_RH054, val);
val = reg_value(csc_param[3][11], 0, G2D_SHIFT16_RH058,
G2D_MASK16_RH058);
val = reg_value(csc_param[3][10], val, G2D_SHIFT00_RH058,
G2D_MASK00_RH058);
g2dlite_write(base, G2D_RH058, val);
val = reg_value(csc_param[3][13], 0, G2D_SHIFT16_RH05C,
G2D_MASK16_RH05C);
val = reg_value(csc_param[3][12], val, G2D_SHIFT00_RH05C,
G2D_MASK00_RH05C);
g2dlite_write(base, G2D_RH05C, val);
val = reg_value(csc_param[3][14], 0, G2D_SHIFT00_RH060,
G2D_MASK00_RH060);
g2dlite_write(base, G2D_RH060, val);
}
static u8 get_r_idx(struct g2dlite_input *ins)
{
int g_nplanes = 0;
switch (ins->layer_num) {
case 1:
if (ins->layer[0].layer == G2DLITE_TYPE_GPIPE) {
g_nplanes = COLOR_GET_PLANE_COUNT(ins->layer[0].fmt);
return g_nplanes;
}
if (ins->layer[0].layer == G2DLITE_TYPE_SPIPE) {
return 4;
}
case 2:
for (int i = 0; i < 2; i++) {
if (ins->layer[i].layer == G2DLITE_TYPE_GPIPE) {
g_nplanes = COLOR_GET_PLANE_COUNT(ins->layer[0].fmt);
return (g_nplanes + 4);
}
}
default:
return 0;
}
}
static u8 get_w_idx(struct g2dlite_output_cfg *output)
{
return COLOR_GET_PLANE_COUNT(output->fmt) - 1;
}
static void g2dlite_rwdma_set(struct g2dlite_device *dev, u8 r_idx, u8 w_idx)
{
int i = 0;
unsigned int val = 0;
unsigned long base = dev->reg_base;
for (i = 0; i < CHN_COUNT; i++)
g2dlite_write(base, G2D_RB000(i), r_wml_cfgs[r_idx][i]);
for (i = 0; i < CHN_COUNT; i++)
g2dlite_write(base, G2D_RB004(i),
r_d_depth_cfgs[r_idx][i]);
for (i = 0; i < CHN_COUNT; i++)
g2dlite_write(base, G2D_RB008(i),
r_c_depth_cfgs[r_idx][i]);
val = reg_value(1, 0, G2D_SHIFT01_RB400, G2D_MASK01_RB400);
val = reg_value(1, val, G2D_SHIFT00_RB400, G2D_MASK00_RB400);
g2dlite_write(base, G2D_RB400, val);
for (i = 0; i < WCHN_COUNT; i++)
g2dlite_write(base, G2D_RG000(i), w_wml_cfgs[w_idx][i]);
for (i = 0; i < WCHN_COUNT; i++)
g2dlite_write(base, G2D_RG004(i),
w_d_depth_cfgs[w_idx][i]);
for (i = 0; i < WCHN_COUNT; i++)
g2dlite_write(base, G2D_RG008(i),
w_c_depth_cfgs[w_idx][i]);
}
static void g2dlite_set_hscaler_coef(struct g2dlite_device *dev)
{
const int hscaler_coef[33][5] = {
{0, 0, 512, 0, 0}, {0, -5, 512, 5, 0},
{0, -10, 511, 11, 0}, {0, -14, 509, 17, 0},
{0, -18, 508, 23, -1}, {-1, -22, 507, 29, -1},
{-1, -25, 503, 36, -1}, {-1, -28, 500, 43, -2},
{-2, -31, 496, 51, -2}, {-2, -33, 491, 59, -3},
{-3, -35, 486, 67, -3}, {-3, -37, 481, 75, -4},
{-3, -39, 475, 84, -5}, {-4, -41, 471, 92, -6},
{-5, -42, 464, 102, -7}, {-5, -43, 457, 111, -8},
{-6, -43, 449, 121, -9}, {-6, -44, 442, 130, -10},
{-7, -44, 435, 140, -12}, {-7, -44, 425, 151, -13},
{-8, -44, 417, 161, -14}, {-8, -44, 408, 172, -16},
{-9, -44, 399, 183, -17}, {-9, -43, 390, 193, -19},
{-9, -42, 379, 204, -20}, {-10, -41, 369, 216, -22},
{-10, -40, 358, 227, -23}, {-11, -39, 349, 238, -25},
{-11, -38, 339, 249, -27}, {-11, -37, 327, 261, -28},
{-11, -36, 317, 272, -30}, {-12, -34, 306, 283, -31},
{-12, -33, 295, 295, -33},
};
unsigned int head, tail;
unsigned long base = dev->reg_base;
for (int i = 0; i < 33; i++) {
head = ((hscaler_coef[i][0] & 0x7ff) << 12) |
((hscaler_coef[i][1] & 0x7ff) << 1) |
((hscaler_coef[i][2] & 0x400) >> 10);
tail = ((hscaler_coef[i][2] & 0x3ff) << 22) |
((hscaler_coef[i][3] & 0x7ff) << 11) |
(hscaler_coef[i][4] & 0x7ff);
g2dlite_write(base, G2DLITE_HSCALER[0][0] + i * 4, head);
g2dlite_write(base, G2DLITE_HSCALER[0][0] + 0x100 + i * 4, tail);
}
}
static void g2dlite_set_vscaler_coef(struct g2dlite_device *dev)
{
const int vscaler_coef[33][4] = {
{0, 64, 0, 0}, {-1, 64, 1, 0}, {-1, 64, 1, 0}, {-2, 64, 2, 0},
{-2, 63, 3, 0}, {-3, 63, 4, 0}, {-3, 62, 5, 0}, {-3, 62, 5, 0},
{-4, 62, 6, 0}, {-4, 61, 7, 0}, {-4, 60, 8, 0}, {-5, 61, 9, -1},
{-5, 60, 10, -1}, {-5, 59, 11, -1}, {-5, 57, 13, -1}, {-5, 56, 14, -1},
{-5, 55, 15, -1}, {-5, 54, 16, -1}, {-5, 53, 17, -1}, {-5, 52, 19, -2},
{-5, 51, 20, -2}, {-5, 50, 21, -2}, {-5, 49, 22, -2}, {-5, 47, 24, -2},
{-5, 46, 25, -2}, {-5, 46, 26, -3}, {-5, 44, 28, -3}, {-5, 43, 29, -3},
{-5, 41, 31, -3}, {-5, 40, 32, -3}, {-4, 39, 33, -4}, {-4, 37, 35, -4},
{-4, 36, 36, -4},
};
unsigned int value;
unsigned long base = dev->reg_base;
for (uint32_t i = 0; i < 33; i++) {
value = ((vscaler_coef[i][3] & 0xff) << 24) |
((vscaler_coef[i][2] & 0xff) << 16) |
((vscaler_coef[i][1] & 0xff) << 8) |
((vscaler_coef[i][0] & 0xff));
g2dlite_write(base, G2DLITE_VSCALER[0][0] + i * 4, value);
}
}
static int g2dlite_plane_frm_comp_set(struct g2dlite_device *dev,
struct g2dlite_input_cfg *input)
{
unsigned int compval;
unsigned int frmc_val;
unsigned char abits, ybits, ubits, vbits;
unsigned char swap;
unsigned char comp_swap;
unsigned char is_yuv;
unsigned char is_uvswap;
unsigned char uv_mode;
unsigned char data_mode;
unsigned char buf_fmt;
abits = COLOR_GET_A_BITS_NUM(input->fmt);
ybits = COLOR_GET_Y_BITS_NUM(input->fmt);
ubits = COLOR_GET_U_BITS_NUM(input->fmt);
vbits = COLOR_GET_V_BITS_NUM(input->fmt);
compval = reg_value(vbits, 0, G2D_SHIFT24_RC000, G2D_MASK24_RC000);
compval = reg_value(ubits, compval, G2D_SHIFT16_RC000, G2D_MASK16_RC000);
compval = reg_value(ybits, compval, G2D_SHIFT08_RC000, G2D_MASK08_RC000);
compval = reg_value(abits, compval, G2D_SHIFT00_RC000, G2D_MASK00_RC000);
swap = COLOR_GET_SWAP(input->fmt);
comp_swap = COLOR_GET_COMP_SWAP(input->fmt);
is_yuv = COLOR_GET_IS_YUV(input->fmt);
is_uvswap = COLOR_GET_IS_UV_SWAP(input->fmt);
uv_mode = COLOR_GET_UV_MODE(input->fmt);
data_mode = COLOR_GET_DATA_MODE(input->fmt);
buf_fmt = COLOR_GET_BUF_FMT(input->fmt);
if ((input->layer == G2DLITE_TYPE_SPIPE) && input->rle.en) {
data_mode = RLE_COMPR_MODE;
}
frmc_val =
reg_value(swap, 0, G2D_SHIFT16_RC004, G2D_MASK16_RC004);
frmc_val = reg_value(comp_swap, frmc_val, G2D_SHIFT12_RC004,
G2D_MASK12_RC004);
frmc_val =
reg_value(is_yuv, frmc_val, G2D_SHIFT08_RC004, G2D_MASK08_RC004);
frmc_val =
reg_value(is_uvswap, frmc_val, G2D_SHIFT07_RC004, G2D_MASK07_RC004);
frmc_val =
reg_value(uv_mode, frmc_val, G2D_SHIFT05_RC004, G2D_MASK05_RC004);
frmc_val = reg_value(data_mode, frmc_val, G2D_SHIFT02_RC004, G2D_MASK02_RC004);
frmc_val = reg_value(buf_fmt, frmc_val, G2D_SHIFT00_RC004, G2D_MASK00_RC004);
if (input->layer == G2DLITE_TYPE_SPIPE) {
g2dlite_cwrite(dev, 0, G2D_RD000, compval);
g2dlite_cwrite(dev, 0, G2D_RD004, frmc_val);
} else if (input->layer == G2DLITE_TYPE_GPIPE) {
g2dlite_cwrite(dev, 0, G2D_RC000, compval);
g2dlite_cwrite(dev, 0, G2D_RC004, frmc_val);
} else {
G2DLITE_LOG_ERR("input layer = %d,the number is incorrect",
input->layer);
return -1;
}
return 0;
}
static int g2dlite_wpipe_pixcomp_set(struct g2dlite_device *dev,
struct g2dlite_output_cfg *output)
{
unsigned int val;
unsigned char swap;
unsigned char abits, ybits, ubits, vbits;
unsigned char uv_mode, buf_fmt, reforce;
unsigned long base = dev->reg_base;
switch (COLOR_GET_PLANE_COUNT(output->fmt)) {
case 2:
case 3:
abits = 0;
ybits = 8;
ubits = 8;
vbits = 8;
break;
default:
abits = COLOR_GET_A_BITS_NUM(output->fmt);
ybits = COLOR_GET_Y_BITS_NUM(output->fmt);
ubits = COLOR_GET_U_BITS_NUM(output->fmt);
vbits = COLOR_GET_V_BITS_NUM(output->fmt);
break;
}
val = reg_value(vbits, 0, G2D_SHIFT24_RH004, G2D_MASK24_RH004);
val = reg_value(ubits, val, G2D_SHIFT16_RH004, G2D_MASK16_RH004);
val = reg_value(ybits, val, G2D_SHIFT08_RH004, G2D_MASK08_RH004);
val = reg_value(abits, val, G2D_SHIFT00_RH004, G2D_MASK00_RH004);
g2dlite_cwrite(dev, 0, G2D_RH004, val);
swap = COLOR_GET_SWAP(output->fmt);
uv_mode = COLOR_GET_UV_MODE(output->fmt);
buf_fmt = COLOR_GET_BUF_FMT(output->fmt);
reforce = (output->rotation == ROTATION_TYPE_NONE) ? 1 : 0;
val = g2dlite_read(base, G2D_RH000);
val = reg_value(swap, val, G2D_SHIFT16_RH000,
G2D_MASK16_RH000);
val = reg_value(reforce, val, G2D_SHIFT08_RH000,
G2D_MASK08_RH000);
val = reg_value(uv_mode, val, G2D_SHIFT06_RH000, G2D_MASK06_RH000);
val = reg_value(buf_fmt, val, G2D_SHIFT04_RH000, G2D_MASK04_RH000);
val = reg_value(output->rotation, val, G2D_SHIFT01_RH000,
G2D_MASK03_RH000 | G2D_MASK02_RH000 |
G2D_MASK01_RH000);
g2dlite_cwrite(dev, 0, G2D_RH000, val);
return 0;
}
static int g2dlite_wp_csc_set(struct g2dlite_device *dev,
struct g2dlite_output_cfg *output,
unsigned char flag)
{
unsigned int val;
unsigned char uv_mode;
unsigned char is_yuv;
unsigned char is_yuv420 = 0;
unsigned long base = dev->reg_base;
is_yuv = COLOR_GET_IS_YUV(output->fmt);
uv_mode = COLOR_GET_UV_MODE(output->fmt);
if (uv_mode == UV_YUV420)
is_yuv420 = 1;
if (flag & G2DLITE_FUN_BLEND) {
val = g2dlite_read(base, G2D_RH040);
val = reg_value(!is_yuv, val, G2D_SHIFT00_RH040,
G2D_MASK00_RH040);
g2dlite_cwrite(dev, 0, G2D_RH040, val);
}
val = g2dlite_read(base, G2D_RH008);
val = reg_value(!is_yuv420, val, G2D_SHIFT09_RH008,
G2D_MASK09_RH008);
val = reg_value(!is_yuv, val, G2D_SHIFT08_RH008,
G2D_MASK08_RH008);
g2dlite_cwrite(dev, 0, G2D_RH008, val);
return 0;
}
static int g2dlite_init(struct g2dlite_device *dev)
{
g2dlite_com_regs_init(dev);
g2dlite_rdma_init(dev);
g2dlite_gpipe_init(dev);
g2dlite_spipe_init(dev);
g2dlite_mlc_init(dev);
g2dlite_wdma_init(dev);
g2dlite_wpipe_init(dev);
g2dlite_set_hscaler_coef(dev);
g2dlite_set_vscaler_coef(dev);
return 0;
}
static int g2dlite_reset(struct g2dlite_device *dev)
{
unsigned int val;
unsigned long base = dev->reg_base;
G2DLITE_LOG_FUNC();
val = g2dlite_read(base, G2D_RA000);
val = reg_value(1, val, G2D_SHIFT31_RA000, G2D_MASK31_RA000);
g2dlite_write(base, G2D_RA000, val);
udelay(10);
val = reg_value(0, val, G2D_SHIFT31_RA000, G2D_MASK31_RA000);
g2dlite_write(base, G2D_RA000, val);
dev->status = G2DLITE_IDLE;
return 0;
}
static int g2dlite_gpipe_set(struct g2dlite_device *dev, char cmdid,
struct g2dlite_input_cfg *input)
{
const unsigned int p_hs = 524288;
const unsigned int p_vs = 262114;
unsigned int val;
unsigned int size;
unsigned int vs_inc;
unsigned char nplanes;
int ratio_int, ratio_fra;
unsigned long base = dev->reg_base;
unsigned long input_addr;
unsigned char is_yuv = 0;
nplanes = COLOR_GET_PLANE_COUNT(input->fmt);
if (!cmdid)
g2dlite_plane_frm_comp_set(dev, input);
/*pipe related*/
size = reg_value(input->src.w - 1, 0, G2D_SHIFT00_RC008, G2D_MASK00_RC008);
size = reg_value(input->src.h - 1, size, G2D_SHIFT16_RC008, G2D_MASK16_RC008);
g2dlite_cwrite(dev, cmdid, G2D_RC008, size);
input_addr = input->addr[0];
g2dlite_cwrite(dev, cmdid, G2D_RC00C, get_l_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RC010, get_h_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RC02C, input->src_stride[0] - 1);
val = reg_value(input->src.x, 0, FRM_X_SHIFT, FRM_X_MASK);
val = reg_value(input->src.y, val, FRM_Y_SHIFT, FRM_Y_MASK);
g2dlite_cwrite(dev, cmdid, G2D_RC040, val);
if (nplanes > 1) {
input_addr = input->addr[1];
g2dlite_cwrite(dev, cmdid, G2D_RC014,
get_l_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RC018,
get_h_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RC030,
input->src_stride[1] - 1);
}
if (nplanes > 2) {
input_addr = input->addr[2];
g2dlite_cwrite(dev, cmdid, G2D_RC01C,
get_l_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RC020,
get_h_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RC034,
input->src_stride[2] - 1);
}
/*yuv params*/
is_yuv = COLOR_GET_IS_YUV(input->fmt);
val = g2dlite_read(base, G2D_RC044);
val = reg_value(is_yuv, val, G2D_SHIFT31_RC044,
G2D_MASK31_RC044);
val = reg_value(is_yuv ? 0 : 1, val, G2D_SHIFT00_RC044,
G2D_MASK00_RC044);
g2dlite_cwrite(dev, cmdid, G2D_RC044, val);
val = g2dlite_read(base, G2D_RC200);
val =
reg_value(is_yuv ? 0 : 1, val, G2D_SHIFT00_RC200, G2D_MASK00_RC200);
g2dlite_cwrite(dev, cmdid, G2D_RC200, val);
/*scaler part*/
if (input->src.w == input->dst.w) {
val = g2dlite_read(base, G2D_RC300);
val = reg_value(0, val, G2D_SHIFT03_RC300,
G2D_MASK03_RC300);
val = reg_value(0, val, G2D_SHIFT02_RC300,
G2D_MASK02_RC300);
val = reg_value(0, val, G2D_SHIFT01_RC300,
G2D_MASK01_RC300);
val = reg_value(0, val, G2D_SHIFT00_RC300,
G2D_MASK00_RC300);
g2dlite_cwrite(dev, cmdid, G2D_RC300, val);
val = reg_value(1, 0, G2D_SHIFT19_RC308, G2D_MASK19_RC308);
val = reg_value(0, val, G2D_SHIFT00_RC308, G2D_MASK00_RC308);
g2dlite_cwrite(dev, cmdid, G2D_RC308, val);
} else {
ratio_int = input->src.w / input->dst.w;
ratio_fra = (input->src.w - ratio_int * input->dst.w) * p_hs / input->dst.w;
val = g2dlite_read(base, G2D_RC300);
val = reg_value(1, val, G2D_SHIFT03_RC300,
G2D_MASK03_RC300);
val = reg_value(1, val, G2D_SHIFT02_RC300,
G2D_MASK02_RC300);
val = reg_value(1, val, G2D_SHIFT01_RC300,
G2D_MASK01_RC300);
val = reg_value(1, val, G2D_SHIFT00_RC300,
G2D_MASK00_RC300);
g2dlite_cwrite(dev, cmdid, G2D_RC300, val);
val = reg_value(ratio_int, 0, G2D_SHIFT19_RC308,
G2D_MASK19_RC308);
val = reg_value(ratio_fra, val, G2D_SHIFT00_RC308,
G2D_MASK00_RC308);
g2dlite_cwrite(dev, cmdid, G2D_RC308, val);
}
g2dlite_cwrite(dev, cmdid, G2D_RC30C, input->dst.w - 1);
size = reg_value(input->src.h - 1, 0, G2D_SHIFT16_RC108,
G2D_MASK16_RC108);
size = reg_value(input->dst.w - 1, size, G2D_SHIFT00_RC108,
G2D_MASK00_RC108);
g2dlite_cwrite(dev, cmdid, G2D_RC108, size);
if (input->src.h == input->dst.h) {
val = g2dlite_read(base, G2D_RC400);
val = reg_value(0, val, G2D_SHIFT00_RC400,
G2D_MASK00_RC400);
g2dlite_cwrite(dev, cmdid, G2D_RC400, val);
g2dlite_cwrite(dev, cmdid, G2D_RC408, 0);
} else {
vs_inc = (int)((1.0 * (input->src.h - 1)) / (input->dst.h - 1) * p_vs);
val = g2dlite_read(base, G2D_RC400);
val = reg_value(2, val, G2D_SHIFT00_RC400,
G2D_MASK00_RC400);
g2dlite_cwrite(dev, cmdid, G2D_RC400, val);
g2dlite_cwrite(dev, cmdid, G2D_RC408, vs_inc);
}
g2dlite_cwrite(dev, cmdid, G2D_RC404, input->dst.h - 1);
return 0;
}
static int g2dlite_spipe_set(struct g2dlite_device *dev, char cmdid,
struct g2dlite_input_cfg *input)
{
unsigned int val;
unsigned int size;
unsigned long input_addr;
if (!cmdid)
g2dlite_plane_frm_comp_set(dev, input);
/*pipe related*/
size = reg_value(input->src.w - 1, 0, G2D_SHIFT00_RC008, G2D_MASK00_RC008);
size = reg_value(input->src.h - 1, size, G2D_SHIFT16_RC008, G2D_MASK16_RC008);
g2dlite_cwrite(dev, cmdid, G2D_RD008, size);
input_addr = input->addr[0];
g2dlite_cwrite(dev, cmdid, G2D_RD00C, get_l_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RD010, get_h_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RD02C, input->src_stride[0] - 1);
val = reg_value(input->src.x, 0, FRM_X_SHIFT, FRM_X_MASK);
val = reg_value(input->src.y, val, FRM_Y_SHIFT, FRM_Y_MASK);
g2dlite_cwrite(dev, cmdid, G2D_RD040, val);
/*rle*/
val = reg_value(input->rle.en, 0, G2D_SHIFT00_RD120, G2D_MASK00_RD120);
if (input->rle.en) {
val = reg_value(input->rle.rle_data_size, val, G2D_SHIFT01_RD120,
G2D_MASK01_RD120);
g2dlite_cwrite(dev, cmdid, G2D_RD100, input->rle.rle_y_len);
g2dlite_cwrite(dev, cmdid, G2D_RD110,
input->rle.rle_y_checksum);
}
g2dlite_cwrite(dev, cmdid, G2D_RD120, val);
/*clut*/
if (input->clut.en) {
u8 bpa = COLOR_GET_A_BITS_NUM(input->fmt);
u8 bpy = COLOR_GET_A_BITS_NUM(input->fmt);
u8 bpu = COLOR_GET_A_BITS_NUM(input->fmt);
u8 bpv = COLOR_GET_A_BITS_NUM(input->fmt);
/*G2D_RD200*/
val = g2dlite_read(dev->reg_base, G2D_RD200);
if (bpa) {
val = reg_value(0, val, G2D_SHIFT16_RD200, G2D_MASK16_RD200);
val = reg_value(bpa, val, G2D_SHIFT00_RD200, G2D_MASK00_RD200);
} else {
val = reg_value(1, val, G2D_SHIFT16_RD200, G2D_MASK16_RD200);
}
g2dlite_cwrite(dev, cmdid, G2D_RD200, val);
/*G2D_RD204*/
val = g2dlite_read(dev->reg_base, G2D_RD204);
if (bpy) {
val = reg_value(0, val, G2D_SHIFT16_RD204, G2D_MASK16_RD204);
val = reg_value(bpy, val, G2D_SHIFT00_RD204, G2D_MASK00_RD204);
} else {
val = reg_value(1, val, G2D_SHIFT16_RD204, G2D_MASK16_RD204);
}
g2dlite_cwrite(dev, cmdid, G2D_RD204, val);
/*G2D_RD208*/
val = g2dlite_read(dev->reg_base, G2D_RD208);
if (bpu) {
val = reg_value(0, val, G2D_SHIFT16_RD208, G2D_MASK16_RD208);
val = reg_value(bpu, val, G2D_SHIFT00_RD208, G2D_MASK00_RD208);
} else {
val = reg_value(1, val, G2D_SHIFT16_RD208, G2D_MASK16_RD208);
}
g2dlite_cwrite(dev, cmdid, G2D_RD208, val);
/*G2D_RD20C*/
val = g2dlite_read(dev->reg_base, G2D_RD20C);
if (bpv) {
val = reg_value(0, val, G2D_SHIFT16_RD20C, G2D_MASK16_RD20C);
val = reg_value(bpv, val, G2D_SHIFT00_RD20C, G2D_MASK00_RD20C);
} else {
val = reg_value(1, val, G2D_SHIFT16_RD20C, G2D_MASK16_RD20C);
}
g2dlite_cwrite(dev, cmdid, G2D_RD20C, val);
} else {
/*G2D_RD200*/
val = g2dlite_read(dev->reg_base, G2D_RD200);
val = reg_value(1, val, G2D_SHIFT16_RD200, G2D_MASK16_RD200);
g2dlite_cwrite(dev, cmdid, G2D_RD200, val);
/*G2D_RD204*/
val = g2dlite_read(dev->reg_base, G2D_RD204);
val = reg_value(1, val, G2D_SHIFT16_RD204, G2D_MASK16_RD204);
g2dlite_cwrite(dev, cmdid, G2D_RD204, val);
/*G2D_RD208*/
val = g2dlite_read(dev->reg_base, G2D_RD208);
val = reg_value(1, val, G2D_SHIFT16_RD208, G2D_MASK16_RD208);
g2dlite_cwrite(dev, cmdid, G2D_RD208, val);
/*G2D_RD20C*/
val = g2dlite_read(dev->reg_base, G2D_RD20C);
val = reg_value(1, val, G2D_SHIFT16_RD20C, G2D_MASK16_RD20C);
g2dlite_cwrite(dev, cmdid, G2D_RD20C, val);
}
return 0;
}
static void g2dlite_close_fastcopy(struct g2dlite_device *dev)
{
unsigned int val;
unsigned long base = dev->reg_base;
/*disable background in order to remove fastcopy
*bring affect when fastcopy using before other
*functions*/
val = g2dlite_read(base, G2D_RF004);
val = reg_value(0, val, G2D_SHIFT00_RF004,
G2D_MASK00_RF004);
g2dlite_write(base, G2D_RF004, val);
val = g2dlite_read(base, G2D_RE220);
val = reg_value(0, val, G2D_SHIFT02_RE220, G2D_MASK02_RE220);
val = reg_value(0, val, G2D_SHIFT01_RE220, G2D_MASK01_RE220);
g2dlite_write(base, G2D_RE220, val);
}
static int g2dlite_mlc_set(struct g2dlite_device *dev, char cmdid,
struct g2dlite_input *ins)
{
int i = 0;
u32 val, sf_val[G2DLITE_MLC_MAX], path_val[MLC_PATH_MAX];
u64 base = dev->reg_base;
u8 pd_types_flag = 0;
/*disable all layers*/
for (i = 0; i < G2DLITE_MLC_MAX; i++) {
val = g2dlite_read(base, G2D_RE000(i));
sf_val[i] = reg_value(0, val, G2D_SHIFT00_RE000, G2D_MASK00_RE000);
g2dlite_cwrite(dev, cmdid, G2D_RE000(i), sf_val[i]);
}
/*disable all paths*/
for (i = 0; i < MLC_PATH_MAX; i++) {
path_val[i] = 0xF777F;
g2dlite_cwrite(dev, cmdid, G2D_RE200(i), path_val[i]);
}
if (ins->bg_layer.en) {
struct g2dlite_bg_cfg *bgcfg = &ins->bg_layer;
if (ins->pd_info.en && (ins->bg_layer.pd_type != PD_NONE)) {
switch (ins->bg_layer.pd_type) {
case PD_SRC:
path_val[0] = reg_value(0, path_val[0], G2D_SHIFT04_RE200,
G2D_MASK04_RE200);
pd_types_flag |= PD_SRC;
break;
case PD_DST:
path_val[0] = reg_value(0, path_val[0], G2D_SHIFT08_RE200,
G2D_MASK08_RE200);
pd_types_flag |= PD_DST;
break;
default:
G2DLITE_LOG_ERR("input bglayer porter-duff type isn't correct");
return -1;
}
path_val[0] = reg_value(G2DLITE_PD_IDX, path_val[0],
G2D_SHIFT00_RE200, G2D_MASK00_RE200);
} else {
/*PATH with zorder*/
path_val[0] = reg_value(bgcfg->zorder, path_val[0],
G2D_SHIFT00_RE200, G2D_MASK00_RE200);
g2dlite_cwrite(dev, cmdid, G2D_RE200(0), path_val[0]);
path_val[bgcfg->zorder] =
reg_value(0, path_val[bgcfg->zorder], G2D_SHIFT16_RE200,
G2D_MASK16_RE200);
g2dlite_cwrite(dev, cmdid, G2D_RE200(bgcfg->zorder),
path_val[bgcfg->zorder]);
}
}
for (i = 0; i < G2DLITE_MLC_MAX; i++) {
struct g2dlite_input_cfg *input = &ins->layer[i];
if (!input->layer_en)
continue;
u8 layer_index = input->layer;
u8 path_index = input->layer + 1;
if (layer_index >= G2DLITE_MLC_MAX) {
G2DLITE_LOG_ERR("input layer = %d, the number isn't correct",
input->layer);
return -1;
}
/*POS*/
g2dlite_cwrite(dev, cmdid, G2D_RE004(layer_index), input->dst.x);
g2dlite_cwrite(dev, cmdid, G2D_RE008(layer_index), input->dst.y);
/*dst size*/
val = reg_value(input->dst.h - 1, 0, G2D_SHIFT16_RE00C,
G2D_MASK16_RE00C);
val = reg_value(input->dst.w - 1, val, G2D_SHIFT00_RE00C,
G2D_MASK00_RE00C);
g2dlite_cwrite(dev, cmdid, G2D_RE00C(layer_index), val);
if (ins->pd_info.en && (input->pd_type != PD_NONE)) {
if (pd_types_flag == (PD_SRC | PD_DST)) {
G2DLITE_LOG_ERR("porter-duff type was already input");
return -1;
}
switch (input->pd_type) {
case PD_SRC:
path_val[0] = reg_value(path_index, path_val[0],
G2D_SHIFT04_RE200, G2D_MASK04_RE200);
pd_types_flag |= PD_SRC;
break;
case PD_DST:
path_val[0] = reg_value(path_index, path_val[0],
G2D_SHIFT08_RE200, G2D_MASK08_RE200);
pd_types_flag |= PD_DST;
break;
default:
G2DLITE_LOG_ERR("input layer%d porter-duff type isn't correct",
input->layer);
return -1;
}
path_val[path_index] =
reg_value(G2DLITE_PD_IDX, path_val[path_index],
G2D_SHIFT00_RE200, G2D_MASK00_RE200);
switch (input->blend) {
case BLEND_PIXEL_NONE:
default:
sf_val[layer_index] =
reg_value(1, sf_val[layer_index], G2D_SHIFT02_RE000,
G2D_MASK02_RE000);
g2dlite_cwrite(dev, cmdid, G2D_RE018(layer_index),
input->alpha);
break;
case BLEND_PIXEL_COVERAGE:
sf_val[layer_index] =
reg_value(0, sf_val[layer_index], G2D_SHIFT02_RE000,
G2D_MASK02_RE000);
break;
}
} else {
/*PATH with zorder*/
path_val[path_index] =
reg_value(input->zorder, path_val[path_index],
G2D_SHIFT00_RE200, G2D_MASK00_RE200);
g2dlite_cwrite(dev, cmdid, G2D_RE200(path_index),
path_val[path_index]);
path_val[input->zorder] =
reg_value(path_index, path_val[input->zorder],
G2D_SHIFT16_RE200, G2D_MASK16_RE200);
g2dlite_cwrite(dev, cmdid, G2D_RE200(input->zorder),
path_val[input->zorder]);
/*Blend mode*/
switch (input->blend) {
case BLEND_PIXEL_NONE:
default:
sf_val[layer_index] =
reg_value(1, sf_val[layer_index], G2D_SHIFT02_RE000,
G2D_MASK02_RE000);
g2dlite_cwrite(dev, cmdid, G2D_RE018(layer_index),
input->alpha);
break;
case BLEND_PIXEL_PREMULTI:
sf_val[layer_index] =
reg_value(0, sf_val[layer_index], G2D_SHIFT02_RE000,
G2D_MASK02_RE000);
path_val[input->zorder] = reg_value(1, path_val[input->zorder],
G2D_SHIFT29_RE200, G2D_MASK29_RE200);
g2dlite_cwrite(dev, cmdid, G2D_RE200(input->zorder),
path_val[input->zorder]);
break;
case BLEND_PIXEL_COVERAGE:
sf_val[layer_index] =
reg_value(0, sf_val[layer_index], G2D_SHIFT02_RE000,
G2D_MASK02_RE000);
break;
}
}
/*enable layer*/
sf_val[layer_index] =
reg_value(1, sf_val[layer_index], G2D_SHIFT00_RE000, G2D_MASK00_RE000);
/*ckey*/
sf_val[layer_index] =
reg_value(input->ckey.en, sf_val[layer_index], G2D_SHIFT03_RE000,
G2D_MASK03_RE000);
g2dlite_cwrite(dev, cmdid, G2D_RE000(layer_index),
sf_val[layer_index]);
if (input->ckey.en) {
g2dlite_cwrite(dev, cmdid, G2D_RE01C(layer_index),
input->ckey.alpha);
val = reg_value(input->ckey.range.r_dn, 0, G2D_SHIFT00_RE020,
G2D_MASK00_RE020);
val = reg_value(input->ckey.range.r_up, val,
G2D_SHIFT16_RE020, G2D_MASK16_RE020);
g2dlite_cwrite(dev, cmdid, G2D_RE020(layer_index), val);
val = reg_value(input->ckey.range.g_dn, 0, G2D_SHIFT00_RE020,
G2D_MASK00_RE020);
val = reg_value(input->ckey.range.g_up, val,
G2D_SHIFT16_RE020, G2D_MASK16_RE020);
g2dlite_cwrite(dev, cmdid, G2D_RE024(layer_index), val);
val = reg_value(input->ckey.range.b_dn, 0, G2D_SHIFT00_RE020,
G2D_MASK00_RE020);
val = reg_value(input->ckey.range.b_up, val,
G2D_SHIFT16_RE020, G2D_MASK16_RE020);
g2dlite_cwrite(dev, cmdid, G2D_RE028(layer_index), val);
}
}
if (ins->pd_info.en) {
path_val[0] = reg_value(ins->pd_info.mode, path_val[0], G2D_SHIFT20_RE200,
G2D_MASK20_RE200);
path_val[0] = reg_value(ins->pd_info.zorder, path_val[0],
G2D_SHIFT12_RE200, G2D_MASK12_RE200);
path_val[ins->pd_info.zorder] =
reg_value(G2DLITE_PD_IDX, path_val[ins->pd_info.zorder],
G2D_SHIFT16_RE200, G2D_MASK16_RE200);
for (i = 0; i < MLC_PATH_MAX; i++) {
g2dlite_cwrite(dev, cmdid, G2D_RE200(i), path_val[i]);
}
/*We bypass alpha blend for output alpha.If we input 3 layers(2 layers
for porter-duff, 1 layer for alpha blend with porter-duff output, we
must clear this bit. G2DLite W-pipe output set 0xFF to alpha value.
*/
val = g2dlite_read(base, G2D_RE220);
if (ins->pd_info.alpha_need)
val = reg_value(1, val, G2D_SHIFT00_RE220, G2D_MASK00_RE220);
else
val = reg_value(0, val, G2D_SHIFT00_RE220, G2D_MASK00_RE220);
g2dlite_cwrite(dev, cmdid, G2D_RE220, val);
} else {
val = g2dlite_read(base, G2D_RE220);
val = reg_value(0, val, G2D_SHIFT00_RE220, G2D_MASK00_RE220);
g2dlite_cwrite(dev, cmdid, G2D_RE220, val);
}
return 0;
}
static int g2dlite_wpipe_set(struct g2dlite_device *dev, char cmdid,
struct g2dlite_output_cfg *output)
{
unsigned int val;
unsigned char nplanes;
unsigned char bpp[3] = {0};
unsigned long input_addr;
if (!cmdid) {
g2dlite_wpipe_pixcomp_set(dev, output);
g2dlite_wp_csc_set(dev, output, G2DLITE_FUN_BLEND);
}
val = reg_value(output->height - 1, 0, G2D_SHIFT16_RA00C,
G2D_MASK16_RA00C);
val = reg_value(output->width - 1, val, G2D_SHIFT00_RA00C,
G2D_MASK00_RA00C);
g2dlite_cwrite(dev, cmdid, G2D_RA00C, val);
nplanes = COLOR_GET_PLANE_COUNT(output->fmt);
get_bpp_by_format(output->fmt, bpp);
input_addr = output->addr[0];
g2dlite_cwrite(dev, cmdid, G2D_RH010, get_l_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RH014, get_h_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RH028, output->stride[0] - 1);
if (nplanes > 1) {
input_addr = output->addr[1];
g2dlite_cwrite(dev, cmdid, G2D_RH018, get_l_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RH01C, get_h_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RH02C, output->stride[1] - 1);
}
if (nplanes > 2) {
input_addr = output->addr[2];
g2dlite_cwrite(dev, cmdid, G2D_RH020, get_l_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RH024, get_h_addr(input_addr));
g2dlite_cwrite(dev, cmdid, G2D_RH030, output->stride[2] - 1);
}
return 0;
}
static void g2dlite_slice_input(struct g2dlite_input_cfg *src,
struct g2dlite_input_cfg *slice_input,
unsigned int slice_w,
unsigned char max_slice_num,
unsigned char slice_idx)
{
unsigned int slice_width;
unsigned long src_addr;
unsigned char nplanes;
unsigned char bpp[3] = {0};
/* copy */
if (!slice_idx) {
slice_input->layer = src->layer;
slice_input->layer_en = src->layer_en;
slice_input->fmt = src->fmt;
slice_input->zorder = src->zorder;
slice_input->src.x = src->src.x;
slice_input->src.y = src->src.y;
slice_input->src.h = src->src.h;
slice_input->dst.x = src->dst.x;
slice_input->dst.y = src->dst.y;
slice_input->dst.h = src->dst.h;
slice_input->ckey.en = src->ckey.en;
slice_input->ckey = src->ckey;
slice_input->blend = src->blend;
slice_input->alpha = src->alpha;
slice_input->src_stride[0] = src->src_stride[0];
slice_input->src_stride[1] = src->src_stride[1];
slice_input->src_stride[2] = src->src_stride[2];
slice_input->src_stride[3] = src->src_stride[3];
}
/*change to slice*/
nplanes = COLOR_GET_PLANE_COUNT(src->fmt);
get_bpp_by_format(src->fmt, bpp);
slice_width =
(slice_idx == (max_slice_num - 1))
? ((src->dst.w % slice_w) ? (src->dst.w % slice_w) : slice_w)
: slice_w;
slice_input->src.w = slice_width;
slice_input->dst.w = slice_width;
src_addr = src->addr[0] + slice_idx * slice_w * bpp[0] / 8;
slice_input->addr[0] = src_addr;
slice_input->src_stride[0] = src->src_stride[0];
if (nplanes > 1) {
src_addr = src->addr[1] + slice_idx * slice_w * bpp[1] / 8;
slice_input->addr[1] = src_addr;
}
if (nplanes > 2) {
src_addr = src->addr[2] + slice_idx * slice_w * bpp[2] / 8;
slice_input->addr[2] = src_addr;
}
}
static void g2dlite_slice_output(struct g2dlite_output_cfg *src,
struct g2dlite_output_cfg *slice_output,
unsigned int slice_w,
unsigned char max_slice_num,
unsigned char slice_idx)
{
unsigned int slice_width;
unsigned char nplanes;
unsigned char bpp[3] = {0};
if (!slice_idx) {
slice_output->height = src->height;
slice_output->fmt = src->fmt;
slice_output->stride[0] = src->stride[0];
slice_output->stride[1] = src->stride[1];
slice_output->stride[2] = src->stride[2];
slice_output->stride[3] = src->stride[3];
slice_output->rotation = src->rotation;
}
nplanes = COLOR_GET_PLANE_COUNT(src->fmt);
get_bpp_by_format(src->fmt, bpp);
slice_width =
(slice_idx == (max_slice_num - 1))
? ((src->width % slice_w) ? (src->width % slice_w) : slice_w)
: slice_w;
slice_output->width = slice_width;
switch (src->rotation) {
case ROTATION_TYPE_NONE:
case ROTATION_TYPE_VFLIP:
slice_output->addr[0] = src->addr[0] + slice_idx * slice_w * bpp[0] / 8;
if (nplanes > 1) {
slice_output->addr[1] =
src->addr[1] + slice_idx * slice_w * bpp[1] / 8;
}
if (nplanes > 2) {
slice_output->addr[2] =
src->addr[2] + slice_idx * slice_w * bpp[2] / 8;
}
break;
case ROTATION_TYPE_ROT_90:
case ROTATION_TYPE_HF_90:
slice_output->addr[0] =
src->addr[0] + slice_idx * slice_w * src->stride[0];
if (nplanes > 1) {
slice_output->addr[1] =
src->addr[1] + slice_idx * slice_w * src->stride[1];
}
if (nplanes > 2) {
slice_output->addr[2] =
src->addr[2] + slice_idx * slice_w * src->stride[2];
}
break;
case ROTATION_TYPE_HFLIP:
case ROTATION_TYPE_ROT_180:
slice_output->addr[0] =
src->addr[0] +
(src->width - (slice_idx * slice_w + slice_width)) * bpp[0] / 8;
if (nplanes > 1) {
slice_output->addr[1] =
src->addr[1] +
(src->width - (slice_idx * slice_w + slice_width)) * bpp[1] / 8;
}
if (nplanes > 2) {
slice_output->addr[2] =
src->addr[2] +
(src->width - (slice_idx * slice_w + slice_width)) * bpp[2] / 8;
}
break;
case ROTATION_TYPE_ROT_270:
case ROTATION_TYPE_VF_90:
slice_output->addr[0] =
src->addr[0] +
(src->width - (slice_idx * slice_w + slice_width)) * src->stride[0];
if (nplanes > 1) {
slice_output->addr[1] =
src->addr[1] +
(src->width - (slice_idx * slice_w + slice_width)) *
src->stride[1];
}
if (nplanes > 2) {
slice_output->addr[2] =
src->addr[2] +
(src->width - (slice_idx * slice_w + slice_width)) *
src->stride[2];
}
break;
default:
break;
}
}
static int g2dlite_rotation(struct g2dlite_device *dev,
struct g2dlite_input *ins)
{
const unsigned int slice_w = 256;
unsigned int slice_count;
struct g2dlite_input slice_ins;
memset(&slice_ins, 0, sizeof(struct g2dlite_input));
struct g2dlite_input_cfg *input = &slice_ins.layer[0];
struct g2dlite_output_cfg *output = &slice_ins.output;
if (!dev || !ins) {
G2DLITE_LOG_ERR("dev or input isn't inited.[dev:%p, ins:%p]", dev, ins);
return -1;
}
u8 r_idx = get_r_idx(ins);
u8 w_idx = get_w_idx(&ins->output);
g2dlite_rwdma_set(dev, r_idx, w_idx);
g2dlite_close_fastcopy(dev);
slice_count = (ins->layer[0].dst.w / slice_w) +
((ins->layer[0].dst.w % slice_w) ? 1 : 0);
for (unsigned int i = 0; i < slice_count; i++) {
G2DLITE_LOG_INFO("slice[%d|%d]", i, slice_count);
g2dlite_slice_input(&ins->layer[0], input, slice_w, slice_count, i);
g2dlite_gpipe_set(dev, i, input);
g2dlite_mlc_set(dev, i, &slice_ins);
g2dlite_slice_output(&ins->output, output, slice_w, slice_count, i);
g2dlite_wpipe_set(dev, i, output);
}
return 0;
}
static int g2dlite_bg_set(struct g2dlite_device *dev,
struct g2dlite_bg_cfg *bgcfg,
struct g2dlite_output_cfg *output,
u8 bypass_alpha_blending)
{
u32 val, a_addr_l, a_addr_h, a_stride;
unsigned long base = dev->reg_base;
unsigned long a_addr;
u8 alpha_select = 0;
if (bgcfg->aaddr) {
a_addr = bgcfg->aaddr;
a_addr_l = get_l_addr(a_addr);
a_addr_h = get_h_addr(a_addr);
a_stride = bgcfg->astride;
alpha_select = 1;
if (!a_stride)
a_stride = (output->width * bgcfg->bpa + 7) / 8 - 1;
/*AP_PIX_COMP*/
val = g2dlite_read(base, G2D_RF000);
val = reg_value(bgcfg->bpa, val, G2D_SHIFT00_RF000,
G2D_MASK00_RF000);
g2dlite_cwrite(dev, 0, G2D_RF000, val);
/*AP_FRM_SIZE*/
val = reg_value(output->height - 1, 0, G2D_SHIFT16_RF008,
G2D_MASK16_RF008);
val = reg_value(output->width - 1, val, G2D_SHIFT00_RF008,
G2D_MASK00_RF008);
g2dlite_cwrite(dev, 0, G2D_RF008, val);
/*AP_BADDR_L*/
val = reg_value(a_addr_l, 0, G2D_SHIFT00_RF00C, G2D_MASK00_RF00C);
g2dlite_cwrite(dev, 0, G2D_RF00C, val);
/*AP_BADDR_H*/
val = reg_value(a_addr_h, 0, G2D_SHIFT00_RF010, G2D_MASK00_RF010);
g2dlite_cwrite(dev, 0, G2D_RF010, val);
/*AP_STRIDE*/
val = reg_value(a_stride - 1, 0, G2D_SHIFT00_RF02C, G2D_MASK00_RF02C);
g2dlite_cwrite(dev, 0, G2D_RF02C, val);
}
/*G2D_RE220*/
val = g2dlite_read(base, G2D_RE220);
val = reg_value(bgcfg->g_alpha, val, G2D_SHIFT08_RE220, G2D_MASK08_RE220);
val = reg_value(alpha_select, val, G2D_SHIFT02_RE220, G2D_MASK02_RE220);
val = reg_value(1, val, G2D_SHIFT01_RE220, G2D_MASK01_RE220);
val = reg_value(bypass_alpha_blending, val,
G2D_SHIFT00_RE220, G2D_MASK00_RE220);
g2dlite_write(base, G2D_RE220, val);
/*G2D_RE224*/
g2dlite_cwrite(dev, 0, G2D_RE224, bgcfg->color);
return 0;
}
static int g2dlite_fill_rect(struct g2dlite_device *dev,
struct g2dlite_bg_cfg *bgcfg,
struct g2dlite_output_cfg *output)
{
int i = 0;
u32 val;
u64 base = dev->reg_base;
u8 w_idx = get_w_idx(output);
g2dlite_rwdma_set(dev, 0, w_idx);
g2dlite_close_fastcopy(dev);
/*disable all layers*/
for (i = 0; i < G2DLITE_MLC_MAX; i++) {
val = g2dlite_read(base, G2D_RE000(i));
val = reg_value(0, val, G2D_SHIFT00_RE000, G2D_MASK00_RE000);
g2dlite_cwrite(dev, 0, G2D_RE000(i), val);
}
/*disable all layer's paths*/
for (i = 1; i < MLC_PATH_MAX; i++) {
g2dlite_cwrite(dev, 0, G2D_RE200(i), 0xF777F);
}
g2dlite_cwrite(dev, 0, G2D_RE200(0), 0x07770);
g2dlite_bg_set(dev, bgcfg, output, 1);
g2dlite_wpipe_set(dev, 0, output);
return 0;
}
static int g2dlite_fastcopy(struct g2dlite_device *dev, struct fcopy_t *in,
struct fcopy_t *out)
{
u32 val, i_addr_l, i_addr_h, o_addr_l, o_addr_h;
unsigned long base = dev->reg_base;
unsigned long i_addr, o_addr;
i_addr = in->addr;
i_addr_l = get_l_addr(i_addr);
i_addr_h = get_h_addr(i_addr);
o_addr = out->addr;
o_addr_l = get_l_addr(o_addr);
o_addr_h = get_h_addr(o_addr);
g2dlite_rwdma_set(dev, 0, 0);
/*AP_FRM_CTRL*/
val = g2dlite_read(base, G2D_RF004);
val = reg_value(1, val, G2D_SHIFT00_RF004,
G2D_MASK00_RF004);
g2dlite_cwrite(dev, 0, G2D_RF004, val);
/*AP_FRM_SIZE*/
val = reg_value(in->height - 1, 0, G2D_SHIFT16_RF008,
G2D_MASK16_RF008);
val = reg_value(in->width - 1, val, G2D_SHIFT00_RF008,
G2D_MASK00_RF008);
g2dlite_cwrite(dev, 0, G2D_RF008, val);
/*AP_BADDR_L*/
val = reg_value(i_addr_l, 0, G2D_SHIFT00_RF00C, G2D_MASK00_RF00C);
g2dlite_cwrite(dev, 0, G2D_RF00C, val);
/*AP_BADDR_H*/
val = reg_value(i_addr_h, 0, G2D_SHIFT00_RF010, G2D_MASK00_RF010);
g2dlite_cwrite(dev, 0, G2D_RF010, val);
/*AP_STRIDE*/
val = reg_value(in->stride - 1, 0, G2D_SHIFT00_RF02C, G2D_MASK00_RF02C);
g2dlite_cwrite(dev, 0, G2D_RF02C, val);
/*Config W-pipe*/
val = reg_value(out->height - 1, 0, G2D_SHIFT16_RA00C,
G2D_MASK16_RA00C);
val = reg_value(out->width - 1, val, G2D_SHIFT00_RA00C,
G2D_MASK00_RA00C);
g2dlite_cwrite(dev, 0, G2D_RA00C, val);
g2dlite_cwrite(dev, 0, G2D_RH010, o_addr_l);
g2dlite_cwrite(dev, 0, G2D_RH014, o_addr_h);
g2dlite_cwrite(dev, 0, G2D_RH028, out->stride - 1);
return 0;
}
static int g2dlite_update(struct g2dlite_device *dev, struct g2dlite_input *ins)
{
if (!dev || !ins) {
G2DLITE_LOG_ERR("dev or input isn't inited.[dev:%p, ins:%p]", dev, ins);
return -1;
}
u8 r_idx = get_r_idx(ins);
u8 w_idx = get_w_idx(&ins->output);
g2dlite_rwdma_set(dev, r_idx, w_idx);
g2dlite_close_fastcopy(dev);
if (ins->bg_layer.en)
g2dlite_bg_set(dev, &ins->bg_layer, &ins->output, 0);
for (unsigned int i = 0; i < ins->layer_num; i++) {
if (ins->layer[i].layer == G2DLITE_TYPE_SPIPE) {
g2dlite_spipe_set(dev, 0, &ins->layer[i]);
} else {
g2dlite_gpipe_set(dev, 0, &ins->layer[i]);
}
}
g2dlite_mlc_set(dev, 0, ins);
g2dlite_wpipe_set(dev, 0, &ins->output);
return 0;
}
static int g2dlite_clut_index_set(struct g2dlite_device *dev, char *clut_src)
{
u32 value;
u32 offset = 0;
u64 base = dev->reg_base;
u32 size = (G2DLITE_CLUT_EADDR - G2DLITE_CLUT_SADDR + 1) / 4;
for (u32 i = 0; i < size; i++, offset += 4) {
value = (clut_src[offset + 3] << 24) | (clut_src[offset + 2] << 16) |
(clut_src[offset + 1] << 8) | (clut_src[offset]);
g2dlite_write(base, G2DLITE_CLUT_SADDR, value);
}
return 0;
}
static int g2dlite_enable(struct g2dlite_device *dev)
{
int i = 0;
unsigned int val;
unsigned long base = dev->reg_base;
unsigned char valid_count = 0;
cmdfile_info *cmd;
unsigned long input_addr;
if (dev->write_mode == G2DLITE_CMD_WRITE) {
for (i = 0; i < G2DLITE_CMDFILE_MAX_NUM; i++) {
cmd = &dev->cmd_info[i];
if (!cmd->dirty) {
valid_count = i;
break;
} else {
cmd->dirty = 0;
}
}
G2DLITE_LOG_INFO("valid_count = %d", valid_count);
for (i = 0; i < valid_count; i++) {
cmd = &dev->cmd_info[i];
if (i < valid_count - 1) {
input_addr = (paddr_t)dev->cmd_info[i + 1].arg;
G2DLITE_LOG_INFO("input_addr = 0x%lx", input_addr);
cmd->arg[cmd->len++] = G2D_RA010;
cmd->arg[cmd->len++] = get_l_addr(input_addr);
cmd->arg[cmd->len++] = G2D_RA014;
cmd->arg[cmd->len++] = get_h_addr(input_addr);
cmd->arg[cmd->len++] = G2D_RA018;
cmd->len++;
} else {
cmd->arg[cmd->len++] = G2D_RA01C;
cmd->arg[cmd->len++] = 0;
G2DLITE_LOG_INFO("G2DLITE_CMDFILE_CFG = %d",
G2D_RA01C);
}
}
for (i = 0; i < valid_count - 1; i++) {
cmd = &dev->cmd_info[i];
cmd->arg[cmd->len - 1] = dev->cmd_info[i + 1].len / 2 - 1;
G2DLITE_LOG_INFO("dev->cmd_info[%d].len / 2 - 1 = 0x%x", i + 1,
dev->cmd_info[i + 1].len / 2 - 1);
}
for (i = 0; i < valid_count; i++) {
cmd = &dev->cmd_info[i];
arch_clean_cache_range((addr_t)cmd->arg, cmd->len * 4);
}
input_addr = (paddr_t)dev->cmd_info[0].arg;
g2dlite_write(base, G2D_RA010, get_l_addr(input_addr));
g2dlite_write(base, G2D_RA014, get_h_addr(input_addr));
g2dlite_write(base, G2D_RA018,
dev->cmd_info[0].len / 2 - 1);
val = g2dlite_read(base, G2D_RA01C);
val = reg_value(1, val, G2D_SHIFT03_RA01C,
G2D_MASK03_RA01C);
g2dlite_write(base, G2D_RA01C, val);
for (i = 0; i < valid_count; i++) {
dev->cmd_info[i].len = 0;
}
}
val = g2dlite_read(base, G2D_RA000);
val = reg_value(1, val, G2D_SHIFT00_RA000, G2D_MASK00_RA000);
g2dlite_write(base, G2D_RA000, val);
dev->status = G2DLITE_WORKING;
return 0;
}
static int g2dlite_irq_handler(u32 irq, void *arg)
{
unsigned int value;
struct g2dlite_device *dev = (struct g2dlite_device *)arg;
unsigned long base = dev->reg_base;
value = g2dlite_read(base, G2D_RA024);
g2dlite_write(base, G2D_RA024, value);
if (value & G2D_MASK06_RA020) {
dev->status = G2DLITE_DONE;
#if CONFIG_OS_FREERTOS
BaseType_t taskwoken;
xSemaphoreGiveFromISR(done_sema, &taskwoken);
#endif
if (dev->done_callback)
dev->done_callback();
}
return 0;
}
static int g2dlite_check_status(struct g2dlite_device *dev)
{
return dev->status;
}
const struct g2dlite_ops ops = {
.init = g2dlite_init,
.reset = g2dlite_reset,
.clut_index_set = g2dlite_clut_index_set,
.update = g2dlite_update,
.rotation = g2dlite_rotation,
.fill_rect = g2dlite_fill_rect,
.fastcopy = g2dlite_fastcopy,
.enable = g2dlite_enable,
.irq_handler = g2dlite_irq_handler,
.check_status = g2dlite_check_status,
};