| /* |
| * AMLOGIC Canvas management driver. |
| * |
| * Copyright (C) 2015 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| */ |
| |
| /* System Headers */ |
| #include <common.h> |
| #include <asm/arch/io.h> |
| #include <asm/arch/secure_apb.h> |
| |
| |
| /* Amlogic Headers */ |
| #include <amlogic/canvas.h> |
| |
| #ifdef BL33_DEBUG_PRINT |
| #define CANVAS_DEBUG_ENABLE |
| #endif |
| #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; |
| } |