MAX_CARLINK_A270S/MXC_A27-PCB4.5-270T/ArkmicroFiles/libcpu-amt630hv100/source/blend2d.c

466 lines
14 KiB
C

#include <string.h>
#include "FreeRTOS.h"
#include "chip.h"
#include "board.h"
#include "lcd.h"
#include "blend2d.h"
#include "ff_stdio.h"
#define REGS_BLEND2D REGS_BLEND2D_BASE
/* BLEND2D MODULE */
#define BLEND2D_ENABLE 0x000
#define BLEND2D_START 0x004
#define BLEND2D_CTL_ENABLE 0x008
#define BLEND2D_MODE 0x00C
#define BLEND2D_WRITE_WAIT 0x010
#define BLEND2D_LAYER1_BURST_CTL 0x020
#define BLEND2D_LAYER1_CTL 0x024
#define BLEND2D_LAYER1_SIZE 0x028
#define BLEND2D_LAYER1_ADDR 0x02C
#define BLEND2D_LAYER2_BURST_CTL 0x030
#define BLEND2D_LAYER2_CTL 0x034
#define BLEND2D_LAYER2_SIZE 0x038
#define BLEND2D_LAYER2_ADDR 0x03C
#define BLEND2D_COLOR_KEY_MASK_THLD_LAYER1 0x040
#define BLEND2D_COLOR_KEY_MASK_THLD_LAYER2 0x044
#define BLEND2D_COLOR_KEY_MASK_VALUE_LAYER1 0x048
#define BLEND2D_COLOR_KEY_MASK_VALUE_LAYER2 0x04C
#define BLEND2D_LAYER1_WINDOW_POINT 0x050
#define BLEND2D_LAYER2_WINDOW_POINT 0x054
#define BLEND2D_LAYER1_SOURCE_SIZE 0x058
#define BLEND2D_LAYER2_SOURCE_SIZE 0x05C
#define BLEND2D_WRITE_BACK_SOURCE_SIZE 0x060
#define BLEND2D_BLD_SIZE 0x064
#define BLEND2D_BLD_WINDOW_POINT 0x068
#define BLEND2D_BLD_ADDR 0x06C
#define BLEND2D_BLD_CTL 0x070
#define BLEND2D_LAYER1_BACK_COLOR 0x074
#define BLEND2D_LAYER2_BACK_COLOR 0x078
#define BLEND2D_INT_CTL 0x080
#define BLEND2D_INT_CLR 0x084
#define BLEND2D_INT_STA 0x088
void blend2d_start(void)
{
writel(1, REGS_BLEND2D + BLEND2D_START);
udelay(10);
writel(0, REGS_BLEND2D + BLEND2D_START);
}
void blend2d_clear_int(void)
{
writel(0, REGS_BLEND2D + BLEND2D_INT_CLR);
}
void blend2d_read_wait_enable(int enable, unsigned int wait_time)
{
unsigned int reg;
reg = readl(REGS_BLEND2D + BLEND2D_MODE);
reg &= ~((0xffff << 16) | (1 <<5));
wait_time &= 0xffff;
if(enable)
reg |= (wait_time << 16) | (1 << 5);
writel(reg, REGS_BLEND2D + BLEND2D_MODE);
}
void blend2d_write_wait_enable(unsigned int enable, unsigned int wait_time)
{
unsigned int reg;
reg = readl(REGS_BLEND2D + BLEND2D_WRITE_WAIT);
reg &= ~((1 << 12) | 0xfff);
wait_time &= 0xfff;
if(enable)
reg |= (1 << 12) | wait_time;
writel(reg, REGS_BLEND2D + BLEND2D_WRITE_WAIT);
}
void blend2d_layer_enable(int layer, int enable)
{
unsigned int reg = readl(REGS_BLEND2D + BLEND2D_CTL_ENABLE);
if (layer == BLEND2D_LAYER1) {
if (enable)
reg |= 1;
else
reg &= ~1;
} else if (layer == BLEND2D_LAYER2) {
if (enable)
reg |= 1 << 1;
else
reg &= ~(1 << 1);
}
writel(reg, REGS_BLEND2D + BLEND2D_CTL_ENABLE);
}
void blend2d_set_layer_point(int layer, int x, int y)
{
x &= 0xfff;
y &= 0xfff;
if (layer == BLEND2D_LAYER1)
writel((y << 12) | x, REGS_BLEND2D + BLEND2D_LAYER1_WINDOW_POINT);
else if (layer == BLEND2D_LAYER2)
writel((y << 12) | x, REGS_BLEND2D + BLEND2D_LAYER2_WINDOW_POINT);
}
void blend2d_set_layer_size(int layer, int width, int height)
{
width &= 0xfff;
height &= 0xfff;
if (layer == BLEND2D_LAYER1)
writel((height << 12) | width, REGS_BLEND2D + BLEND2D_LAYER1_SIZE);
else if (layer == BLEND2D_LAYER2)
writel((height << 12) | width, REGS_BLEND2D + BLEND2D_LAYER2_SIZE);
}
void blend2d_set_layer_source_size(int layer, int width, int height)
{
width &= 0xfff;
height &= 0xfff;
if (layer == BLEND2D_LAYER1)
writel((height << 12) | width, REGS_BLEND2D + BLEND2D_LAYER1_SOURCE_SIZE);
else if (layer == BLEND2D_LAYER2)
writel((height << 12) | width, REGS_BLEND2D + BLEND2D_LAYER2_SOURCE_SIZE);
}
void blend2d_set_layer_addr(int layer, unsigned int addr)
{
if (layer == BLEND2D_LAYER1)
writel(addr, REGS_BLEND2D + BLEND2D_LAYER1_ADDR);
else if (layer == BLEND2D_LAYER2)
writel(addr, REGS_BLEND2D + BLEND2D_LAYER2_ADDR);
}
void blend2d_set_layer_format(int layer, int format, int rgb_order)
{
format &= 0xf;
rgb_order &= 0x7;
if (layer == BLEND2D_LAYER1)
writel(rgb_order << 4 | format, REGS_BLEND2D + BLEND2D_LAYER1_CTL);
else if (layer == BLEND2D_LAYER2)
writel(rgb_order << 4 | format, REGS_BLEND2D + BLEND2D_LAYER2_CTL);
}
void blend2d_set_layer_alpha_mode(int layer, int mode)
{
unsigned int reg;
if (layer == BLEND2D_LAYER1) {
reg = readl(REGS_BLEND2D + BLEND2D_LAYER1_BURST_CTL);
if (mode == BLEND2D_ALPHA_DATA)
reg &= ~(1 << 15);
else if (mode == BLEND2D_ALPHA_REG)
reg |= 1 << 15;
writel(reg, REGS_BLEND2D + BLEND2D_LAYER1_BURST_CTL);
} else if (layer == BLEND2D_LAYER2) {
reg = readl(REGS_BLEND2D + BLEND2D_LAYER2_BURST_CTL);
if (mode == BLEND2D_ALPHA_DATA)
reg &= ~(1 << 15);
else if (mode == BLEND2D_ALPHA_REG)
reg |= 1 << 15;
writel(reg, REGS_BLEND2D + BLEND2D_LAYER2_BURST_CTL);
}
}
void blend2d_set_layer_alpha(int layer, uint8_t alpha)
{
unsigned int reg;
if (layer == BLEND2D_LAYER1) {
reg = readl(REGS_BLEND2D + BLEND2D_LAYER1_BURST_CTL);
reg &= ~(0xf << 16);
reg |= alpha << 16;
writel(reg, REGS_BLEND2D + BLEND2D_LAYER1_BURST_CTL);
} else if (layer == BLEND2D_LAYER2) {
reg = readl(REGS_BLEND2D + BLEND2D_LAYER2_BURST_CTL);
reg &= ~(0xf << 16);
reg |= alpha << 16;
writel(reg, REGS_BLEND2D + BLEND2D_LAYER2_BURST_CTL);
}
}
void blend2d_set_layer_colorkey(int layer, int enable, uint8_t r, uint8_t g, uint8_t b)
{
unsigned int reg;
if (layer == BLEND2D_LAYER1) {
reg = readl(REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER1);
reg &= ~0x1ffffff;
reg |= (r << 16) | (g << 8) | b;
if (enable)
reg |= 1 << 24;
writel(reg, REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER1);
} else if (layer == BLEND2D_LAYER2) {
reg = readl(REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER2);
reg &= ~0x1ffffff;
reg |= (r << 16) | (g << 8) | b;
if (enable)
reg |= 1 << 24;
writel(reg, REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER2);
}
}
void blend2d_set_layer_colorkey_thld(int layer, uint8_t r, uint8_t g, uint8_t b)
{
if (layer == BLEND2D_LAYER1)
writel((r << 16) | (g << 8) | b, REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_THLD_LAYER1);
else if (layer == BLEND2D_LAYER2)
writel((r << 16) | (g << 8) | b, REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_THLD_LAYER2);
}
void blend2d_set_layer_colorkey_backcolor(int layer, int enable, uint8_t r, uint8_t g, uint8_t b)
{
unsigned int reg;
if (layer == BLEND2D_LAYER1) {
reg = readl(REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER1);
if (enable)
reg |= 1 << 25;
else
reg &= ~(1 << 25);
writel(reg, REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER1);
writel((r << 16) | (g << 8) | b, REGS_BLEND2D + BLEND2D_LAYER1_BACK_COLOR);
} else if (layer == BLEND2D_LAYER2) {
reg = readl(REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER2);
if (enable)
reg |= 1 << 25;
else
reg &= ~(1 << 25);
writel(reg, REGS_BLEND2D + BLEND2D_COLOR_KEY_MASK_VALUE_LAYER2);
writel((r << 16) | (g << 8) | b, REGS_BLEND2D + BLEND2D_LAYER2_BACK_COLOR);
}
}
void blend2d_set_blend_point(int x, int y)
{
x &= 0xfff;
y &= 0xfff;
writel((y << 12) | x, REGS_BLEND2D + BLEND2D_BLD_WINDOW_POINT);
}
void blend2d_set_blend_source_size(int width, int height)
{
width &= 0xfff;
height &= 0xfff;
writel((height << 12) | width, REGS_BLEND2D + BLEND2D_WRITE_BACK_SOURCE_SIZE);
}
void blend2d_set_blend_size(int width, int height)
{
width &= 0xfff;
height &= 0xfff;
writel((height << 12) | width, REGS_BLEND2D + BLEND2D_BLD_SIZE);
}
void blend2d_set_blend_mode(int mode)
{
unsigned int reg = readl(REGS_BLEND2D + BLEND2D_MODE);
reg &= ~((0xf << 8) | 0x1);
reg |= (mode << 8) | (0x1 << 4);
writel(reg, REGS_BLEND2D + BLEND2D_MODE);
}
void blend2d_set_blend_addr(uint32_t addr)
{
writel(addr, REGS_BLEND2D + BLEND2D_BLD_ADDR);
}
void blend2d_set_blend_format(int format)
{
unsigned int reg = readl(REGS_BLEND2D + BLEND2D_BLD_CTL);
format &= 0xf;
reg &= ~0xf;
reg |= format;
writel(reg, REGS_BLEND2D + BLEND2D_BLD_CTL);
}
void blend2d_set_blend_endian(int endian)
{
unsigned int reg = readl(REGS_BLEND2D + BLEND2D_BLD_CTL);
if (endian == BLEND2D_ARGB)
reg |= 1 << 4;
else if (endian == BLEND2D_RGBA)
reg &= ~(1 << 4);
writel(reg, REGS_BLEND2D + BLEND2D_BLD_CTL);
}
void blend2d_set_blend_alpha(uint8_t alpha)
{
unsigned int reg = readl(REGS_BLEND2D + BLEND2D_BLD_CTL);
reg &= ~(0xff << 24);
reg |= alpha << 24;
writel(reg, REGS_BLEND2D + BLEND2D_BLD_CTL);
}
void blend2d_set_blend_alpha_mode(int mode)
{
unsigned int reg = readl(REGS_BLEND2D + BLEND2D_BLD_CTL);
mode &= 3;
reg &= ~((0x1ff << 8) | (3 << 5));
reg |= (256 << 8) | (mode << 5);
writel(reg, REGS_BLEND2D + BLEND2D_BLD_CTL);
}
void blend2d_fill(uint32_t address, int xpos, int ypos, int width, int height, int source_width, int source_height,
uint8_t cr, uint8_t cg, uint8_t cb, int format, uint8_t opa, int alpha_byte)
{
/* printf("addr 0x%x, %d,%d,%d,%d-%d,%d r=%d, g=%d, b=%d, format=%d, opa=0x%x.\n",
address, xpos, ypos, width, height, source_width, source_height, cr, cg, cb, format, opa); */
blend2d_set_layer_format(BLEND2D_LAYER2, format & 0xf, (format >> 8) & 0xf);
blend2d_set_layer_addr(BLEND2D_LAYER2, address);
blend2d_set_layer_point(BLEND2D_LAYER2, 0, 0);
blend2d_set_layer_size(BLEND2D_LAYER2, width, height);
blend2d_set_layer_source_size(BLEND2D_LAYER2, width, height);
blend2d_set_layer_colorkey(BLEND2D_LAYER2, 1, 0, 0, 0);
blend2d_set_layer_colorkey_thld(BLEND2D_LAYER2, 0xff, 0xff, 0xff);
blend2d_set_layer_colorkey_backcolor(BLEND2D_LAYER2, 1, cr, cg, cb);
blend2d_set_layer_alpha(BLEND2D_LAYER2, opa);
blend2d_set_layer_alpha_mode(BLEND2D_LAYER2, BLEND2D_ALPHA_REG);
blend2d_layer_enable(BLEND2D_LAYER2, 1);
blend2d_set_layer_format(BLEND2D_LAYER1, format & 0xf, (format >> 8) & 0xf);
blend2d_set_layer_addr(BLEND2D_LAYER1, address);
blend2d_set_layer_point(BLEND2D_LAYER1, 0, 0);
blend2d_set_layer_size(BLEND2D_LAYER1, width, height);
blend2d_set_layer_source_size(BLEND2D_LAYER1, source_width, source_height);
blend2d_layer_enable(BLEND2D_LAYER1, 1);
blend2d_set_blend_format(format & 0xf);
blend2d_set_blend_addr(address);
blend2d_set_blend_point(xpos, ypos);
blend2d_set_blend_size(width, height);
blend2d_set_blend_source_size(source_width, source_height);
blend2d_set_blend_mode(BLEND2D_MIX_BLEND);
blend2d_set_blend_endian(BLEND2D_ARGB);
blend2d_set_blend_alpha(0xff);
if (alpha_byte)
blend2d_set_blend_alpha_mode(BLEND2D_ALPHA_LAYER2);
else
blend2d_set_blend_alpha_mode(BLEND2D_ALPHA_BLEND_REG);
blend2d_read_wait_enable(1, 0x3f);
}
void blend2d_blit(uint32_t dst_addr, int dst_w, int dst_h, int dst_x, int dst_y, int dst_format, int width, int height,
uint32_t src_addr, int src_w, int src_h, int src_x, int src_y, int src_format, uint8_t opa, int alpha_byte)
{
/* printf("dst 0x%x,%dx%d-%d,%d %dx%d src 0x%x,%dx%d-%d,%d, src_format=%d, opa=0x%x, alpha_byte=%d.\n",
dst_addr, dst_w, dst_h, dst_x, dst_y, width, height,
src_addr, src_w, src_h, src_x, src_y, src_format, opa, alpha_byte); */
blend2d_set_layer_format(BLEND2D_LAYER2, src_format & 0xf, (src_format >> 8) & 0xf);
blend2d_set_layer_addr(BLEND2D_LAYER2, src_addr);
blend2d_set_layer_point(BLEND2D_LAYER2, src_x, src_y);
blend2d_set_layer_size(BLEND2D_LAYER2, width, height);
blend2d_set_layer_source_size(BLEND2D_LAYER2, src_w, src_h);
blend2d_set_layer_colorkey(BLEND2D_LAYER2, 0, 0, 0, 0);
blend2d_set_layer_alpha(BLEND2D_LAYER2, opa);
if (alpha_byte)
blend2d_set_layer_alpha_mode(BLEND2D_LAYER2, BLEND2D_ALPHA_DATA);
else
blend2d_set_layer_alpha_mode(BLEND2D_LAYER2, BLEND2D_ALPHA_REG);
blend2d_layer_enable(BLEND2D_LAYER2, 1);
blend2d_set_layer_format(BLEND2D_LAYER1, dst_format & 0xf, (dst_format >> 8) & 0xf);
blend2d_set_layer_addr(BLEND2D_LAYER1, dst_addr);
blend2d_set_layer_point(BLEND2D_LAYER1, dst_x, dst_y);
blend2d_set_layer_size(BLEND2D_LAYER1, width, height);
blend2d_set_layer_source_size(BLEND2D_LAYER1, dst_w, dst_h);
blend2d_layer_enable(BLEND2D_LAYER1, 1);
blend2d_set_blend_format(dst_format & 0xf);
blend2d_set_blend_addr(dst_addr);
blend2d_set_blend_point(dst_x, dst_y);
blend2d_set_blend_size(width, height);
blend2d_set_blend_source_size(dst_w, dst_h);
blend2d_set_blend_mode(BLEND2D_MIX_BLEND);
blend2d_set_blend_endian(BLEND2D_ARGB);
//blend2d_set_blend_alpha(0xff);
if (alpha_byte)
blend2d_set_blend_alpha_mode(BLEND2D_ALPHA_LAYER1);
else
blend2d_set_blend_alpha_mode(BLEND2D_ALPHA_LAYER2);
blend2d_read_wait_enable(1, 0x3f);
}
static void blend2d_fill_test(void)
{
unsigned char *buf = pvPortMalloc(1024*600*4);
memset(buf, 0, 1024*600*4);
CP15_clean_dcache_for_dma((uint32_t)buf, (uint32_t)buf + 1024*600*4);
ark_lcd_set_osd_yaddr(LCD_OSD1, (uint32_t)buf);
ark_lcd_set_osd_sync(LCD_OSD1);
blend2d_fill((uint32_t)buf, 0, 0, 1024, 600, 1024, 600, 0xff, 0, 0, BLEND2D_FORAMT_ARGB888, 0x20, 0);
blend2d_run();
}
static void blend2d_demo_thread(void *param)
{
blend2d_fill_test();
vTaskDelay(portMAX_DELAY);
}
int blend2d_demo(void)
{
/* Create a task to play animation */
if (xTaskCreate(blend2d_demo_thread, "axiblendemo", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES / 3, NULL) != pdPASS) {
printf("create axiblend demo task fail.\n");
return -1;
}
vTaskDelay(portMAX_DELAY);
return 0;
}
static QueueHandle_t blend2d_done;
static void blend2d_int_handler(void *para)
{
unsigned int status;
status = readl(REGS_BLEND2D + BLEND2D_INT_STA);
blend2d_clear_int();
if(status & 0x2) {
printf("blend2d err int 0x%x.\n", status);
}
xQueueSendFromISR(blend2d_done, NULL, 0);
}
int blend2d_init(void)
{
blend2d_done = xQueueCreate(1, 0);
request_irq(BLEND2D_IRQn, 0, blend2d_int_handler, NULL);
writel(0x82, REGS_BLEND2D + BLEND2D_LAYER1_BURST_CTL);
writel(0x82, REGS_BLEND2D + BLEND2D_LAYER2_BURST_CTL);
writel(0x3, REGS_BLEND2D + BLEND2D_INT_CTL);
writel(1, REGS_BLEND2D + BLEND2D_ENABLE);
return 0;
}
int blend2d_run(void)
{
xQueueReset(blend2d_done);
blend2d_start();
if (xQueueReceive(blend2d_done, NULL, pdMS_TO_TICKS(100)) != pdTRUE) {
printf("blend2d_run timeout.\n");
return -1;
}
return 0;
}