rt-thread/bsp/allwinner/libraries/sunxi-hal/hal/test/disp2/disp_mem.c

269 lines
6.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <rtthread.h>
#include <log.h>
#include <hal_mem.h>
#include <video/sunxi_display2.h>
struct info_mm {
void *info_base; /* Virtual address */
unsigned long mem_start; /* Start of frame buffer mem */
/* (physical address) */
u32 mem_len; /* Length of frame buffer mem */
};
struct test_mem_cfg
{
int screen_id;
int layer_id;
int mem_id;
struct disp_layer_config layer_cfg;
int addr_map;
int width,height;//screen size
int dispfh;//device node handle
int fh;//picture resource file handle
void* mem;
int buffer_num;//is double buffer
int clear;//is clear layer
char filename[32];
};
static struct info_mm g_disp_mm[10];
static int g_disp_mem_id = -1;
#define DISP_TEST_BYTE_ALIGN(x) (((x + (4*1024-1)) >> 12) << 12)
static void *disp_malloc(u32 num_bytes, void *phys_addr)
{
u32 actual_bytes;
void *address = NULL;
if (num_bytes != 0) {
actual_bytes = DISP_TEST_BYTE_ALIGN(num_bytes);
address = hal_malloc(actual_bytes);
*(uint32_t *)phys_addr = __va_to_pa((unsigned long)address);
if (address) {
__wrn
("hal_malloc ok, phy addr=0x%p, vir addr=%p size=0x%x\n",
(void *)(*(unsigned long *)phys_addr), address, num_bytes);
return address;
}
printf("dma_alloc_coherent fail, size=0x%x\n", num_bytes);
return NULL;
}
printf("%s size is zero\n", __func__);
return NULL;
}
static void disp_free(void *virt_addr, void *phys_addr, u32 num_bytes)
{
u32 actual_bytes;
actual_bytes = DISP_TEST_BYTE_ALIGN(num_bytes);
if (phys_addr && virt_addr)
hal_free(virt_addr);
}
static int disp_mem_release(int sel)
{
if (g_disp_mm[sel].info_base == NULL)
return -1;
__inf("disp_mem_release, mem_id=%d, phy_addr=0x%p\n", sel,
(void *)g_disp_mm[sel].mem_start);
disp_free((void *)g_disp_mm[sel].info_base,
(void *)g_disp_mm[sel].mem_start, g_disp_mm[sel].mem_len);
memset(&g_disp_mm[sel], 0, sizeof(struct info_mm));
g_disp_mem_id = -1;
return 0;
}
static int disp_mem_request(int sel, u32 size)
{
uintptr_t phy_addr;
if ((sel >= 10) ||
(g_disp_mm[sel].info_base != NULL)) {
printf("invalid param\n");
return -1;
}
g_disp_mm[sel].info_base = disp_malloc(size, (void *)&phy_addr);
if (g_disp_mm[sel].info_base) {
g_disp_mm[sel].mem_start = phy_addr;
g_disp_mm[sel].mem_len = size;
memset(g_disp_mm[sel].info_base, 0, size);
printf("pa=0x%p va=0x%p size:0x%x\n",
(void *)g_disp_mm[sel].mem_start,
g_disp_mm[sel].info_base, size);
g_disp_mem_id = sel;
return 0;
}
printf("disp_malloc fail!\n");
return -1;
}
u32 disp_mem_getadr(u32 memid)
{
if (memid < 10)
return g_disp_mm[memid].mem_start;
return 0;
}
int disp_mem(u32 mem_id, u32 width, u32 height, u32 clear_flag, char *filename)
{
unsigned long arg[6];
int phy_adr, i, n, fb_width, fb_height;
int ret = -1;
FILE *fh = NULL;
void *mem = NULL;
unsigned long count = width*height;
char *tmp;
if(clear_flag) {
/* release memory && clear layer */
disp_mem_release(mem_id);
return 0;
}
//for_test we use r g b to set color buffer
if(filename[0] != 'r' && filename[0] != 'g' && filename[0] != 'b') {
if(filename != NULL)
fh = fopen(filename, "r");
if(!fh) {
printf("open file %s fail. \n", filename);
goto OUT;
}
}
fb_width = width;
fb_height = height;
ret = disp_mem_request(mem_id, fb_width*fb_height*4);
if(ret) {
printf("DISP_MEM_REQUEST 0\n");
goto FILE_CLOSE;
}
phy_adr = g_disp_mm[mem_id].mem_start;
mem = g_disp_mm[mem_id].info_base;
tmp = mem;
if(fh != NULL) {
memset((void*)mem, 0x0, fb_width*fb_height*4);
fread((void *)mem, fb_width * fb_height * 4, 1, fh);
} else {
while(count--) {
//for(i = 0; i < 4; i++) {
#if 0
*(tmp) = 0xff;//A
*(tmp + 1) = filename[0]=='r'?0xff:0;//R
*(tmp + 2) = filename[0]=='g'?0xff:0;//G
*(tmp + 3) = filename[0]=='b'?0xff:0;//B
#else
*(tmp + 3) = 0xff;//A
*(tmp + 2) = filename[0]=='r'?0xff:0;//R
*(tmp + 1) = filename[0]=='g'?0xff:0;//G
*(tmp + 0) = filename[0]=='b'?0xff:0;//B
#endif
//}
tmp+=4;
}
}
FILE_CLOSE:
if(fh!=NULL)
fclose(fh);
OUT:
return ret;
}
int disp_mem_clear(u32 mem_id)
{
return disp_mem(mem_id, 0, 0, 1, NULL);
}
int parse_cmdline_and_alloc(int argc, char **argv)
{
int err = 0;
int i = 0;
struct test_mem_cfg mem_cfg;
struct test_mem_cfg *p = &mem_cfg;
while(i<argc) {
printf("%s ",argv[i]);
i++;
}
memset(p, 0, sizeof(struct test_mem_cfg));
i = 0;
while(i < argc) {
if ( ! strcmp(argv[i], "-mem_id")) {
if (argc > i+1) {
i+=1;
p->mem_id = atoi(argv[i]);
}
}
if ( ! strcmp(argv[i], "-clr")) {
if (argc > i+1) {
i+=1;
p->clear = atoi(argv[i]);
}
}
if ( ! strcmp(argv[i], "-file")) {
if (argc > i+1) {
i++;
p->filename[0] = '\0';
sprintf(p->filename,"%s",argv[i]);
printf("filename=%s\n", argv[i]);
} else {
printf("no file described!!\n");
err ++;
}
}
if ( ! strcmp(argv[i], "-size")) {
if (argc > i+2) {
i++;
p->layer_cfg.info.fb.size[0].width = atoi(argv[i]);
i++;
p->layer_cfg.info.fb.size[0].height = atoi(argv[i]);
} else {
printf("-size para err!\n\n");
err ++;
}
}
if ( ! strcmp(argv[i], "-buffer_num")) {
if (argc > i+1) {
i++;
p->buffer_num = atoi(argv[i]);
p->buffer_num = (p->buffer_num == 0)? 1:p->buffer_num;
}
}
i++;
}
if(err > 0) {
printf("example : ./disp_mem -mem_id 0 -size 1280 800 -double 0 -file ./pic/ui_1280x800_double_151.bin\n");
return -1;
} else {
if (p->clear)
return disp_mem_clear(p->mem_id);
return disp_mem(p->mem_id, p->layer_cfg.info.fb.size[0].width, p->layer_cfg.info.fb.size[0].height, 0, p->filename);
}
}
FINSH_FUNCTION_EXPORT_ALIAS(parse_cmdline_and_alloc, disp_mem, disp mem);