/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* * drivers/display/canvas/canvas.c * * Copyright (C) 2020 Amlogic, Inc. All rights reserved. * */ /* System Headers */ #include #include #include /* Amlogic Headers */ #include #define CANVAS_DEBUG_ENABLE #ifdef CANVAS_DEBUG_ENABLE #define canvas_log(fmt, args...) \ do { \ printf("[CANVAS]"fmt"\n", ##args); \ } while (0) #else #define canvas_log(fmt, args...) #endif #define canvas_reg_read(reg) readl(DMC_REG_BASE + reg) #define canvas_reg_write(val, reg) writel(val, (DMC_REG_BASE + reg)) #define CANVAS_NUM 256 static canvas_t canvasPool[CANVAS_NUM]; static int canvas_inited = 0; void canvas_init(void) { int index = 0; if (canvas_inited == 1) return; canvas_log("canvas init"); canvas_reg_write(0, DC_CAV_LUT_DATAL); canvas_reg_write(0, DC_CAV_LUT_DATAH); for (index = 0; index < CANVAS_NUM; index++) { canvas_reg_write(CANVAS_LUT_WR_EN | index, DC_CAV_LUT_ADDR); canvas_reg_read(DC_CAV_LUT_DATAH); } canvas_inited = 1; } void canvas_config(u32 index, ulong addr, u32 width, u32 height, u32 wrap, u32 blkmode) { canvas_t *canvasP = &canvasPool[index]; if (index >= CANVAS_NUM) return; canvas_init(); canvas_log("addr=0x%08lx width=%d, height=%d", addr, width, height); canvas_reg_write((((addr + 7) >> 3) & CANVAS_ADDR_LMASK) | ((((width + 7) >> 3) & CANVAS_WIDTH_LMASK) << CANVAS_WIDTH_LBIT), DC_CAV_LUT_DATAL); canvas_reg_write(((((width + 7) >> 3) >> CANVAS_WIDTH_LWID) << CANVAS_WIDTH_HBIT) | ((height & CANVAS_HEIGHT_MASK) << CANVAS_HEIGHT_BIT) | ((wrap & CANVAS_XWRAP) ? CANVAS_XWRAP : 0) | ((wrap & CANVAS_YWRAP) ? CANVAS_YWRAP : 0) | ((blkmode & CANVAS_BLKMODE_MASK) << CANVAS_BLKMODE_BIT), DC_CAV_LUT_DATAH); canvas_reg_write(CANVAS_LUT_WR_EN | index, DC_CAV_LUT_ADDR); // read a cbus to make sure last write finish. canvas_reg_read(DC_CAV_LUT_DATAH); canvasP->addr = addr; canvasP->width = width; canvasP->height = height; canvasP->wrap = wrap; canvasP->blkmode = blkmode; } void canvas_read(u32 index, canvas_t *p) { if (index < CANVAS_NUM) *p = canvasPool[index]; } void canvas_copy(u32 src, u32 dst) { unsigned long addr; unsigned width, height, wrap, blkmode; if ((src >= CANVAS_NUM) || (dst >= CANVAS_NUM)) return; addr = canvasPool[src].addr; width = canvasPool[src].width; height = canvasPool[src].height; wrap = canvasPool[src].wrap; blkmode = canvasPool[src].blkmode; canvas_reg_write((((addr + 7) >> 3) & CANVAS_ADDR_LMASK) | ((((width + 7) >> 3) & CANVAS_WIDTH_LMASK) << CANVAS_WIDTH_LBIT), DC_CAV_LUT_DATAL); canvas_reg_write(((((width + 7) >> 3) >> CANVAS_WIDTH_LWID) << CANVAS_WIDTH_HBIT) | ((height & CANVAS_HEIGHT_MASK) << CANVAS_HEIGHT_BIT) | ((wrap & CANVAS_XWRAP) ? CANVAS_XWRAP : 0) | ((wrap & CANVAS_YWRAP) ? CANVAS_YWRAP : 0) | ((blkmode & CANVAS_BLKMODE_MASK) << CANVAS_BLKMODE_BIT), DC_CAV_LUT_DATAH); canvas_reg_write(CANVAS_LUT_WR_EN | dst, DC_CAV_LUT_ADDR); // read a cbus to make sure last write finish. canvas_reg_read(DC_CAV_LUT_DATAH); canvasPool[dst].addr = addr; canvasPool[dst].width = width; canvasPool[dst].height = height; canvasPool[dst].wrap = wrap; canvasPool[dst].blkmode = blkmode; return; } void canvas_update_addr(u32 index, u32 addr) { if (index >= CANVAS_NUM) return; canvasPool[index].addr = addr; canvas_reg_write((((canvasPool[index].addr + 7) >> 3) & CANVAS_ADDR_LMASK) | ((((canvasPool[index].width + 7) >> 3) & CANVAS_WIDTH_LMASK) << CANVAS_WIDTH_LBIT), DC_CAV_LUT_DATAL); canvas_reg_write(((((canvasPool[index].width + 7) >> 3) >> CANVAS_WIDTH_LWID) << CANVAS_WIDTH_HBIT) | ((canvasPool[index].height & CANVAS_HEIGHT_MASK) << CANVAS_HEIGHT_BIT) | ((canvasPool[index].wrap & CANVAS_XWRAP) ? CANVAS_XWRAP : 0) | ((canvasPool[index].wrap & CANVAS_YWRAP) ? CANVAS_YWRAP : 0) | ((canvasPool[index].blkmode & CANVAS_BLKMODE_MASK) << CANVAS_BLKMODE_BIT), DC_CAV_LUT_DATAH); canvas_reg_write(CANVAS_LUT_WR_EN | index, DC_CAV_LUT_ADDR); // read a cbus to make sure last write finish. canvas_reg_read(DC_CAV_LUT_DATAH); return; } unsigned int canvas_get_addr(u32 index) { return canvasPool[index].addr; }