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

268 lines
8.0 KiB
C
Raw Permalink Normal View History

2025-01-21 16:49:37 +08:00
#include "FreeRTOS.h"
#include "board.h"
#include "chip.h"
#define PXP_CTRL 0x000
#define PXP_CTRL_SET 0x004
#define PXP_CTRL_CLR 0x008
#define PXP_CTRL_TOG 0x00C
#define PXP_STAT 0x010
#define PXP_STAT_SET 0x014
#define PXP_STAT_CLR 0x018
#define PXP_STAT_TOG 0x01c
#define PXP_OUTBUF 0x020
#define PXP_OUTBUF2 0x030
#define PXP_OUTSIZE 0x040
#define PXP_S0BUF 0x050
#define PXP_S0UBUF 0x060
#define PXP_S0VBUF 0x070
#define PXP_S0PARAM 0x080
#define PXP_S0BACKGROUND 0x090
#define PXP_S0CLIP 0x0A0
#define PXP_S0SCALE 0x0B0
#define PXP_S0OFFSET 0x0C0
#define PXP_CSCCOEFF0 0x0D0
#define PXP_CSCCOEFF1 0x0E0
#define PXP_CSCCOEFF2 0x0F0
#define PXP_NEXT 0x100
#define PXP_PAGETABLE 0x170
#define PXP_S0CKEYL 0x180
#define PXP_S0CKEYH 0x190
#define PXP_OLCKEYL 0x1A0
#define PXP_OLCKEYH 0x1B0
#define PXP_OL0BUF 0x200
#define PXP_OL0SIZE 0x210
#define PXP_OL0PARAM 0x220
#define PXP_OL1BUF 0x240
#define PXP_OL1SIZE 0x250
#define PXP_OL1PARAM 0x260
#define PXP_OL2BUF 0x280
#define PXP_OL2SIZE 0x290
#define PXP_OL2PARAM 0x2A0
#define PXP_OL3BUF 0x2C0
#define PXP_OL3SIZE 0x2D0
#define PXP_OL3PARAM 0x2E0
#define PXP_OL4BUF 0x300
#define PXP_OL4SIZE 0x310
#define PXP_OL4PARAM 0x320
#define PXP_OL5BUF 0x340
#define PXP_OL5SIZE 0x350
#define PXP_OL5PARAM 0x360
#define PXP_OL6BUF 0x380
#define PXP_OL6SIZE 0x390
#define PXP_OL6PARAM 0x3A0
#define PXP_OL7BUF 0x3C0
#define PXP_OL7SIZE 0x3D0
#define PXP_OL7PARAM 0x3E0
// offss for "NEXT" pointers
#define PXP_NEXTCTRL 0x000
#define PXP_NEXTRGBBUF 0x004
#define PXP_NEXTRGBBUF2 0x008
#define PXP_NEXTRGBSIZE 0x00C
#define PXP_NEXTS0BUF 0x010
#define PXP_NEXTS0UBUF 0x014
#define PXP_NEXTS0VBUF 0x018
#define PXP_NEXTS0PARAM 0x01C
#define PXP_NEXTS0BACKGROUND 0x020
#define PXP_NEXTS0CLIP 0x024
#define PXP_NEXTS0SCALE 0x028
#define PXP_NEXTS0OFFSET 0x02C
#define PXP_NEXTS0CKEYL 0x030
#define PXP_NEXTS0CKEYH 0x034
#define PXP_NEXTOLCKEYL 0x038
#define PXP_NEXTOLCKEYH 0x03C
#define PXP_NEXTOL0BUF 0x040
#define PXP_NEXTOL0SIZE 0x044
#define PXP_NEXTOL0PARAM 0x048
#define PXP_NEXTOL1BUF 0x050
#define PXP_NEXTOL1SIZE 0x054
#define PXP_NEXTOL1PARAM 0x058
#define PXP_NEXTOL2BUF 0x060
#define PXP_NEXTOL2SIZE 0x064
#define PXP_NEXTOL2PARAM 0x068
#define PXP_NEXTOL3BUF 0x070
#define PXP_NEXTOL3SIZE 0x074
#define PXP_NEXTOL3PARAM 0x078
#define PXP_NEXTOL4BUF 0x080
#define PXP_NEXTOL4SIZE 0x084
#define PXP_NEXTOL4PARAM 0x088
#define PXP_NEXTOL5BUF 0x090
#define PXP_NEXTOL5SIZE 0x094
#define PXP_NEXTOL5PARAM 0x098
#define PXP_NEXTOL6BUF 0x0A0
#define PXP_NEXTOL6SIZE 0x0A4
#define PXP_NEXTOL6PARAM 0x0A8
#define PXP_NEXTOL7BUF 0x0B0
#define PXP_NEXTOL7SIZE 0x0B4
#define PXP_NEXTOL7PARAM 0x0B8
#define abs(a, b) ((a > b) ? (a - b) : (b - a))
#define PXP_H_FILP 0
#define PXP_V_FILP 0
static uint32_t pxpbase = REGS_PXP_BASE;
static SemaphoreHandle_t pxp_mutex = NULL;
static QueueHandle_t pxp_done;
/* this function can not used in isr */
int pxp_scaler_rotate(uint32_t s0buf, uint32_t s0ubuf, uint32_t s0vbuf,
int s0format, uint32_t s0width, uint32_t s0height,
uint32_t outbuf, uint32_t outbuf2, int outformat,
uint32_t outwidth, uint32_t outheight, int outangle)
{
uint32_t ctrl;
int ret = 0;
int cutx = 2;
int cuty = 2;
int mirror = 0;
#if PXP_H_FILP
mirror = 1;
#endif
#if PXP_V_FILP
mirror |= 2;
#endif
configASSERT(outangle >= PXP_ROTATE_0 && outangle <= PXP_ROTATE_270);
if (outangle == PXP_ROTATE_90 || outangle == PXP_ROTATE_270) {
uint32_t tmp = outheight;
outheight = outwidth;
outwidth = tmp;
}
if(abs(s0width, outwidth) < 16)
cutx = 0;
if(abs(s0height, outheight) < 16)
cuty = 0;
xSemaphoreTake(pxp_mutex, portMAX_DELAY);
writel(1UL << 31, pxpbase + PXP_CTRL);
udelay(10);
writel(0, pxpbase + PXP_CTRL);
writel(outbuf, pxpbase + PXP_OUTBUF);
writel(outbuf2, pxpbase + PXP_OUTBUF2);
writel((0xffUL << 24) | (outwidth << 12) | outheight, pxpbase + PXP_OUTSIZE);
writel(s0buf, pxpbase + PXP_S0BUF);
writel(s0ubuf, pxpbase + PXP_S0UBUF);
writel(s0vbuf, pxpbase + PXP_S0VBUF);
writel((((s0width >> 3) & 0xff) << 8) | ((s0height >> 3) & 0xff), pxpbase + PXP_S0PARAM);
writel(0, pxpbase + PXP_S0BACKGROUND);
writel((((outwidth >> 3) & 0xff) << 8) | ((outheight >> 3) & 0xff), pxpbase + PXP_S0CLIP);
writel(((s0height * 0x1000 / (outheight + cuty)) << 16) | (s0width * 0x1000 / (outwidth + cutx)),
pxpbase + PXP_S0SCALE);
//YCbCr->RGB Coefficient Values bit31 ycbcr_mode
writel((1 << 31) | 0x1f0 | (0x180 << 9) | (0x12a << 18), pxpbase + PXP_CSCCOEFF0);
writel(0x204 | (0x198 <<16), pxpbase + PXP_CSCCOEFF1);
writel(0x79c | (0x730 <<16), pxpbase + PXP_CSCCOEFF2);
ctrl = (1 << 19) | (1 << 18) | ((s0format & 0xf) << 12) | (outangle << 8) |
(mirror << 10) | ((outformat & 0xf) << 4) | 3;
if(outformat == PXP_OUT_FMT_ARGB8888)
ctrl |=(1<<22);
xQueueReset(pxp_done);
writel(ctrl, pxpbase + PXP_CTRL);
if (xQueueReceive(pxp_done, NULL, pdMS_TO_TICKS(1000)) != pdTRUE) {
printf("pxp timeout.\n");
ret = -ETIMEDOUT;
}
xSemaphoreGive(pxp_mutex);
return ret;
}
int pxp_rotate(uint32_t s0buf, uint32_t s0ubuf, uint32_t s0vbuf,
int s0format, uint32_t s0width, uint32_t s0height,
uint32_t outbuf, uint32_t outbuf2, int outformat,
int outangle)
{
uint32_t ctrl = 0;
int ret = 0;
int mirror = 0;
#if PXP_H_FILP
mirror = 1;
#endif
#if PXP_V_FILP
mirror |= 2;
#endif
configASSERT(outangle >= PXP_ROTATE_0 && outangle <= PXP_ROTATE_270);
xSemaphoreTake(pxp_mutex, portMAX_DELAY);
writel(1UL << 31, pxpbase + PXP_CTRL);
udelay(10);
writel(0, pxpbase + PXP_CTRL);
writel(outbuf, pxpbase + PXP_OUTBUF);
writel(outbuf2, pxpbase + PXP_OUTBUF2);
writel((0xffUL << 24) | (s0width << 12) | s0height, pxpbase + PXP_OUTSIZE);
writel(s0buf, pxpbase + PXP_S0BUF);
writel(s0ubuf, pxpbase + PXP_S0UBUF);
writel(s0vbuf, pxpbase + PXP_S0VBUF);
writel((((s0width >> 3) & 0xff) << 8) | ((s0height >> 3) & 0xff), pxpbase + PXP_S0PARAM);
writel(0, pxpbase + PXP_S0BACKGROUND);
//YCbCr->RGB Coefficient Values bit31 ycbcr_mode
writel((1 << 31) | 0x1f0 | (0x180 << 9) | (0x12a << 18), pxpbase + PXP_CSCCOEFF0);
writel(0x204 | (0x198 << 16), pxpbase + PXP_CSCCOEFF1);
writel(0x79c | (0x730 << 16), pxpbase + PXP_CSCCOEFF2);
if(outformat == PXP_OUT_FMT_ARGB8888) {
if(s0format == PXP_SRC_FMT_ARGB8888) {
writel(0, pxpbase + PXP_OLCKEYL);
writel(0, pxpbase + PXP_OLCKEYH);
writel(s0buf, pxpbase + PXP_OL0BUF);
writel((((s0width >> 3) & 0xff) << 8) | ((s0height >> 3) & 0xff), pxpbase + PXP_OL0SIZE);
writel((0x1<<0) | (0x3<<1) | (0x1<<3) | (s0format<<4) | (0x2<<16), pxpbase + PXP_OL0PARAM);
ctrl |= (1<<19);
s0format = PXP_SRC_FMT_RGB888;
} else {
ctrl |= (1<<22);
}
}
ctrl |= ((s0format & 0xf) << 12) | (outangle << 8) | (mirror<< 10) | ((outformat & 0xf) << 4) | 3;
xQueueReset(pxp_done);
writel(ctrl, pxpbase + PXP_CTRL);
if (xQueueReceive(pxp_done, NULL, pdMS_TO_TICKS(1000)) != pdTRUE) {
printf("pxp timeout.\n");
ret = -ETIMEDOUT;
}
xSemaphoreGive(pxp_mutex);
return ret;
}
static void pxp_interupt_handler(void *param)
{
uint32_t status = readl(pxpbase + PXP_STAT);
writel(status, pxpbase + PXP_STAT_CLR);
if (status & 0x01) {
xQueueSendFromISR(pxp_done, NULL, 0);
}
}
int pxp_init(void)
{
pxp_mutex = xSemaphoreCreateMutex();
pxp_done = xQueueCreate(1, 0);
request_irq(PXP_IRQn, 0, pxp_interupt_handler, NULL);
return 0;
}