blob: 23026df929464e6ca5e57b763530f616c7cebaa0 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
#include <linux/amlogic/media/vpu/vpu.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/highmem.h>
#include <linux/page-flags.h>
#include <linux/vmalloc.h>
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
#include <linux/sched/clock.h>
#include <linux/amlogic/media/video_sink/video.h>
#include <linux/amlogic/media/amdolbyvision/dolby_vision.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"
#include "vdin_dv.h"
#define VDIN2_DV_HSIZE 2048
#define VDIN2_DV_VSIZE 10
#define DBG_ON 0
#define dprintk(level, fmt, arg...) \
do { \
if (vdin_dbg_en >= (level)) \
pr_info("vdin:dv " fmt, ## arg); \
} while (0)
void vdin_wrmif2_enable(struct vdin_dev_s *devp, u32 en)
{
u32 offset = 0;
if (devp->dtdata->hw_ver != VDIN_HW_T7)
return;
/*clear int status*/
wr_bits(0, VDIN2_WR_CTRL, 1,
DIRECT_DONE_CLR_BIT, DIRECT_DONE_CLR_WID);
wr_bits(0, VDIN2_WR_CTRL, 0,
DIRECT_DONE_CLR_BIT, DIRECT_DONE_CLR_WID);
/*write mif2 int*/
if (en)
wr_bits(offset, VDIN_TOP_DOUBLE_CTRL, 0x3,
VDIN1_INT_MASK_BIT, 3);
else
wr_bits(offset, VDIN_TOP_DOUBLE_CTRL, 0x7,
VDIN1_INT_MASK_BIT, 3);
if (en)
wr_bits(offset, VDIN2_WR_CTRL, 1, 8, 1);
else
wr_bits(offset, VDIN2_WR_CTRL, 0, 8, 1);
dprintk(1, "%s %d\n", __func__, en);
}
/*
* mode_10b:0:8bit 1:10bit;
* in_fmt: [1:0]: 0->422; 1->444
*
*/
void vdin_wrmif2_initial(struct vdin_dev_s *devp)
{
u32 offset = 0;
u32 hsize = VDIN2_DV_HSIZE;
u32 vsize = VDIN2_DV_VSIZE;
u32 md_10b = 0;/*0:8bit 1:10bit*/
u32 in_fmt = MIF_FMT_NV12_21;
if (devp->dtdata->hw_ver != VDIN_HW_T7)
return;
/* vdin2 mif sel t7 vdin1 normal is meta data*/
wr_bits(offset, VDIN_TOP_DOUBLE_CTRL, WR_SEL_VDIN1_NOR, MIF2_OUT_SEL_BIT,
VDIN_REORDER_SEL_WID);
wr_bits(offset, VDIN_TOP_DOUBLE_CTRL, WR_SEL_VDIN1_SML, MIF1_OUT_SEL_BIT,
VDIN_REORDER_SEL_WID);
/* scope */
wr_bits(offset, VDIN2_WR_H_START_END, 0, 16, 13);//v start
wr_bits(offset, VDIN2_WR_H_START_END, hsize - 1, 0, 13);//v end
wr_bits(offset, VDIN2_WR_V_START_END, 0, 16, 13);//v start
wr_bits(offset, VDIN2_WR_V_START_END, vsize - 1, 0, 13);//v end
wr_bits(offset, VDIN2_WR_CTRL2, md_10b, 19, 1);//10bit mode
wr_bits(offset, VDIN2_WR_CTRL2, 1, 18, 1);//data_ext_en
wr_bits(offset, VDIN2_WR_CTRL, 1, 19, 1); //swap between 64bit
wr_bits(offset, VDIN2_WR_CTRL, in_fmt, 12, 2); //vdin_wr_format
wr_bits(offset, VDIN2_WR_CTRL, 1, 9, 1); //vdin_wr_req_urgent
//wr_bits(offset, VDIN2_WR_CTRL, 1, 8, 1); //vdin_wr_req_en
wr_bits(offset, VDIN2_WR_CTRL, 0, 27, 1); //eol from pixel count
wr_bits(0, VDIN2_WR_URGENT_CTRL, 1, 9, 1);/*write done last sel*/
wr_bits(0, VDIN2_WR_URGENT_CTRL, 1, 8, 1);/*reg Bvalid enable*/
wr_bits(0, VDIN2_WR_CTRL, 1,
DIRECT_DONE_CLR_BIT, DIRECT_DONE_CLR_WID);
wr_bits(0, VDIN2_WR_CTRL, 0,
DIRECT_DONE_CLR_BIT, DIRECT_DONE_CLR_WID);
}
/*
* for t7 dv meta data issue
*/
void vdin_wrmif2_addr_update(struct vdin_dev_s *devp)
{
u32 offset = 0;
u32 stride_luma;
u32 hsize = VDIN2_DV_HSIZE;
u32 baddr;
if (devp->dtdata->hw_ver != VDIN_HW_T7)
return;
baddr = devp->dv.meta_data_raw_pbuff0;
if (!baddr)
dprintk(0, "err: meta_data_raw_pbuff0\n");
stride_luma = ((hsize * 8) + 511) >> 9;
/*dprintk(0, "%s baddr:0x%x strid:0x%x\n", __func__,*/
/* baddr, stride_luma);*/
wr(offset, VDIN2_WR_BADDR_LUMA, baddr >> 4);
wr(offset, VDIN2_WR_STRIDE_LUMA, stride_luma << 2);
}
irqreturn_t vdin_wrmif2_dvmeta_wr_done_isr(int irq, void *dev_id)
{
/*struct vdin_dev_s *devp = (struct vdin_dev_s *)dev_id;*/
irqreturn_t sts = IRQ_HANDLED;
struct vdin_dev_s *devp = (struct vdin_dev_s *)dev_id;
char *src_dv_meta_vaddr;
u32 len_raw_data;
char *dst_dv_meta_vaddr;
u32 src_idx = 0, dst_idx = 0;
/*u32 meta_len = 0;*/
u8 data;
u32 max_pkt = 15;
static u32 irq_cnt;
devp->meta_wr_done_irq_cnt++;
if (devp->dtdata->hw_ver != VDIN_HW_T7)
return sts;
src_dv_meta_vaddr = devp->dv.meta_data_raw_vbuff0;
dst_dv_meta_vaddr = devp->dv.meta_data_raw_buff1;
if (IS_ERR_OR_NULL(src_dv_meta_vaddr) ||
IS_ERR_OR_NULL(dst_dv_meta_vaddr)) {
if (irq_cnt % dv_dbg_log_du)
dprintk(0, "%s err: null meta addr\n", __func__);
return IRQ_NONE;
}
/* not dv input */
if (!vdin_is_dolby_signal_in(devp))
return IRQ_NONE;
dma_sync_single_for_device(&devp->this_pdev->dev,
devp->dv.meta_data_raw_pbuff0,
K_DV_META_RAW_BUFF0,
DMA_TO_DEVICE);
/*for debug*/
//if ((irq_cnt % dv_dbg_log_du) == 0)
// vdin_dolby_pr_meta_data(src_dv_meta_vaddr, 128);
len_raw_data = 128 * max_pkt * 8; /*K_DV_META_RAW_BUFF0;*/
//if ((dv_dbg_log & (1 << 5)) && (irq_cnt % dv_dbg_log_du))
// pr_info("\n\n");
dst_idx = 0;
/* write meta raw data to meta_data_raw_buff1 */
for (src_idx = 0; src_idx < len_raw_data;) {
data = 0;
/* 8 bytes raw data got one byte meta*/
if (src_dv_meta_vaddr[src_idx + 0] == 0x80)
data |= 0x1;
if (src_dv_meta_vaddr[src_idx + 1] == 0x80)
data |= 0x2;
if (src_dv_meta_vaddr[src_idx + 2] == 0x80)
data |= 0x4;
if (src_dv_meta_vaddr[src_idx + 3] == 0x80)
data |= 0x8;
if (src_dv_meta_vaddr[src_idx + 4] == 0x80)
data |= 0x10;
if (src_dv_meta_vaddr[src_idx + 5] == 0x80)
data |= 0x20;
if (src_dv_meta_vaddr[src_idx + 6] == 0x80)
data |= 0x40;
if (src_dv_meta_vaddr[src_idx + 7] == 0x80)
data |= 0x80;
dst_dv_meta_vaddr[dst_idx] = data;
dst_idx++;
src_idx += 8;
}
//if ((dv_dbg_log & (1 << 5)) && (irq_cnt % dv_dbg_log_du))
// vdin_dolby_pr_meta_data(dst_dv_meta_vaddr,
// 6 * DV_META_PACKET_SIZE);
irq_cnt++;
return sts;
}