From 831a14c3100dffa04fac17ae26c0d66ffbbfbd87 Mon Sep 17 00:00:00 2001 From: xuhua zhang Date: Tue, 9 Oct 2018 17:21:14 +0800 Subject: [PATCH] vdin: add afbce function for tl1 [1/1] PD#172587 Problem: new added function for tl1 Solution: add vdin afbce support for tl1 Verify: verified on PTM Change-Id: I5e3e2487b6cdbed2d2ca794a6a21ed885e4bf469 Signed-off-by: xuhua zhang --- MAINTAINERS | 5 + arch/arm/boot/dts/amlogic/tl1_pxp.dts | 8 +- drivers/amlogic/media/vin/tvin/vdin/Makefile | 2 + drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c | 590 +++++++++++++++++++++++ drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h | 313 ++++++++++++ drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c | 29 -- drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h | 3 +- drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c | 248 ++++++++++ drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c | 82 +++- drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h | 27 ++ drivers/amlogic/media/vin/tvin/vdin/vdin_regs.h | 1 + drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c | 1 + drivers/amlogic/media/vin/tvin/vdin/vdin_vf.h | 1 + 13 files changed, 1263 insertions(+), 47 deletions(-) create mode 100644 drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c create mode 100644 drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h diff --git a/MAINTAINERS b/MAINTAINERS index c0b9410..608febc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14672,3 +14672,8 @@ F: drivers\amlogic\media\vout\lcd\lcd_clk_ctrl.h F: drivers\amlogic\media\vout\lcd\lcd_debug.h F: drivers\amlogic\media\vout\lcd\lcd_tcon.c F: drivers\amlogic\media\vout\lcd\lcd_tcon.h + +AMLOGIC VDIN DRIVERS +M: Xuhua Zhang +F: drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +F: drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index 7068dfb..50b7fe1 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -88,7 +88,7 @@ // compatible = "shared-dma-pool"; // reusable; /* 3840x2160x4x4 ~=128 M */ - // size = <0x8000000>; + // size = <0xc400000>; // alignment = <0x400000>; //}; @@ -313,6 +313,12 @@ * bit9:use 10bit at 4k_50/60hz_10bit */ tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * 0: normal mode, not use afbce + * 1: use afbce non-mmu mode + * 2: use afbce mmu mode + */ + afbce_bit_mode = <0>; }; vdin@1 { diff --git a/drivers/amlogic/media/vin/tvin/vdin/Makefile b/drivers/amlogic/media/vin/tvin/vdin/Makefile index ee325b5..7f0c556 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/Makefile +++ b/drivers/amlogic/media/vin/tvin/vdin/Makefile @@ -9,3 +9,5 @@ tvin_vdin-objs += vdin_drv.o tvin_vdin-objs += vdin_ctl.o tvin_vdin-objs += vdin_sm.o tvin_vdin-objs += vdin_canvas.o +tvin_vdin-objs += vdin_afbce.o + diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c new file mode 100644 index 0000000..eaa9d73 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -0,0 +1,590 @@ +/* + * drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c + * + * Copyright (C) 2017 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. + * + */ + +/******************** READ ME ************************ + * + * at afbce mode, 1 block = 32 * 4 pixel + * there is a header in one block. + * for example at 1080p, + * header nembers = block nembers = 1920 * 1080 / (32 * 4) + * + * table map(only at non-mmu mode): + * afbce data was saved at "body" region, + * body region has been divided for every 4K(4096 bytes) and 4K unit, + * table map contents is : (body addr >> 12) + * + * at non-mmu mode(just vdin non-mmu mode): + * ------------------------------ + * header + * (can analysis body addr) + * ------------------------------ + * table map + * (save body addr) + * ------------------------------ + * body + * (save afbce data) + * ------------------------------ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../tvin_global.h" +#include "../tvin_format_table.h" +#include "vdin_ctl.h" +#include "vdin_regs.h" +#include "vdin_drv.h" +#include "vdin_vf.h" +#include "vdin_canvas.h" +#include "vdin_afbce.h" + +static unsigned int max_buf_num = VDIN_CANVAS_MAX_CNT; +static unsigned int min_buf_num = 4; +static unsigned int max_buf_width = VDIN_CANVAS_MAX_WIDTH_HD; +static unsigned int max_buf_height = VDIN_CANVAS_MAX_HEIGH; +/* one frame max metadata size:32x280 bits = 1120bytes(0x460) */ +unsigned int dolby_size_bytes = PAGE_SIZE; + +unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) +{ + char vdin_name[6]; + unsigned int mem_size, h_size, v_size; + int flags = CODEC_MM_FLAGS_CMA_FIRST|CODEC_MM_FLAGS_CMA_CLEAR| + CODEC_MM_FLAGS_CPU; + unsigned int max_buffer_num = min_buf_num; + unsigned int i; + /*afbce head need 1036800 byte at most*/ + unsigned int afbce_head_size_byte = PAGE_SIZE * 300;/*1.2M*/ + /*afbce map_table need 218700 byte at most*/ + unsigned int afbce_table_size_byte = PAGE_SIZE * 60;/*0.3M*/ + unsigned int afbce_mem_used; + unsigned int frame_head_size; + unsigned int mmu_used; + //unsigned long afbce_head_phy_addr; + //unsigned long afbce_table_phy_addr; + unsigned long body_start_paddr; + + if (devp->rdma_enable) + max_buffer_num++; + /*todo: need update if vf_skip_cnt used by other port*/ + if (devp->vfp->skip_vf_num && + (((devp->parm.port >= TVIN_PORT_HDMI0) && + (devp->parm.port <= TVIN_PORT_HDMI7)) || + ((devp->parm.port >= TVIN_PORT_CVBS0) && + (devp->parm.port <= TVIN_PORT_CVBS3)))) + max_buffer_num += devp->vfp->skip_vf_num; + if (max_buffer_num > max_buf_num) + max_buffer_num = max_buf_num; + devp->vfmem_max_cnt = max_buffer_num; + devp->canvas_max_num = max_buffer_num; + + if ((devp->cma_config_en == 0) || + (devp->cma_mem_alloc == 1)) { + pr_info("\nvdin%d %s use_reserved mem or cma already alloced (%d,%d)!!!\n", + devp->index, __func__, devp->cma_config_en, + devp->cma_mem_alloc); + return 0; + } + h_size = devp->h_active; + v_size = devp->v_active; + if (devp->canvas_config_mode == 1) { + h_size = max_buf_width; + v_size = max_buf_height; + } + if ((devp->format_convert == VDIN_FORMAT_CONVERT_YUV_YUV444) || + (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_RGB) || + (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444) || + (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_RGB) || + (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_GBR) || + (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_BRG) || + (devp->force_yuv444_malloc == 1)) { + if ((devp->source_bitdepth > VDIN_MIN_SOURCE_BITDEPTH) && + (devp->color_depth_mode != 1)) { + h_size = roundup(h_size * + VDIN_YUV444_10BIT_PER_PIXEL_BYTE, + devp->canvas_align); + devp->canvas_alin_w = h_size / + VDIN_YUV444_10BIT_PER_PIXEL_BYTE; + } else { + h_size = roundup(h_size * + VDIN_YUV444_8BIT_PER_PIXEL_BYTE, + devp->canvas_align); + devp->canvas_alin_w = h_size / + VDIN_YUV444_8BIT_PER_PIXEL_BYTE; + } + } else if ((devp->format_convert == VDIN_FORMAT_CONVERT_YUV_NV12) || + (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_NV21) || + (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_NV12) || + (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_NV21)) { + h_size = roundup(h_size, devp->canvas_align); + devp->canvas_alin_w = h_size; + /*todo change with canvas alloc!!*/ + /* nv21/nv12 only have 8bit mode */ + } else { + /* txl new add mode yuv422 pack mode:canvas-w=h*2*10/8 + *canvas_w must ensure divided exact by 256bit(32byte + */ + if ((devp->source_bitdepth > VDIN_MIN_SOURCE_BITDEPTH) && + ((devp->format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || + (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_YUV422) || + (devp->format_convert == VDIN_FORMAT_CONVERT_GBR_YUV422) || + (devp->format_convert == VDIN_FORMAT_CONVERT_BRG_YUV422)) && + (devp->color_depth_mode == 1)) { + h_size = roundup((h_size * 5)/2, devp->canvas_align); + devp->canvas_alin_w = (h_size * 2) / 5; + } else if ((devp->source_bitdepth > VDIN_MIN_SOURCE_BITDEPTH) && + (devp->color_depth_mode == 0)) { + h_size = roundup(h_size * + VDIN_YUV422_10BIT_PER_PIXEL_BYTE, + devp->canvas_align); + devp->canvas_alin_w = h_size / + VDIN_YUV422_10BIT_PER_PIXEL_BYTE; + } else { + h_size = roundup(h_size * + VDIN_YUV422_8BIT_PER_PIXEL_BYTE, + devp->canvas_align); + devp->canvas_alin_w = h_size / + VDIN_YUV422_8BIT_PER_PIXEL_BYTE; + } + } + mem_size = h_size * v_size; + if ((devp->format_convert >= VDIN_FORMAT_CONVERT_YUV_NV12) && + (devp->format_convert <= VDIN_FORMAT_CONVERT_RGB_NV21)) + mem_size = (mem_size * 3)/2; + devp->vfmem_size = PAGE_ALIGN(mem_size) + dolby_size_bytes; + devp->vfmem_size = (devp->vfmem_size/PAGE_SIZE + 1)*PAGE_SIZE; + + mem_size = PAGE_ALIGN(mem_size) * max_buffer_num + + dolby_size_bytes * max_buffer_num; + mem_size = (mem_size/PAGE_SIZE + 1)*PAGE_SIZE; + if (mem_size > devp->cma_mem_size) + mem_size = devp->cma_mem_size; + if (devp->index == 0) + strcpy(vdin_name, "vdin0"); + else if (devp->index == 1) + strcpy(vdin_name, "vdin1"); + + + if (devp->cma_config_flag == 0x101) { + devp->afbce_info->head_paddr = codec_mm_alloc_for_dma( + vdin_name, afbce_head_size_byte/PAGE_SIZE, 0, flags); + devp->afbce_info->table_paddr = codec_mm_alloc_for_dma( + vdin_name, afbce_table_size_byte/PAGE_SIZE, 0, flags); + devp->afbce_info->head_size = afbce_head_size_byte; + devp->afbce_info->table_size = afbce_table_size_byte; + devp->afbce_info->frame_body_size = devp->vfmem_size; + + pr_info("vdin%d head_start = 0x%lx, head_size = 0x%x\n", + devp->index, devp->afbce_info->head_paddr, + devp->afbce_info->head_size); + pr_info("vdin%d table_start = 0x%lx, table_size = 0x%x\n", + devp->index, devp->afbce_info->table_paddr, + devp->afbce_info->table_size); + + /* set fm_body_paddr */ + for (i = 0; i < max_buffer_num; i++) { + devp->afbce_info->fm_body_paddr[i] = + codec_mm_alloc_for_dma(vdin_name, + devp->vfmem_size/PAGE_SIZE, 0, flags); + if (devp->afbce_info->fm_body_paddr[i] == 0) { + pr_err("\nvdin%d-afbce buf[%d]codec alloc fail!!!\n", + devp->index, i); + devp->cma_mem_alloc = 0; + } else { + devp->cma_mem_alloc = 1; + pr_info("vdin%d fm_body_paddr[%d] = 0x%lx, body_size = 0x%x\n", + devp->index, i, + devp->afbce_info->fm_body_paddr[i], + devp->afbce_info->frame_body_size); + } + + if (devp->cma_mem_alloc == 0) + return 1; + } + pr_info("vdin%d-afbce codec cma alloc ok!\n", devp->index); + devp->mem_size = mem_size; + } else if (devp->cma_config_flag == 0) { + devp->venc_pages = dma_alloc_from_contiguous( + &(devp->this_pdev->dev), + devp->cma_mem_size >> PAGE_SHIFT, 0); + if (devp->venc_pages) { + devp->mem_start = + page_to_phys(devp->venc_pages); + devp->mem_size = mem_size; + devp->cma_mem_alloc = 1; + + devp->afbce_info->head_paddr = devp->mem_start; + devp->afbce_info->head_size = 2*SZ_1M;/*2M*/ + devp->afbce_info->table_paddr = + devp->mem_start + devp->afbce_info->head_paddr; + devp->afbce_info->table_size = 2*SZ_1M;/*2M*/ + devp->afbce_info->frame_body_size = devp->vfmem_size; + + body_start_paddr = devp->afbce_info->table_paddr + + devp->afbce_info->table_size; + + pr_info("vdin%d head_start = 0x%lx, head_size = 0x%x\n", + devp->index, devp->afbce_info->head_paddr, + devp->afbce_info->head_size); + pr_info("vdin%d table_start = 0x%lx, table_size = 0x%x\n", + devp->index, devp->afbce_info->table_paddr, + devp->afbce_info->table_size); + + /* set fm_body_paddr */ + for (i = 0; i < max_buffer_num; i++) { + devp->afbce_info->fm_body_paddr[i] = + body_start_paddr + (devp->vfmem_size * i); + + pr_info("vdin%d body[%d]_start = 0x%lx, body_size = 0x%x\n", + devp->index, i, + devp->afbce_info->fm_body_paddr[i], + devp->afbce_info->frame_body_size); + } + + /*check memory over the boundary*/ + afbce_mem_used = + devp->afbce_info->fm_body_paddr[max_buffer_num] + + devp->afbce_info->frame_body_size - + devp->afbce_info->head_paddr; + if (afbce_mem_used > devp->cma_mem_size) { + pr_info("afbce mem: afbce_mem_used(%d) > cma_mem_size(%d)\n", + afbce_mem_used, devp->cma_mem_size); + return 1; + } + devp->cma_mem_alloc = 1; + pr_info("vdin%d cma alloc ok!\n", devp->index); + } else { + devp->cma_mem_alloc = 0; + pr_err("\nvdin%d-afbce cma mem undefined2.\n", + devp->index); + return 1; + } + } + + /* 1 block = 32 * 4 pixle = 128 pixel */ + /* there is a header in one block, a header has 4 bytes */ + /* set fm_head_paddr start */ + frame_head_size = roundup(devp->h_active * devp->v_active, 128); + /*h_active * v_active / 128 * 4 = frame_head_size*/ + frame_head_size = devp->h_active * devp->v_active / 32; + frame_head_size = PAGE_ALIGN(frame_head_size); + + devp->afbce_info->frame_head_size = frame_head_size; + + for (i = 0; i < max_buffer_num; i++) { + devp->afbce_info->fm_head_paddr[i] = + devp->afbce_info->head_paddr + (frame_head_size*i); + + pr_info("vdin%d fm_head_paddr[%d] = 0x%lx, frame_head_size = 0x%x\n", + devp->index, i, + devp->afbce_info->fm_head_paddr[i], + frame_head_size); + } + /* set fm_head_paddr end */ + + /* set fm_table_paddr start */ + mmu_used = devp->afbce_info->frame_body_size >> 12; + mmu_used = mmu_used * 4; + mmu_used = PAGE_ALIGN(mmu_used); + devp->afbce_info->frame_table_size = mmu_used; + + for (i = 0; i < max_buffer_num; i++) { + devp->afbce_info->fm_table_paddr[i] = + devp->afbce_info->table_paddr + (mmu_used*i); + + pr_info("vdin%d fm_table_paddr[%d]=0x%lx, frame_table_size = 0x%x\n", + devp->index, i, + devp->afbce_info->fm_table_paddr[i], + devp->afbce_info->frame_table_size); + } + /* set fm_table_paddr end */ + + return 0; +} + +void vdin_afbce_cma_release(struct vdin_dev_s *devp) +{ + char vdin_name[6]; + unsigned int i; + + if ((devp->cma_config_en == 0) || + (devp->cma_mem_alloc == 0)) { + pr_err("\nvdin%d %s fail for (%d,%d)!!!\n", + devp->index, __func__, devp->cma_config_en, + devp->cma_mem_alloc); + return; + } + if (devp->index == 0) + strcpy(vdin_name, "vdin0"); + else if (devp->index == 1) + strcpy(vdin_name, "vdin1"); + + if (devp->cma_config_flag == 0x101) { + codec_mm_free_for_dma(vdin_name, devp->afbce_info->head_paddr); + codec_mm_free_for_dma(vdin_name, devp->afbce_info->table_paddr); + for (i = 0; i < devp->vfmem_max_cnt; i++) + codec_mm_free_for_dma(vdin_name, + devp->afbce_info->fm_body_paddr[i]); + pr_info("vdin%d-afbce codec cma release ok!\n", devp->index); + } else if (devp->venc_pages + && devp->cma_mem_size + && (devp->cma_config_flag == 0)) { + dma_release_from_contiguous( + &(devp->this_pdev->dev), + devp->venc_pages, + devp->cma_mem_size >> PAGE_SHIFT); + pr_info("vdin%d-afbce cma release ok!\n", devp->index); + } else { + pr_err("\nvdin%d %s fail for (%d,0x%x,0x%lx)!!!\n", + devp->index, __func__, devp->cma_mem_size, + devp->cma_config_flag, devp->mem_start); + } + devp->mem_start = 0; + devp->mem_size = 0; + devp->cma_mem_alloc = 0; +} + +void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, + enum vdin_output_mif_e sel) +{ + unsigned int offset = devp->addr_offset; + + if (offset == 0) { + if (sel == VDIN_OUTPUT_TO_MIF) { + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_AFBCE_BIT, 1); + } else if (sel == VDIN_OUTPUT_TO_AFBCE) { + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_AFBCE_BIT, 1); + } + } else { + if (sel == VDIN_OUTPUT_TO_MIF) { + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_AFBCE_BIT, 1); + } else if (sel == VDIN_OUTPUT_TO_AFBCE) { + /*sel vdin1 afbce: not support in sw now, + *just reserved interface + */ + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_AFBCE_BIT, 1); + } + } +} + +static void afbce_wr(uint32_t reg, const uint32_t val) +{ + wr(0, reg, val); +} + +void vdin_afbce_config(struct vdin_dev_s *devp) +{ + unsigned int offset = devp->addr_offset; + int hold_line_num = 4; + int lbuf_depth = 256; + int lossy_luma_en = 0; + int lossy_chrm_en = 0; + int cur_mmu_used = 0; + int reg_format_mode;//0:444 1:422 2:420 + int reg_fmt444_comb; + int sblk_num; + int uncmp_bits; + int uncmp_size; + int def_color_0 = 0; + int def_color_1 = 0; + int def_color_2 = 0; + int def_color_3 = 0; + int hblksize_out = (devp->h_active + 31) >> 5; + int vblksize_out = (devp->v_active + 3) >> 2; + int blk_out_end_h;//output blk scope + int blk_out_bgn_h;//output blk scope + int blk_out_end_v;//output blk scope + int blk_out_bgn_v;//output blk scope + int enc_win_bgn_h;//input scope + int enc_win_end_h;//input scope + int enc_win_bgn_v;//input scope + int enc_win_end_v;//input scope + + if (offset != 0) { + pr_info("cat not use afbce on vdin1 at the moment\n"); + return; + } + + enc_win_bgn_h = 0; + enc_win_end_h = devp->h_active - 1; + enc_win_bgn_v = 0; + enc_win_end_v = devp->v_active - 1; + + blk_out_end_h = enc_win_bgn_h >> 5 ;//output blk scope + blk_out_bgn_h = (enc_win_end_h+31) >> 5 ;//output blk scope + blk_out_end_v = enc_win_bgn_v >> 2 ;//output blk scope + blk_out_bgn_v = (enc_win_end_v + 3) >> 2 ;//output blk scope + + if ((devp->prop.dest_cfmt == TVIN_YUV444) && (devp->h_active > 2048)) + reg_fmt444_comb = 1; + else + reg_fmt444_comb = 0; + + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) { + reg_format_mode = 2; + sblk_num = 12; + } else if ((devp->prop.dest_cfmt == TVIN_YUV422) || + (devp->prop.dest_cfmt == TVIN_YUYV422) || + (devp->prop.dest_cfmt == TVIN_YVYU422) || + (devp->prop.dest_cfmt == TVIN_UYVY422) || + (devp->prop.dest_cfmt == TVIN_VYUY422)) { + reg_format_mode = 1; + sblk_num = 16; + } else { + reg_format_mode = 0; + sblk_num = 24; + } + uncmp_bits = devp->source_bitdepth; + + //bit size of uncompression mode + uncmp_size = (((((16*uncmp_bits*sblk_num)+7)>>3)+31)/32)<<1; + + W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 3, 1);//vpu arb axi_enable + W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 7, 1);//vpu arb axi_enable + + afbce_wr(AFBCE_MODE, + (0 & 0x7) << 29 | (0 & 0x3) << 26 | (3 & 0x3) << 24 | + (hold_line_num & 0x7f) << 16 | + (2 & 0x3) << 14 | (reg_fmt444_comb & 0x1)); + + W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_luma_en & 0x1), 0, 1);//loosy + W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_chrm_en & 0x1), 4, 1);//loosy + + afbce_wr(AFBCE_SIZE_IN, + ((devp->h_active & 0x1fff) << 16) | // hsize_in of afbc input + ((devp->v_active & 0x1fff) << 0) // vsize_in of afbc input + ); + + afbce_wr(AFBCE_BLK_SIZE_IN, + ((hblksize_out & 0x1fff) << 16) | // out blk hsize + ((vblksize_out & 0x1fff) << 0) // out blk vsize + ); + + //head addr of compressed data + afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[0]); + + W_VCBUS_BIT(AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);//uncmp_size + + /* how to set reg when we use crop ? */ + // scope of hsize_in ,should be a integer multipe of 32 + // scope of vsize_in ,should be a integer multipe of 4 + afbce_wr(AFBCE_PIXEL_IN_HOR_SCOPE, + ((enc_win_end_h & 0x1fff) << 16) | + ((enc_win_bgn_h & 0x1fff) << 0)); + + // scope of hsize_in ,should be a integer multipe of 32 + // scope of vsize_in ,should be a integer multipe of 4 + afbce_wr(AFBCE_PIXEL_IN_VER_SCOPE, + ((enc_win_end_v & 0x1fff) << 16) | + ((enc_win_bgn_v & 0x1fff) << 0)); + + afbce_wr(AFBCE_CONV_CTRL, lbuf_depth);//fix 256 + + afbce_wr(AFBCE_MIF_HOR_SCOPE, + ((blk_out_bgn_h & 0x3ff) << 16) | // scope of out blk hsize + ((blk_out_end_h & 0xfff) << 0) // scope of out blk vsize + ); + + afbce_wr(AFBCE_MIF_VER_SCOPE, + ((blk_out_bgn_v & 0x3ff) << 16) | // scope of out blk hsize + ((blk_out_end_v & 0xfff) << 0) // scope of out blk vsize + ); + + afbce_wr(AFBCE_FORMAT, + (reg_format_mode & 0x3) << 8 | + (uncmp_bits & 0xf) << 4 | + (uncmp_bits & 0xf)); + + afbce_wr(AFBCE_DEFCOLOR_1, + ((def_color_3 & 0xfff) << 12) | // def_color_a + ((def_color_0 & 0xfff) << 0) // def_color_y + ); + + afbce_wr(AFBCE_DEFCOLOR_2, + ((def_color_2 & 0xfff) << 12) | // def_color_v + ((def_color_1 & 0xfff) << 0) // def_color_u + ); + + //cur_mmu_used += Rd(AFBCE_MMU_NUM); //4k addr have used in every frame; + + W_VCBUS_BIT(AFBCE_MMU_RMIF_CTRL4, devp->afbce_info->table_paddr, 0, 32); + W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); + + W_VCBUS_BIT(AFBCE_ENABLE, 1, 8, 1);//enable afbce +} + +void vdin_afbce_maptable_init(struct vdin_dev_s *devp) +{ + unsigned int i, j; + unsigned int *ptable = NULL; + unsigned int *vtable = NULL; + unsigned int body; + unsigned int size; + + size = roundup(devp->afbce_info->frame_body_size, 4096); + + for (i = 0; i < devp->vfmem_max_cnt; i++) { + ptable = (unsigned int *) + (devp->afbce_info->fm_table_paddr[i]&0xffffffff); + if (devp->cma_config_flag == 0x101) + vtable = codec_mm_phys_to_virt((unsigned long)ptable); + else if (devp->cma_config_flag == 0) + vtable = phys_to_virt((unsigned long)ptable); + + body = devp->afbce_info->fm_body_paddr[i]&0xffffffff; + for (j = 0; j < size; j += 4096) { + *vtable = ((j + body) >> 12) & 0x000fffff; + vtable++; + } + } +} + +void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, + unsigned int rdma_enable, struct vf_entry *vfe) +{ + unsigned char i; + unsigned int cur_mmu_used; + + i = vfe->af_num; + cur_mmu_used = devp->afbce_info->fm_table_paddr[i] / 4; + +#ifdef CONFIG_AML_RDMA + if (rdma_enable) + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); + rdma_write_reg(devp->rdma_handle, + AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); + else +#endif + afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); + W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); +} + diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h new file mode 100644 index 0000000..feb2d08 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h @@ -0,0 +1,313 @@ +/* + * drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h + * + * Copyright (C) 2017 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. + * + */ + +#ifndef __VDIN_AFBCE_H__ +#define __VDIN_AFBCE_H__ +#include "vdin_drv.h" +#include "vdin_ctl.h" + +#define AFBCE_ENABLE 0x41a0 +//Bit 31:13, reserved +//Bit 12 , reg_clk_en default = 1, +//Bit 11:9, reserved +//Bit 8, enc_enable default = 0 +//Bit 7:1, reserved +//Bit 0, enc_frm_start default = 0, + +#define AFBCE_MODE 0x41a1 +//Bit 31:29, soft_rst default = 0 ,the use as go_field +//Bit 28, reserved +//Bit 27:26, rev_mode default = 0 , reverse mode +//Bit 25:24, mif_urgent default = 3 , info mif and data mif urgent +//Bit 23, reserved +//Bit 22:16, hold_line_num default = 4, 0: burst1 1:burst2 2:burst4 +//Bit 15:14, burst_mode default = 1, 0: burst1 1:burst2 2:burst4 +//Bit 13:0, reserved + +#define AFBCE_SIZE_IN 0x41a2 +//Bit 31:29, reserved +//Bit 28:16 hsize_in default = 1920,pic horz size in.unit: pixel +//Bit 15:13, reserved +//Bit 12:0, vsize_in default = 1080,pic vert size in.unit: pixel + +#define AFBCE_BLK_SIZE_IN 0x41a3 +//Bit 31:29, reserved +//Bit 28:16 hblk_size default = 60 , pic horz size in.unit: pixel +//Bit 15:13, reserved +//Bit 12:0, vblk_size default = 270, pic vert size in.unit: pixel + +#define AFBCE_HEAD_BADDR 0x41a4 +//Bit 31:0, head_baddr unsigned, default = 32'h00; + +#define AFBCE_MIF_SIZE 0x41a5 +//Bit 31:30, reserved +//Bit 29:28, ddr_blk_size unsigned, default = 32'h128; +//Bit 27, reserved +//Bit 26:24, cmd_blk_size unsigned, default = 32'h128; +//Bit 23:21, reserved +//Bit 20:16, uncmp_size unsigned, default = 32'h128; +//Bit 15:13, reserved +//Bit 12:0, mmu_page_size unsigned, default = 32'h4096; + +#define AFBCE_PIXEL_IN_HOR_SCOPE 0x41a6 +//Bit 31:29, reserved +//Bit 28:16, enc_win_end_h unsigned, default = 1919 +//Bit 15:13, reserved +//Bit 12:0, enc_win_bgn_h unsigned, default = 0 + +#define AFBCE_PIXEL_IN_VER_SCOPE 0x41a7 +//Bit 31:29, reserved +//Bit 28:16, enc_win_end_v unsigned, default = 1079 +//Bit 15:13, reserved +//Bit 12:0, enc_win_bgn_v unsigned, default = 0 + +#define AFBCE_CONV_CTRL 0x41a8 +//Bit 31:12, reserved +//Bit 11: 0, lbuf_depth default = 256, unit=16 pixel need to set = 2^n + +#define AFBCE_MIF_HOR_SCOPE 0x41a9 +//Bit 31:26, reserved +//Bit 25:16, blk_end_h unsigned, default = 0 +//Bit 15:10, reserved +//Bit 9:0, blk_bgn_h unsigned, default = 59 + +#define AFBCE_MIF_VER_SCOPE 0x41aa +//Bit 31:28, reserved +//Bit 27:16, blk_end_v unsigned, default = 0 +//Bit 15:12, reserved +//Bit 11:0, blk_bgn_v unsigned, default = 269 + +#define AFBCE_STAT1 0x41ab +//Bit 31, ro_frm_end_pulse1 unsigned, default = 0;frame end status +//Bit 30:0, ro_dbg_top_info1 unsigned, default = 0; + +#define AFBCE_STAT2 0x41ac +//Bit 31, reserved unsigned, default = 0;frame end status +//Bit 30:0, ro_dbg_top_info2 unsigned, default = 0 + +#define AFBCE_FORMAT 0x41ad +//Bit 31:12 reserved +//Bit 11 reserved +//Bit 10 reg_inp_yuv default = 1 +// input is with yuv instead of rgb: 0: rgb, 1:yuv +//Bit 9 reg_inp_422 default = 0 +// input is with yuv422 instead of 444. 0: yuv444/yuv420; 1:yuv422 +//Bit 8 reg_inp_420 default = 1 +// input is with yuv420 instead of 444. 0: yuv444/yuv422; 1:yuv420 +//Bit 7: 4 reg_bly default = 10 luma bitwidth +//Bit 3: 0 reg_blc default = 10 chroma bitwidth + +#define AFBCE_MODE_EN 0x41ae +//Bit 31:28 reserved +//Bit 27:26 reserved +//Bit 25 reg_adpt_interleave_ymode +// RW, default = 0 force 0 to disable it: no HW implementation +//Bit 24 reg_adpt_interleave_cmode +// RW, default = 0 force 0 to disable it: not HW implementation +//Bit 23 reg_adpt_yinterleave_luma_ride +// RW, default = 1 vertical interleave piece luma reorder ride; +// 0: no reorder ride; 1: w/4 as ride +//Bit 22 reg_adpt_yinterleave_chrm_ride +// RW, default = 1 vertical interleave piece chroma reorder ride; +// 0: no reorder ride; 1: w/2 as ride +//Bit 21 reg_adpt_xinterleave_luma_ride +// RW, default = 1 vertical interleave piece luma reorder ride; +// 0: no reorder ride; 1: w/4 as ride +//Bit 20 reg_adpt_xinterleave_chrm_ride +// RW, default = 1 vertical interleave piece chroma reorder ride; +// 0: no reorder ride; 1: w/2 as ride +//Bit 19 reserved +//Bit 18 reg_disable_order_mode_i_6 +// RW, default = 0 disable order mode0~6: each mode with one +// disable bit: 0: no disable, 1: disable +//Bit 17 reg_disable_order_mode_i_5 +// RW, default = 0 disable order mode0~6: each mode with one +// disable bit: 0: no disable, 1: disable +//Bit 16 reg_disable_order_mode_i_4 +// RW, default = 0 disable order mode0~6: each mode with one +// disable bit: 0: no disable, 1: disable +//Bit 15 reg_disable_order_mode_i_3 +// RW, default = 0 disable order mode0~6: each mode with one +// disable bit: 0: no disable, 1: disable +//Bit 14 reg_disable_order_mode_i_2 +// RW, default = 0 disable order mode0~6: each mode with one +// disable bit: 0: no disable, 1: disable +//Bit 13 reg_disable_order_mode_i_1 +// RW, default = 0 disable order mode0~6: each mode with one +// disable bit: 0: no disable, 1: disable +//Bit 12 reg_disable_order_mode_i_0 +// RW, default = 0 disable order mode0~6: each mode with one +// disable bit: 0: no disable, 1: disable +//Bit 11 reserved +//Bit 10 reg_minval_yenc_en +// RW, default = 0 force disable, +// final decision to remove this ws 1% performance loss +//Bit 9 reg_16x4block_enable +// RW, default = 0 block as mission, but permit 16x4 block +//Bit 8 reg_uncompress_split_mode +// RW, default = 0 0: no split; 1: split +//Bit 7: 6 reserved +//Bit 5 reg_input_padding_uv128 +// RW, default = 0 input picture 32x4 +// block gap mode: 0: pad uv=0; 1: pad uv=128 +//Bit 4 reg_dwds_padding_uv128 +// RW, default = 0 downsampled image for double write 32x gap mode +// 0: pad uv=0; 1: pad uv=128 +//Bit 3: 1 reg_force_order_mode_value +// RW, default = 0 force order mode 0~7 +//Bit 0 reg_force_order_mode_en +// RW, default = 0 force order mode enable +// 0: no force; 1: forced to force_value + +#define AFBCE_DWSCALAR 0x41af +//Bit 31: 8 reserved +//Bit 7: 6 reg_dwscalar_w0 +// RW, default = 3 horizontal 1st step scalar mode +// 0: 1:1 no scalar; 1: 2:1 data drop (0,2,4, 6) +// pixel kept; 2: 2:1 data drop (1, 3, 5,7..) pixels kept; 3: avg +//Bit 5: 4 reg_dwscalar_w1 +// RW, default = 0 horizontal 2nd step scalar mode +// 0: 1:1 no scalar; 1: 2:1 data drop (0,2,4, 6) pixel kept; +// 2: 2:1 data drop (1, 3, 5,7..) pixels kept; 3: avg +//Bit 3: 2 reg_dwscalar_h0 +// RW, default = 2 vertical 1st step scalar mode +// 0: 1:1 no scalar; 1: 2:1 data drop (0,2,4, 6) pixel kept +// 2: 2:1 data drop (1, 3, 5,7..) pixels kept; 3: avg +//Bit 1: 0 reg_dwscalar_h1 +// RW, default = 3 vertical 2nd step scalar mode +// 0: 1:1 no scalar; 1: 2:1 data drop (0,2,4, 6) pixel kept +// 2: 2:1 data drop (1, 3, 5,7..) pixels kept; 3: avg + +#define AFBCE_DEFCOLOR_1 0x41b0 +//Bit 31:24 reserved +//Bit 23:12 reg_enc_defalutcolor_3 +// RW, default = 4095 Picture wise default color value in [Y Cb Cr] +//Bit 11: 0 reg_enc_defalutcolor_0 +// RW, default = 4095 Picture wise default color value in [Y Cb Cr] + +#define AFBCE_DEFCOLOR_2 0x41b1 +//Bit 31:24 reserved +//Bit 23:12 reg_enc_defalutcolor_2 +// RW, default = 2048 wise default color value in [Y Cb Cr] +//Bit 11: 0 reg_enc_defalutcolor_1 +// RW, default = 2048 wise default color value in [Y Cb Cr] + +#define AFBCE_QUANT_ENABLE 0x41b2 +//Bit 31:10 reserved +//Bit 9: 8 reg_bcleav_ofst +// RW, default = 0 bcleave ofset to get lower range, +// especially under lossy, for v1/v2, x=0 is equivalent, default = -1; +//Bit 7: 5 reserved +//Bit 4 reg_quant_enable_1 +// RW, default = 0 enable for quant to get some lossy +//Bit 3: 1 reserved +//Bit 0 reg_quant_enable_0 +// RW, default = 0 enable for quant to get some lossy + +#define AFBCE_IQUANT_LUT_1 0x41b3 +#define AFBCE_IQUANT_LUT_2 0x41b4 +#define AFBCE_IQUANT_LUT_3 0x41b5 +#define AFBCE_IQUANT_LUT_4 0x41b6 +#define AFBCE_RQUANT_LUT_1 0x41b7 +#define AFBCE_RQUANT_LUT_2 0x41b8 +#define AFBCE_RQUANT_LUT_3 0x41b9 +#define AFBCE_RQUANT_LUT_4 0x41ba + +#define AFBCE_YUV_FORMAT_CONV_MODE 0x41bb +//Bit 31: 8 reserved +//Bit 7 reserved +//Bit 6: 4 reg_444to422_mode RW, default = 0 +//Bit 3 reserved +//Bit 2: 0 reg_422to420_mode RW, default = 0 + +#define AFBCE_DUMMY_DATA 0x41bc +//Bit 31:30 reserved +//Bit 29: 0 reg_dummy_data RW, default = 0x00080200 + +#define AFBCE_CLR_FLAG 0x41bd +//Bit 31:0 reg_afbce_clr_flag default = 0 + +#define AFBCE_STA_FLAGT 0x41be +//Bit 31:0 ro_afbce_sta_flag default = 0 + +#define AFBCE_MMU_NUM 0x41bf +//Bit 31:16 reserved +//Bit 15: 0 ro_frm_mmu_num default = 0 + +#define AFBCE_MMU_RMIF_CTRL1 0x41c0 +//Bit 31:26 reserved +//Bit 25:24 reg_sync_sel default = 0, axi canvas id sync with frm rst +//Bit 23:16 reg_canvas_id default = 0, axi canvas id num +//Bit 15 reserved +//Bit 14:12 reg_cmd_intr_len +// default = 1, interrupt send cmd when how many series axi cmd +//Bit 11:10 reg_cmd_req_size +// default = 1, how many room fifo have, +// then axi send series req, 0=16 1=32 2=24 3=64 +//Bit 9:8 reg_burst_len +// default = 2, burst type: 0-single 1-bst2 2-bst4 +//Bit 7 reg_swap_64bit +// default = 0, 64bits of 128bit swap enable +//Bit 6 reg_little_endian +// default = 0, big endian enable +//Bit 5 reg_y_rev default = 0, vertical reverse enable +//Bit 4 reg_x_rev default = 0, horizontal reverse enable +//Bit 3 reserved +//Bit 2:0 reg_pack_mode +// default = 3, 0:4bit 1:8bit 2:16bit 3:32bit 4:64bit 5:128bit + +#define AFBCE_MMU_RMIF_CTRL2 0x41c1 +//Bit 31:30 reg_sw_rst // unsigned , default = 0, +//Bit 29:24 reserved +//Bit 23:18 reg_gclk_ctrl +//Bit 17 reserved +//Bit 16:0 reg_urgent_ctrl // unsigned , default = 0, urgent control reg + +#define AFBCE_MMU_RMIF_CTRL3 0x41c2 +//Bit 31:17 reserved +//Bit 16 reg_acc_mode // unsigned , default = 1 +//Bit 15:13 reserved +//Bit 12:0 reg_stride // unsigned , default = 4096 + +#define AFBCE_MMU_RMIF_CTRL4 0x41c3 +//Bit 31:0 reg_baddr // unsigned , default = 0 + +#define AFBCE_MMU_RMIF_SCOPE_X 0x41c4 +//Bit 31:29 reserved +//Bit 28:16 reg_x_end default = 4095, the canvas hor end pixel position +//Bit 15:13 reserved +//Bit 12: 0 reg_x_start default = 0, the canvas hor start pixel position + +#define AFBCE_MMU_RMIF_SCOPE_Y 0x41c5 +//Bit 31:29 reserved +//Bit 28:16 reg_y_end default = 0, the canvas ver end pixel position +//Bit 15:13 reserved +//Bit 12: 0 reg_y_start default = 0, the canvas ver start pixel positio + +#define AFBCE_MMU_RMIF_RO_STAT 0x41c6 + +extern void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, + enum vdin_output_mif_e sel); +extern unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp); +extern void vdin_afbce_cma_release(struct vdin_dev_s *devp); +extern void vdin_afbce_config(struct vdin_dev_s *devp); +extern void vdin_afbce_maptable_init(struct vdin_dev_s *devp); +extern void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, +unsigned int rdma_enable, struct vf_entry *vfe); + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index da16b14..97d58d3 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -4327,33 +4327,4 @@ void vdin_clk_onoff(struct vdin_dev_s *devp, bool onoff) } } -void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, - enum vdin_output_mif_e sel) -{ - unsigned int offset = devp->addr_offset; - if (offset == 0) { - if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_AFBCE_BIT, 1); - } else if (sel == VDIN_OUTPUT_TO_AFBCE) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_AFBCE_BIT, 1); - } - } else { - if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_AFBCE_BIT, 1); - } else if (sel == VDIN_OUTPUT_TO_AFBCE) { - /*sel vdin1 afbce: not support in sw now, - *just reserved interface - */ - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_AFBCE_BIT, 1); - } - } -} diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h index 0d8199b..178c74a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h @@ -207,8 +207,7 @@ extern enum tvin_force_color_range_e color_range_force; extern void vdin_vlock_input_sel(unsigned int type, enum vframe_source_type_e source_type); -extern void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, - enum vdin_output_mif_e sel); + #endif diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index 14e9bc3..cf16fb1 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -263,6 +263,8 @@ static ssize_t vdin_attr_show(struct device *dev, "echo rdma_irq_cnt >/sys/class/vdin/vdinx/attr.\n"); len += sprintf(buf+len, "echo skip_vf_num 0/1/2 /sys/class/vdin/vdinx/attr.\n"); + len += sprintf(buf+len, + "echo dump_afbce storage/xxx.bin >/sys/class/vdin/vdinx/attr\n"); return len; } static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, @@ -368,6 +370,217 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) set_fs(old_fs); } +static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, + unsigned int buf_num) +{ + struct file *filp = NULL; + loff_t pos = 0; + void *buf_head = NULL; + void *buf_table = NULL; + void *buf_body = NULL; + unsigned char buff[100]; + mm_segment_t old_fs = get_fs(); + + if (buf_num >= devp->canvas_max_num) { + pr_info("%s: param error", __func__); + return; + } + + if ((devp->cma_config_flag & 0x1) && + (devp->cma_mem_alloc == 0)) { + pr_info("%s:no cma alloc mem!!!\n", __func__); + return; + } + + if (devp->cma_config_flag == 0x101) { + buf_head = codec_mm_phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = codec_mm_phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } else if (devp->cma_config_flag == 0) { + buf_head = phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } + + set_fs(KERNEL_DS); + + /*write header bin*/ + strcpy(buff, path); + strcat(buff, "_1header.bin"); + filp = filp_open(buff, O_RDWR|O_CREAT, 0666); + if (IS_ERR(filp)) { + pr_info("create %s header error.\n", buff); + return; + } + + vfs_write(filp, buf_head, devp->afbce_info->frame_head_size, &pos); + pr_info("write buffer %2d of %2u head to %s.\n", + buf_num, devp->canvas_max_num, buff); + vfs_fsync(filp, 0); + filp_close(filp, NULL); + + /*write table bin*/ + pos = 0; + strcpy(buff, path); + strcat(buff, "_1table.bin"); + filp = filp_open(buff, O_RDWR|O_CREAT, 0666); + if (IS_ERR(filp)) { + pr_info("create %s table error.\n", buff); + return; + } + vfs_write(filp, buf_table, devp->afbce_info->frame_table_size, &pos); + pr_info("write buffer %2d of %2u table to %s.\n", + buf_num, devp->canvas_max_num, buff); + vfs_fsync(filp, 0); + filp_close(filp, NULL); + + /*write body bin*/ + pos = 0; + strcpy(buff, path); + strcat(buff, "_1body.bin"); + filp = filp_open(buff, O_RDWR|O_CREAT, 0666); + if (IS_ERR(filp)) { + pr_info("create %s body error.\n", buff); + return; + } + vfs_write(filp, buf_body, devp->afbce_info->frame_body_size, &pos); + pr_info("write buffer %2d of %2u body to %s.\n", + buf_num, devp->canvas_max_num, buff); + vfs_fsync(filp, 0); + filp_close(filp, NULL); + + set_fs(old_fs); +} + +static void vdin_dump_afbce_mem(char *path, struct vdin_dev_s *devp) +{ + struct file *filp = NULL; + loff_t pos = 0; + void *buf_head = NULL; + void *buf_table = NULL; + void *buf_body = NULL; + unsigned char buff[100]; + unsigned int i; + mm_segment_t old_fs = get_fs(); + + if ((devp->cma_config_flag & 0x1) && + (devp->cma_mem_alloc == 0)) { + pr_info("%s:no cma alloc mem!!!\n", __func__); + return; + } + + if (devp->cma_config_flag == 0x101) { + buf_head = codec_mm_phys_to_virt( + devp->afbce_info->head_paddr); + buf_table = codec_mm_phys_to_virt( + devp->afbce_info->table_paddr); + buf_body = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[0]); + + pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->head_paddr, + (devp->afbce_info->table_paddr), + devp->afbce_info->fm_body_paddr[0]); + } else if (devp->cma_config_flag == 0) { + buf_head = phys_to_virt( + devp->afbce_info->head_paddr); + buf_table = phys_to_virt( + devp->afbce_info->table_paddr); + buf_body = phys_to_virt( + devp->afbce_info->fm_body_paddr[0]); + + pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->head_paddr, + (devp->afbce_info->table_paddr), + devp->afbce_info->fm_body_paddr[0]); + } + + set_fs(KERNEL_DS); + + /* write header bin start */ + strcpy(buff, path); + strcat(buff, "_header.bin"); + filp = filp_open(buff, O_RDWR|O_CREAT, 0666); + if (IS_ERR(filp)) { + pr_info("create %s header error.\n", buff); + return; + } + + for (i = 0; i < devp->vfmem_max_cnt; i++) { + vfs_write(filp, buf_head, + devp->afbce_info->frame_head_size, &pos); + buf_head += devp->afbce_info->frame_head_size; + pr_info("write buffer %2d(0x%x bytes) of %2u head to %s.\n", + i, devp->afbce_info->frame_head_size, + devp->canvas_max_num, buff); + } + vfs_fsync(filp, 0); + filp_close(filp, NULL); + /* write header bin end */ + + /* write table bin start */ + pos = 0; + strcpy(buff, path); + strcat(buff, "_table.bin"); + filp = filp_open(buff, O_RDWR|O_CREAT, 0666); + if (IS_ERR(filp)) { + pr_info("create %s table error.\n", buff); + return; + } + + for (i = 0; i < devp->vfmem_max_cnt; i++) { + vfs_write(filp, buf_table, + devp->afbce_info->frame_table_size, &pos); + buf_table += devp->afbce_info->frame_table_size; + pr_info("write buffer %2d(0x%x bytes) of %2u table to %s.\n", + i, devp->afbce_info->frame_table_size, + devp->canvas_max_num, buff); + } + vfs_fsync(filp, 0); + filp_close(filp, NULL); + /* write table bin end */ + + /* write body bin start */ + pos = 0; + strcpy(buff, path); + strcat(buff, "_body.bin"); + filp = filp_open(buff, O_RDWR|O_CREAT, 0666); + if (IS_ERR(filp)) { + pr_info("create %s body error.\n", buff); + return; + } + + for (i = 0; i < devp->vfmem_max_cnt; i++) { + vfs_write(filp, buf_body, + devp->afbce_info->frame_body_size, &pos); + buf_body += devp->afbce_info->frame_body_size; + pr_info("write buffer %2d(0x%x bytes) of %2u body to %s.\n", + i, devp->afbce_info->frame_body_size, + devp->canvas_max_num, buff); + } + vfs_fsync(filp, 0); + filp_close(filp, NULL); + /* write body bin end */ + + set_fs(old_fs); +} + static void dump_other_mem(char *path, unsigned int start, unsigned int offset) { @@ -552,6 +765,31 @@ static void vdin_dump_state(struct vdin_dev_s *devp) pr_info("dv_flag:%d;dv_config:%d,dolby_vision:%d\n", devp->dv.dv_flag, devp->dv.dv_config, devp->prop.dolby_vision); pr_info("size of struct vdin_dev_s: %d\n", devp->vdin_dev_ssize); + + if (devp->afbce_mode == 1) { + for (i = 0; i < devp->vfmem_max_cnt; i++) { + pr_info("head(%d) addr:0x%lx, size:0x%x\n", + i, devp->afbce_info->fm_head_paddr[i], + devp->afbce_info->frame_head_size); + } + pr_info("all head size: 0x%x\n", + devp->afbce_info->head_size); + + for (i = 0; i < devp->vfmem_max_cnt; i++) { + pr_info("table(%d) addr:0x%lx, size:0x%x\n", + i, devp->afbce_info->fm_table_paddr[i], + devp->afbce_info->frame_table_size); + } + pr_info("all table size: 0x%x\n", + devp->afbce_info->table_size); + + for (i = 0; i < devp->vfmem_max_cnt; i++) { + pr_info("body(%d) addr:0x%lx, size:0x%x\n", + i, devp->afbce_info->fm_body_paddr[i], + devp->afbce_info->frame_body_size); + } + } + pr_info("Vdin driver version : %s\n", VDIN_VER); } @@ -1629,6 +1867,16 @@ start_chk: pr_info("vframe_skip(%d):%d\n\n", devp->index, devp->vfp->skip_vf_num); } + } else if (!strcmp(parm[0], "dump_afbce")) { + if (parm[2] != NULL) { + unsigned int buf_num = 0; + + if (kstrtol(parm[2], 10, &val) == 0) + buf_num = val; + vdin_dump_one_afbce_mem(parm[1], devp, buf_num); + } else if (parm[1] != NULL) { + vdin_dump_afbce_mem(parm[1], devp); + } } else { pr_info("unknown command\n"); } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 8d1394e..0b7875b 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -63,6 +63,7 @@ #include "vdin_sm.h" #include "vdin_vf.h" #include "vdin_canvas.h" +#include "vdin_afbce.h" #define VDIN_DRV_NAME "vdin" #define VDIN_DEV_NAME "vdin" @@ -466,17 +467,30 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->parm.v_reverse); #ifdef CONFIG_CMA vdin_cma_malloc_mode(devp); - if (vdin_cma_alloc(devp)) { - pr_err("\nvdin%d %s fail for cma alloc fail!!!\n", - devp->index, __func__); - return; + if (devp->afbce_mode == 1) { + if (vdin_afbce_cma_alloc(devp)) { + pr_err("\nvdin%d-afbce %s fail for cma alloc fail!!!\n", + devp->index, __func__); + return; + } + } else if (devp->afbce_mode == 0) { + if (vdin_cma_alloc(devp)) { + pr_err("\nvdin%d %s fail for cma alloc fail!!!\n", + devp->index, __func__); + return; + } } #endif /* h_active/v_active will be used by bellow calling */ - if (canvas_config_mode == 1) - vdin_canvas_start_config(devp); - else if (canvas_config_mode == 2) - vdin_canvas_auto_config(devp); + if (devp->afbce_mode == 0) { + if (canvas_config_mode == 1) + vdin_canvas_start_config(devp); + else if (canvas_config_mode == 2) + vdin_canvas_auto_config(devp); + } else if (devp->afbce_mode == 1) { + vdin_afbce_maptable_init(devp); + vdin_afbce_config(devp); + } #if 0 if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) @@ -523,8 +537,14 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_hw_enable(devp->addr_offset); vdin_set_all_regs(devp); - if (is_meson_tl1_cpu() && (devp->index == 0)) - vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); + + if (is_meson_tl1_cpu()) { + if (devp->afbce_mode == 0) + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); + else if (devp->afbce_mode == 1) + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_AFBCE); + } + if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && (devp->frontend) && devp->frontend->dec_ops && @@ -630,7 +650,10 @@ void vdin_stop_dec(struct vdin_dev_s *devp) vf_unreg_provider(&devp->vprov); devp->dv.dv_config = 0; #ifdef CONFIG_CMA - vdin_cma_release(devp); + if (devp->afbce_mode == 1) + vdin_afbce_cma_release(devp); + else if (devp->afbce_mode == 0) + vdin_cma_release(devp); #endif vdin_dolby_addr_release(devp, devp->vfp->size); @@ -1508,8 +1531,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), - (next_wr_vfe->vf.canvas0Addr&0xff)); + if (devp->afbce_mode == 0) + vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), + (next_wr_vfe->vf.canvas0Addr&0xff)); + else if (devp->afbce_mode == 1) + vdin_afbce_set_next_frame(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); + /* prepare for chroma canvas*/ if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) @@ -1700,8 +1728,13 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), - (next_wr_vfe->vf.canvas0Addr&0xff)); + if (devp->afbce_mode == 0) + vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), + (next_wr_vfe->vf.canvas0Addr&0xff)); + else if (devp->afbce_mode == 1) + vdin_afbce_set_next_frame(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); + if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) vdin_set_chma_canvas_id(devp, @@ -2471,6 +2504,25 @@ static int vdin_drv_probe(struct platform_device *pdev) else vdevp->color_depth_mode = 0; + /*set afbce mode*/ + ret = of_property_read_u32(pdev->dev.of_node, + "afbce_bit_mode", &vdevp->afbce_mode); + if (ret) { + vdevp->afbce_mode = 0; + pr_info("no afbce mode found, use normal mode\n"); + } else { + if ((is_meson_tl1_cpu()) && (vdevp->index == 0)) { + /* just use afbce at vdin0 */ + pr_info("afbce mode = %d\n", vdevp->afbce_mode); + vdevp->afbce_info = devm_kzalloc(vdevp->dev, + sizeof(struct vdin_afbce_s), GFP_KERNEL); + if (!vdevp->afbce_info) + goto fail_kzalloc_vdev; + } else { + vdevp->afbce_mode = 0; + pr_info("get afbce from dts, but chip cannot support\n"); + } + } /*vdin urgent en*/ ret = of_property_read_u32(pdev->dev.of_node, "urgent_en", &urgent_en); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 1ee8eb9..2e1f5a6 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -161,6 +161,25 @@ struct vdin_dv_s { bool dv_config; bool dv_crc_check;/*0:fail;1:ok*/ }; + +struct vdin_afbce_s { + unsigned int head_size;/*all head size*/ + unsigned int table_size;/*all table size*/ + unsigned int frame_head_size;/*1 frame head size*/ + unsigned int frame_table_size;/*1 frame table size*/ + unsigned int frame_body_size;/*1 frame body size*/ + unsigned long head_paddr; + unsigned long table_paddr; + /*every frame head addr*/ + unsigned long fm_head_paddr[VDIN_CANVAS_MAX_CNT]; + /*every frame tab addr*/ + unsigned long fm_table_paddr[VDIN_CANVAS_MAX_CNT]; + /*every body head addr*/ + unsigned long fm_body_paddr[VDIN_CANVAS_MAX_CNT]; + //unsigned int cur_af;/*current afbce number*/ + //unsigned int last_af;/*last afbce number*/ +}; + struct vdin_dev_s { struct cdev cdev; struct device *dev; @@ -173,6 +192,8 @@ struct vdin_dev_s { struct vframe_provider_s vprov; struct vdin_dv_s dv; + struct vdin_afbce_s *afbce_info; + /* 0:from gpio A,1:from csi2 , 2:gpio B*/ enum bt_path_e bt_path; @@ -294,6 +315,12 @@ struct vdin_dev_s { */ unsigned int game_mode; unsigned int rdma_enable; + /* afbce_mode: (amlogic frame buff compression encoder) + * 0: normal mode, not use afbce + * 1: use afbce non-mmu mode: head/body addr set by code + * 2: use afbce mmu mode: head set by code, body addr assigning by hw + */ + unsigned int afbce_mode; unsigned int canvas_config_mode; bool prehsc_en; bool vshrk_en; diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_regs.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_regs.h index eaf40b0..aaf4173 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_regs.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_regs.h @@ -717,6 +717,7 @@ /*g12a new add end*/ +#define VDIN_WRARB_REQEN_SLV 0x12c1 /* #define VDIN_SCALE_COEF_IDX 0x1200 */ /* #define VDIN_SCALE_COEF 0x1201 */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c index 6204a83..afd3446 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c @@ -387,6 +387,7 @@ int vf_pool_init(struct vf_pool *p, int size) log_state = false; break; } + master->af_num = i; master->status = VF_STATUS_WL; master->flag |= VF_FLAG_NORMAL_FRAME; master->flag &= (~VF_FLAG_FREEZED_FRAME); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.h index 75a1a77..02b3756 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.h @@ -106,6 +106,7 @@ struct vf_entry { enum vf_status_e status; struct list_head list; unsigned int flag; + unsigned char af_num;/*afbce num*/ }; struct vf_pool { -- 2.7.4