Files
SDK_SG200x_V2/u-boot-2021.10/drivers/jpeg/jdi.c
sophgo-forum-service 17580ae06a u-boot: weekly rls 2024.05.22
- bf9a0a

Change-Id: I0d8f19b2dfb78faf564af12d311557ac18b74c4d
2024-05-31 14:44:04 +08:00

538 lines
11 KiB
C

#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WIN32) || defined(__MINGW32__)
#elif defined(linux) || defined(__linux) || defined(ANDROID)
#include <malloc.h>
#include "jdi.h"
#include "jpulog.h"
#include "jdi_osal.h"
#include "dm/device.h"
#include "timer.h"
#include "asm/cache.h"
#define JPU_BIT_REG_SIZE 0x1000
#define JPU_BIT_REG_BASE (0x0B000000)
/*
* DRAM Total Size = 256MB = 0x10000000
* DRAM_PHYSICAL_BASE = 0x100000000
| Offset | Size | Note
* System | 0x100000000 | 0x2000000 | 32MB
* System Mem | 0x102000000 | 0x4000000 | 64MB
* File Buf | 0x106000000 | 0x2000000 | 32MB
* Enc BS | 0x108000000 | 0x1000000 | 16MB
* ENC SRC | 0x10C000000 | 0x1000000 | 16MB
* LOAD SRC | 0x10D000000
*/
//#define SYSTEM_SIZE 0x2000000
#define JDI_DRAM_PHYSICAL_BASE (0x130000000)
#define JDI_DRAM_PHYSICAL_SIZE 0x00200000 //0x004000000
#define JDI_SYSTEM_ENDIAN JDI_LITTLE_ENDIAN
#define SPM_MEM_PHYSICAL_BASE 0x140000000
#define SPM_MEM_PHYSICAL_SIZE 0xC0000000
typedef struct jpu_buffer_t jpudrv_buffer_t;
typedef struct jpu_buffer_pool_t {
jpudrv_buffer_t jdb;
int inuse;
} jpu_buffer_pool_t;
static int s_jpu_fd;
static jpu_instance_pool_t *s_pjip;
static jpu_instance_pool_t s_jip;
static int s_task_num;
static int s_clock_state;
static jpudrv_buffer_t s_jdb_video_memory;
static jpudrv_buffer_t s_jdb_register;
static jpu_buffer_pool_t s_jpu_buffer_pool[MAX_JPU_BUFFER_POOL];
static int s_jpu_buffer_pool_count;
static int jpu_swap_endian(unsigned char *data, int len, int endian);
int jdi_probe(void)
{
int ret;
ret = jdi_init();
jdi_release();
return ret;
}
int jdi_init(void)
{
int ret;
void *buf = NULL;
if (s_jpu_fd != -1 && s_jpu_fd != 0x00) {
s_task_num++;
return 0;
}
s_jpu_fd = 1;
memset((void *)&s_jpu_buffer_pool, 0x00, sizeof(jpu_buffer_pool_t) * MAX_JPU_BUFFER_POOL);
s_jpu_buffer_pool_count = 0;
s_pjip = jdi_get_instance_pool();
if (!s_pjip) {
JLOG(ERR, "[jdi] fail to create instance pool for saving context\n");
goto ERR_JDI_INIT;
}
buf = malloc(JDI_DRAM_PHYSICAL_SIZE);
if (buf) {
s_jdb_video_memory.phys_addr = (unsigned long)buf;
s_jdb_video_memory.size = JDI_DRAM_PHYSICAL_SIZE;
JLOG(INFO, "alloc s_jdb_video_memory.phys_addr buf %p\n", buf);
} else {
JLOG(ERR, "alloc s_jdb_video_memory.phys_addr failed\n");
goto ERR_JDI_INIT;
}
if (!s_pjip->instance_pool_inited) {
memset(&s_pjip->vmem, 0x00, sizeof(jpeg_mm_t));
ret = jmem_init(&s_pjip->vmem, (unsigned long)s_jdb_video_memory.phys_addr, s_jdb_video_memory.size);
if (ret < 0) {
JLOG(ERR, "[JDI] fail to init jpu memory management logic\n");
goto ERR_JDI_INIT;
}
}
s_jdb_register.phys_addr = JPU_BIT_REG_BASE;
s_jdb_register.virt_addr = JPU_BIT_REG_BASE;
s_jdb_register.size = JPU_BIT_REG_SIZE;
jdi_set_clock_gate(1);
s_task_num++;
JLOG(INFO, "[jdi] success to init driver\n");
return s_jpu_fd;
ERR_JDI_INIT:
jdi_release();
return -1;
}
int jdi_release(void)
{
if (s_jpu_fd == -1 || s_jpu_fd == 0x00)
return 0;
if (jdi_lock() < 0) {
JLOG(ERR, "[jdi] fail to handle lock function\n");
return -1;
}
if (s_task_num > 1) {// means that the opened instance remains
s_task_num--;
jdi_unlock();
return 0;
}
if (s_jdb_video_memory.phys_addr) {
JLOG(INFO, "free s_jdb_video_memory.phys_addr buf %p\n", (void *)s_jdb_video_memory.phys_addr);
free((void *)s_jdb_video_memory.phys_addr);
}
s_task_num--;
jmem_exit(&s_pjip->vmem);
memset(&s_jdb_register, 0x00, sizeof(jpudrv_buffer_t));
if (s_jpu_fd != -1 && s_jpu_fd != 0x00)
s_jpu_fd = -1;
s_pjip = NULL;
jdi_unlock();
return 0;
}
jpu_instance_pool_t *jdi_get_instance_pool(void)
{
if (!s_pjip) {
s_pjip = &s_jip;
memset(s_pjip, 0x00, sizeof(jpu_instance_pool_t));
}
return (jpu_instance_pool_t *)s_pjip;
}
int jdi_open_instance(unsigned long instIdx)
{
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return -1;
s_pjip->jpu_instance_num++;
return 0;
}
int jdi_close_instance(unsigned long instIdx)
{
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return -1;
s_pjip->jpu_instance_num--;
return 0;
}
int jdi_get_instance_num(void)
{
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return -1;
return s_pjip->jpu_instance_num;
}
int jdi_hw_reset(void)
{
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return -1;
// to do any action for hw reset
return 0;
}
int jdi_lock(void)
{
return 0;
}
void jdi_unlock(void)
{
}
void jdi_write_register(unsigned int addr, unsigned int data)
{
unsigned long reg_addr;
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return;
reg_addr = addr + (unsigned long)s_jdb_register.virt_addr;
*(unsigned int *)reg_addr = data;
flush_dcache_range(reg_addr, reg_addr + sizeof(unsigned int));
// flush_dcache_all();
}
unsigned int jdi_read_register(unsigned int addr)
{
unsigned long reg_addr;
reg_addr = addr + (unsigned long)s_jdb_register.virt_addr;
// INV_DCACHE_RANGE((unsigned int)reg_addr, sizeof(unsigned int));
// invalidate_dcache_all();
invalidate_dcache_range(reg_addr, reg_addr + sizeof(unsigned int));
return *(unsigned int *)reg_addr;
}
int jdi_write_memory(unsigned long addr, unsigned char *data, int len, int endian)
{
jpudrv_buffer_t jdb = {0, };
unsigned long offset;
int i;
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return -1;
for (i = 0; i < MAX_JPU_BUFFER_POOL; i++) {
if (s_jpu_buffer_pool[i].inuse == 1) {
jdb = s_jpu_buffer_pool[i].jdb;
if (addr >= jdb.phys_addr && addr < (jdb.phys_addr + jdb.size))
break;
}
}
if (!jdb.size) {
JLOG(ERR, "address 0x%08lx is not mapped address!!!\n", addr);
return -1;
}
offset = addr - (unsigned long)jdb.phys_addr;
jpu_swap_endian(data, len, endian);
//by zhao for cache testing
OSAL_MEMCPY((void *)((unsigned long)jdb.virt_addr + offset), (void *)data, len);
//josal_memcpy_nocache((void *)((unsigned long)jdb.virt_addr+offset), (void *)data, len);
return len;
}
int jdi_read_memory(unsigned long addr, unsigned char *data, int len, int endian)
{
jpudrv_buffer_t jdb = {0};
unsigned long offset;
int i;
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return -1;
for (i = 0; i < MAX_JPU_BUFFER_POOL; i++) {
if (s_jpu_buffer_pool[i].inuse == 1) {
jdb = s_jpu_buffer_pool[i].jdb;
if (addr >= jdb.phys_addr && addr < (jdb.phys_addr + jdb.size))
break;
}
}
if (!jdb.size)
return -1;
offset = addr - (unsigned long)jdb.phys_addr;
INV_DCACHE_RANGE(((unsigned long)jdb.virt_addr + offset), len);
OSAL_MEMCPY(data, (const void *)((unsigned long)jdb.virt_addr + offset), len);
jpu_swap_endian(data, len, endian);
return len;
}
int jdi_allocate_dma_memory(jpu_buffer_t *vb)
{
int i;
unsigned long offset;
jpudrv_buffer_t jdb = {0, };
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return -1;
jdb.size = vb->size;
jdb.phys_addr = (unsigned long)jmem_alloc(&s_pjip->vmem, jdb.size, 0);
if (jdb.phys_addr == (unsigned long)-1)
return -1; // not enough memory
offset = (unsigned long)(jdb.phys_addr - s_jdb_video_memory.phys_addr);
jdb.base = (unsigned long)s_jdb_video_memory.base + offset;
jdb.virt_addr = jdb.phys_addr;
vb->phys_addr = (unsigned long)jdb.phys_addr;
vb->base = (unsigned long)jdb.base;
vb->virt_addr = (unsigned long)vb->phys_addr;
for (i = 0; i < MAX_JPU_BUFFER_POOL; i++) {
if (s_jpu_buffer_pool[i].inuse == 0) {
s_jpu_buffer_pool[i].jdb = jdb;
s_jpu_buffer_pool_count++;
s_jpu_buffer_pool[i].inuse = 1;
break;
}
}
return 0;
}
void jdi_free_dma_memory(jpu_buffer_t *vb)
{
int i;
// int ret = 0;
jpudrv_buffer_t jdb = {0, };
if (!s_pjip || s_jpu_fd == -1 || s_jpu_fd == 0x00)
return;
if (vb->size == 0)
return;
for (i = 0; i < MAX_JPU_BUFFER_POOL; i++) {
if (s_jpu_buffer_pool[i].jdb.phys_addr == vb->phys_addr) {
s_jpu_buffer_pool[i].inuse = 0;
s_jpu_buffer_pool_count--;
jdb = s_jpu_buffer_pool[i].jdb;
break;
}
}
if (!jdb.size) {
JLOG(ERR, "[JDI] invalid buffer to free address = 0x%x\n", (int)jdb.virt_addr);
return;
}
jmem_free(&s_pjip->vmem, (unsigned long)jdb.phys_addr, 0);
memset(vb, 0, sizeof(jpu_buffer_t));
}
int jdi_set_clock_gate(int enable)
{
s_clock_state = enable;
return 0;
}
int jdi_get_clock_gate(void)
{
return s_clock_state;
}
static int intr_reason;
int irq_handler_jpeg_codec(int irqn, void *priv)
{
int curr_int = 0;
#ifdef PROFILE_PERFORMANCE
int ms;
ms = timer_meter_get_ms();
BM_DBG_PERF("time = %d ms\n", ms);
#endif
curr_int = jdi_read_register(MJPEG_PIC_STATUS_REG);
intr_reason |= curr_int;
BM_DBG_TRACE("curr_int = 0x%X, intr_reason = 0x%X\n", curr_int, intr_reason);
JpuWriteReg(MJPEG_PIC_STATUS_REG, curr_int);
return 0;
}
int jdi_wait_interrupt(int timeout)
{
#ifdef SUPPORT_INTERRUPT
int out_reason = 0;
while (1) {
BM_DBG_TRACE("intr_reason = 0x%X\n", intr_reason);
out_reason = intr_reason;
if (out_reason) {
int int_en = jdi_read_register(MJPEG_INTR_MASK_REG);
JpuWriteReg(MJPEG_INTR_MASK_REG, 0);
intr_reason &= (~out_reason);
BM_DBG_TRACE("out_reason = 0x%X\n", out_reason);
JpuWriteReg(MJPEG_INTR_MASK_REG, int_en);
break;
}
}
return out_reason;
#else
while (1) {
if (jdi_read_register(MJPEG_PIC_STATUS_REG))
break;
//Sleep(1); // 1ms sec
//if (count++ > timeout)
// return -1;
}
return 0;
#endif
}
void jdi_log(int cmd, int step)
{
int i;
switch (cmd) {
case JDI_LOG_CMD_PICRUN:
if (step == 1) {
JLOG(INFO, "\n**PIC_RUN start\n");
} else {
JLOG(INFO, "\n**PIC_RUN end\n");
}
break;
}
for (i = 0; i <= 0x238; i = i + 16) {
JLOG(INFO, "0x%04xh: 0x%08x 0x%08x 0x%08x 0x%08x\n", i,
jdi_read_register(i), jdi_read_register(i + 4),
jdi_read_register(i + 8), jdi_read_register(i + 0xc));
}
}
int jpu_swap_endian(unsigned char *data, int len, int endian)
{
unsigned long *p;
unsigned long v1, v2, v3;
int i;
int swap = 0;
p = (unsigned long *)data;
if (endian == JDI_SYSTEM_ENDIAN)
swap = 0;
else
swap = 1;
if (swap) {
if (endian == JDI_LITTLE_ENDIAN || endian == JDI_BIG_ENDIAN) {
for (i = 0; i < len / 4; i += 2) {
v1 = p[i];
v2 = (v1 >> 24) & 0xFF;
v2 |= ((v1 >> 16) & 0xFF) << 8;
v2 |= ((v1 >> 8) & 0xFF) << 16;
v2 |= ((v1 >> 0) & 0xFF) << 24;
v3 = v2;
v1 = p[i + 1];
v2 = (v1 >> 24) & 0xFF;
v2 |= ((v1 >> 16) & 0xFF) << 8;
v2 |= ((v1 >> 8) & 0xFF) << 16;
v2 |= ((v1 >> 0) & 0xFF) << 24;
p[i] = v2;
p[i + 1] = v3;
}
} else {
int sys_endian = JDI_SYSTEM_ENDIAN;
int swap4byte = 0;
swap = 0;
if (endian == JDI_32BIT_LITTLE_ENDIAN) {
if (sys_endian == JDI_BIG_ENDIAN) {
swap = 1;
}
} else {
if (sys_endian == JDI_BIG_ENDIAN) {
swap4byte = 1;
} else if (sys_endian == JDI_LITTLE_ENDIAN) {
swap4byte = 1;
swap = 1;
} else {
swap = 1;
}
}
if (swap) {
for (i = 0; i < len / 4; i++) {
v1 = p[i];
v2 = (v1 >> 24) & 0xFF;
v2 |= ((v1 >> 16) & 0xFF) << 8;
v2 |= ((v1 >> 8) & 0xFF) << 16;
v2 |= ((v1 >> 0) & 0xFF) << 24;
p[i] = v2;
}
}
if (swap4byte) {
for (i = 0; i < len / 4; i += 2) {
v1 = p[i];
v2 = p[i + 1];
p[i] = v2;
p[i + 1] = v1;
}
}
}
}
return swap;
}
#endif