vdin: add afbce function for tl1 [1/1]
authorxuhua zhang <xuhua.zhang@amlogic.com>
Tue, 9 Oct 2018 09:21:14 +0000 (17:21 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 29 Oct 2018 11:21:10 +0000 (04:21 -0700)
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 <xuhua.zhang@amlogic.com>
13 files changed:
MAINTAINERS
arch/arm/boot/dts/amlogic/tl1_pxp.dts
drivers/amlogic/media/vin/tvin/vdin/Makefile
drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c [new file with mode: 0644]
drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h [new file with mode: 0644]
drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c
drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h
drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c
drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c
drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h
drivers/amlogic/media/vin/tvin/vdin/vdin_regs.h
drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c
drivers/amlogic/media/vin/tvin/vdin/vdin_vf.h

index c0b9410..608febc 100644 (file)
@@ -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 <xuhua.zhang@amlogic.com>
+F:     drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c
+F:     drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h
index 7068dfb..50b7fe1 100644 (file)
@@ -88,7 +88,7 @@
                //      compatible = "shared-dma-pool";
                //      reusable;
                        /* 3840x2160x4x4 ~=128 M */
-               //      size = <0x8000000>;
+               //      size = <0xc400000>;
                //      alignment = <0x400000>;
                //};
 
                 * 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 {
index ee325b5..7f0c556 100644 (file)
@@ -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 (file)
index 0000000..eaa9d73
--- /dev/null
@@ -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 <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/cma.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/dma-contiguous.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/slab.h>
+#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
+#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 (file)
index 0000000..feb2d08
--- /dev/null
@@ -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
+
index da16b14..97d58d3 100644 (file)
@@ -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);
-               }
-       }
-}
index 0d8199b..178c74a 100644 (file)
@@ -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
 
index 14e9bc3..cf16fb1 100644 (file)
@@ -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");
        }
index 8d1394e..0b7875b 100644 (file)
@@ -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);
index 1ee8eb9..2e1f5a6 100644 (file)
@@ -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;
index eaf40b0..aaf4173 100644 (file)
 
 /*g12a new add end*/
 
+#define VDIN_WRARB_REQEN_SLV       0x12c1
 
 /* #define VDIN_SCALE_COEF_IDX                        0x1200 */
 /* #define VDIN_SCALE_COEF                            0x1201 */
index 6204a83..afd3446 100644 (file)
@@ -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);
index 75a1a77..02b3756 100644 (file)
@@ -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 {