vdin: fixed the issue of mem mapping from vmap. [1/1]

PD#SWPL-6196

Problem:
the memory issue cause to kernel crash.

Solution:
1. add flush cache when the mem oper end.
2. unmap addr which from vmap in vdin driver.

Verify:
X301

Change-Id: Id6efe2b009fe64ad753d51eb06784bd4e66f5e87
Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
This commit is contained in:
Nanxin Qin
2019-03-28 23:43:08 +08:00
committed by Tao Zeng
parent 325a18ae9c
commit d1f81490a2
6 changed files with 285 additions and 196 deletions

View File

@@ -778,6 +778,7 @@ static int picdec_memset_phyaddr(ulong phys, u32 size, u32 val)
if (!p)
return -1;
memset(p, val, span);
codec_mm_dma_flush(p, span, DMA_TO_DEVICE);
codec_mm_unmap_phyaddr(p);
}
return 0;
@@ -887,6 +888,7 @@ static int copy_phybuf_to_file(ulong phys, u32 size,
p = codec_mm_vmap(addr, span);
if (!p)
return -1;
codec_mm_dma_flush(p, span, DMA_FROM_DEVICE);
vfs_write(fp, (char *)p,
span, &pos);
pos += span;

View File

@@ -580,6 +580,7 @@ void vdin_afbce_maptable_init(struct vdin_dev_s *devp)
unsigned int *vtable = NULL;
unsigned int body;
unsigned int size;
void *p = NULL;
size = roundup(devp->afbce_info->frame_body_size, 4096);
@@ -599,19 +600,40 @@ void vdin_afbce_maptable_init(struct vdin_dev_s *devp)
else
vtable = phys_to_virt(ptable);
} else {
vtable = (unsigned int *)codec_mm_vmap(
ptable,
vtable = (unsigned int *)vdin_vmap(ptable,
devp->afbce_info->frame_table_size);
if (vdin_dbg_en) {
pr_err("----vdin vmap v: %p, p: %lx, size: %d\n",
vtable, ptable,
devp->afbce_info->frame_table_size);
}
if (!vtable) {
pr_err("vmap fail, size: %d.\n",
devp->afbce_info->frame_table_size);
return;
}
}
p = vtable;
body = devp->afbce_info->fm_body_paddr[i]&0xffffffff;
for (j = 0; j < size; j += 4096) {
*vtable = ((j + body) >> 12) & 0x000fffff;
vtable++;
}
/* clean tail data. */
memset(vtable, 0, devp->afbce_info->frame_table_size -
((char *)vtable - (char *)p));
vdin_dma_flush(devp, p,
devp->afbce_info->frame_table_size,
DMA_TO_DEVICE);
if (highmem_flag)
codec_mm_unmap_phyaddr((void *)vtable);
vdin_unmap_phyaddr(p);
vtable = NULL;
}
}

View File

@@ -23,6 +23,9 @@
#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/amlogic/media/video_sink/video.h>
@@ -160,6 +163,79 @@ static unsigned int vpu_reg_27af = 0x3;
#define pr_info(fmt, ...)
#endif
u8 *vdin_vmap(ulong addr, u32 size)
{
u8 *vaddr = NULL;
struct page **pages = NULL;
u32 i, npages, offset = 0;
ulong phys, page_start;
/*pgprot_t pgprot = pgprot_noncached(PAGE_KERNEL);*/
pgprot_t pgprot = PAGE_KERNEL;
if (!PageHighMem(phys_to_page(addr)))
return phys_to_virt(addr);
offset = offset_in_page(addr);
page_start = addr - offset;
npages = DIV_ROUND_UP(size + offset, PAGE_SIZE);
pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
if (!pages)
return NULL;
for (i = 0; i < npages; i++) {
phys = page_start + i * PAGE_SIZE;
pages[i] = pfn_to_page(phys >> PAGE_SHIFT);
}
vaddr = vmap(pages, npages, VM_MAP, pgprot);
if (!vaddr) {
pr_err("the phy(%lx) vmaped fail, size: %d\n",
page_start, npages << PAGE_SHIFT);
kfree(pages);
return NULL;
}
kfree(pages);
if (vdin_dbg_en) {
pr_info("[vdin HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n",
__func__, page_start, vaddr, npages << PAGE_SHIFT);
}
return vaddr + offset;
}
void vdin_unmap_phyaddr(u8 *vaddr)
{
void *addr = (void *)(PAGE_MASK & (ulong)vaddr);
if (is_vmalloc_or_module_addr(vaddr)) {
if (vdin_dbg_en)
pr_info("----vdin unmap v: %p\n", addr);
vunmap(addr);
}
}
void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr,
int size, enum dma_data_direction dir)
{
ulong phy_addr;
if (is_vmalloc_or_module_addr(vaddr)) {
phy_addr = page_to_phys(vmalloc_to_page(vaddr))
+ offset_in_page(vaddr);
if (phy_addr && PageHighMem(phys_to_page(phy_addr))) {
if (vdin_dbg_en)
pr_info("----vdin flush v: %p, p: %lx\n",
vaddr, phy_addr);
dma_sync_single_for_device(&devp->this_pdev->dev,
phy_addr, size, dir);
}
return;
}
}
/*reset reg mif value of vdin0:
* VDIN_WR_CTRL \VDIN_COM_CTRL0\ VDIN_MISC_CTRL
*/
@@ -3550,12 +3626,12 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size)
if ((devp->cma_config_flag & 0x100)
&& devp->cma_config_en)
devp->vfp->dv_buf_ori[index] =
codec_mm_vmap(devp->vfmem_start[index] +
vdin_vmap(devp->vfmem_start[index] +
devp->vfmem_size-dolby_size_byte,
dolby_size_byte);
else
devp->vfp->dv_buf_ori[index] =
codec_mm_vmap(devp->mem_start +
vdin_vmap(devp->mem_start +
devp->mem_size -
dolby_size_byte *
(devp->canvas_max_num - index),
@@ -3572,15 +3648,32 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size)
void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size)
{
unsigned int alloc_size;
int highmem_flag;
int index;
alloc_size = dolby_size_byte*size;
if (devp->dv.dv_dma_vaddr)
dma_free_coherent(&devp->this_pdev->dev, alloc_size,
devp->dv.dv_dma_vaddr, devp->dv.dv_dma_paddr);
devp->dv.dv_dma_vaddr = NULL;
if (devp->cma_config_flag & 0x100)
highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0]));
else
highmem_flag = PageHighMem(phys_to_page(devp->mem_start));
if (highmem_flag) {
for (index = 0; index < size; index++) {
if (devp->vfp->dv_buf_ori[index]) {
vdin_unmap_phyaddr(
devp->vfp->dv_buf_ori[index]);
devp->vfp->dv_buf_ori[index] = NULL;
}
}
}
}
static void vdin_dolby_metadata_swap(char *buf)
static void vdin_dolby_metadata_swap(struct vdin_dev_s *devp, char *buf)
{
char ext;
unsigned int i, j;
@@ -3592,6 +3685,8 @@ static void vdin_dolby_metadata_swap(char *buf)
buf[i*16+15-j] = ext;
}
}
vdin_dma_flush(devp, buf, dolby_size_byte, DMA_TO_DEVICE);
}
#define swap32(num) \
@@ -3689,7 +3784,8 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index)
for (count = 0; count < META_RETRY_MAX; count++) {
if (dv_dbg_mask & DV_READ_MODE_AXI) {
memcpy(p, devp->vfp->dv_buf_vmem[index], 128);
vdin_dolby_metadata_swap(c);
vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE);
vdin_dolby_metadata_swap(devp, c);
} else {
wr(offset, VDIN_DOLBY_DSC_CTRL3, 0);
wr(offset, VDIN_DOLBY_DSC_CTRL2, 0xd180c0d5);
@@ -3702,7 +3798,9 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index)
if ((i == 31) && (multimeta_flag == 0))
break;
}
vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE);
}
meta_size = (c[3] << 8) | c[4];
crc = p[31];
crc_result = crc32(0, p, 124);

View File

@@ -17,7 +17,11 @@
#ifndef __TVIN_VDIN_CTL_H
#define __TVIN_VDIN_CTL_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 "vdin_drv.h"
#define DV_SWAP_EN (1 << 0)
@@ -111,10 +115,16 @@ struct ldim_max_s {
#endif
extern unsigned int game_mode;
extern bool vdin_dbg_en;
/* ************************************************************************ */
/* ******** GLOBAL FUNCTION CLAIM ******** */
/* ************************************************************************ */
extern u8 *vdin_vmap(ulong addr, u32 size);
extern void vdin_unmap_phyaddr(u8 *vaddr);
extern void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr,
int size, enum dma_data_direction dir);
extern void vdin_set_vframe_prop_info(struct vframe_s *vf,
struct vdin_dev_s *devp);
extern void LDIM_Initial_2(int pic_h, int pic_v, int BLK_Vnum,

View File

@@ -343,14 +343,15 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp,
for (j = 0; j < count; j++) {
highaddr = phys + j * devp->canvas_w;
buf = codec_mm_vmap(highaddr, span);
buf = vdin_vmap(highaddr, span);
if (!buf) {
pr_info("codec_mm_vmap error\n");
pr_info("vdin_vmap error\n");
return;
}
vdin_dma_flush(devp, buf, span, DMA_FROM_DEVICE);
vfs_write(filp, buf, span, &pos);
codec_mm_unmap_phyaddr(buf);
vdin_unmap_phyaddr(buf);
}
pr_info("high-mem write buffer %2d of %2u to %s.\n",
buf_num, devp->canvas_max_num, path);
@@ -448,14 +449,16 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp)
for (j = 0; j < count; j++) {
highaddr = phys + j * devp->canvas_w;
buf = codec_mm_vmap(highaddr, span);
buf = vdin_vmap(highaddr, span);
if (!buf) {
pr_info("codec_mm_vmap error\n");
pr_info("vdin_vmap error\n");
return;
}
vdin_dma_flush(devp, buf, span,
DMA_FROM_DEVICE);
vfs_write(filp, buf, span, &pos);
codec_mm_unmap_phyaddr(buf);
vdin_unmap_phyaddr(buf);
}
pr_info("high-mem write buffer %2d of %2u to %s.\n",
i, devp->canvas_max_num, path);
@@ -496,10 +499,8 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
return;
}
if (devp->cma_config_flag == 0x101)
highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0]));
else
highmem_flag = PageHighMem(phys_to_page(devp->mem_start));
highmem_flag = PageHighMem(
phys_to_page(devp->afbce_info->fm_body_paddr[0]));
if (highmem_flag == 0) {
/*low mem area*/
@@ -532,11 +533,11 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
} else {
/*high mem area*/
pr_info("high mem area\n");
buf_head = codec_mm_vmap(
buf_head = vdin_vmap(
devp->afbce_info->fm_head_paddr[buf_num],
devp->afbce_info->frame_head_size);
buf_table = codec_mm_vmap(
buf_table = vdin_vmap(
devp->afbce_info->fm_table_paddr[buf_num],
devp->afbce_info->frame_table_size);
@@ -557,8 +558,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
return;
}
vdin_dma_flush(devp, buf_head,
devp->afbce_info->frame_head_size,
DMA_FROM_DEVICE);
vfs_write(filp, buf_head, devp->afbce_info->frame_head_size, &pos);
codec_mm_unmap_phyaddr(buf_head);
if (highmem_flag)
vdin_unmap_phyaddr(buf_head);
pr_info("write buffer %2d of %2u head to %s.\n",
buf_num, devp->canvas_max_num, buff);
vfs_fsync(filp, 0);
@@ -573,8 +578,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
pr_info("create %s table error.\n", buff);
return;
}
vdin_dma_flush(devp, buf_table,
devp->afbce_info->frame_table_size,
DMA_FROM_DEVICE);
vfs_write(filp, buf_table, devp->afbce_info->frame_table_size, &pos);
codec_mm_unmap_phyaddr(buf_table);
if (highmem_flag)
vdin_unmap_phyaddr(buf_table);
pr_info("write buffer %2d of %2u table to %s.\n",
buf_num, devp->canvas_max_num, buff);
vfs_fsync(filp, 0);
@@ -600,27 +609,29 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
for (j = 0; j < count; j++) {
highaddr = phys + j * span;
vbuf = codec_mm_vmap(highaddr, span);
vbuf = vdin_vmap(highaddr, span);
if (!vbuf) {
pr_info("codec_mm_vmap error\n");
pr_info("vdin_vmap error\n");
return;
}
vdin_dma_flush(devp, vbuf, span, DMA_FROM_DEVICE);
vfs_write(filp, vbuf, span, &pos);
codec_mm_unmap_phyaddr(vbuf);
vdin_unmap_phyaddr(vbuf);
}
if (remain) {
span = devp->afbce_info->frame_body_size - remain;
highaddr = phys + span;
vbuf = codec_mm_vmap(highaddr, remain);
vbuf = vdin_vmap(highaddr, remain);
if (!vbuf) {
pr_info("codec_mm_vmap1 error\n");
pr_info("vdin_vmap1 error\n");
return;
}
vfs_write(filp, vbuf, span, &pos);
codec_mm_unmap_phyaddr(vbuf);
vdin_dma_flush(devp, vbuf, remain, DMA_FROM_DEVICE);
vfs_write(filp, vbuf, remain, &pos);
vdin_unmap_phyaddr(vbuf);
}
}
pr_info("write buffer %2d of %2u body to %s.\n",
@@ -631,119 +642,6 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
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)
{
@@ -1101,21 +999,30 @@ static void vdin_dump_histgram(struct vdin_dev_s *devp)
}
/*type: 1:nv21 2:yuv422 3:yuv444*/
static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type,
char *path)
{
char *md_path_head = "/storage/B8F7-DBD0/afbce/a0_1header.bin";
char *md_path_body = "/storage/B8F7-DBD0/afbce/a0_1body.bin";
unsigned int i;
char md_path_head[100], md_path_body[100];
unsigned int i, j;
int highmem_flag = 0;
unsigned int size = 0;
unsigned int span = 0;
unsigned int remain = 0;
unsigned int count = 0;
unsigned long highaddr;
unsigned long phys;
long val;
struct file *filp = NULL;
loff_t pos = 0;
mm_segment_t old_fs;
void *head_dts = NULL;
void *body_dts = NULL;
void *vbuf = NULL;
if (kstrtol(type, 10, &val) < 0)
return;
if (!path)
return;
if (!devp->curr_wr_vfe) {
devp->curr_wr_vfe = provider_vf_get(devp->vfp);
@@ -1125,6 +1032,9 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
}
}
sprintf(md_path_head, "%s_1header.bin", path);
sprintf(md_path_body, "%s_1body.bin", path);
i = devp->curr_wr_vfe->af_num;
devp->curr_wr_vfe->vf.type = VIDTYPE_VIU_SINGLE_PLANE |
VIDTYPE_VIU_FIELD | VIDTYPE_COMPRESS | VIDTYPE_SCATTER;
@@ -1146,8 +1056,18 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
devp->curr_wr_vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i];
devp->curr_wr_vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i];
head_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_head_paddr[i]);
body_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_body_paddr[i]);
highmem_flag = PageHighMem(
phys_to_page(devp->afbce_info->fm_body_paddr[0]));
if (highmem_flag == 0) {
pr_info("low mem area\n");
head_dts = codec_mm_phys_to_virt(
devp->afbce_info->fm_head_paddr[i]);
} else {
pr_info("high mem area\n");
head_dts = vdin_vmap(
devp->afbce_info->fm_head_paddr[i],
devp->afbce_info->frame_head_size);
}
old_fs = get_fs();
set_fs(KERNEL_DS);
@@ -1160,6 +1080,8 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
size = vfs_read(filp, head_dts,
devp->afbce_info->frame_head_size, &pos);
if (highmem_flag)
vdin_unmap_phyaddr(head_dts);
vfs_fsync(filp, 0);
filp_close(filp, NULL);
@@ -1175,8 +1097,30 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
return;
}
size = vfs_read(filp, body_dts,
devp->afbce_info->frame_body_size, &pos);
if (highmem_flag == 0) {
body_dts = codec_mm_phys_to_virt(
devp->afbce_info->fm_body_paddr[i]);
size = vfs_read(filp, body_dts,
devp->afbce_info->frame_body_size, &pos);
} else {
span = SZ_1M;
count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span);
remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span);
phys = devp->afbce_info->fm_body_paddr[i];
for (j = 0; j < count; j++) {
highaddr = phys + j * span;
vbuf = vdin_vmap(highaddr, span);
if (!vbuf) {
pr_info("vdin_vmap error\n");
return;
}
vfs_read(filp, vbuf, span, &pos);
vdin_unmap_phyaddr(vbuf);
}
}
vfs_fsync(filp, 0);
filp_close(filp, NULL);
@@ -1187,6 +1131,7 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type)
vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
}
static void vdin_write_mem(
struct vdin_dev_s *devp, char *type,
char *path, char *md_path)
@@ -1272,13 +1217,14 @@ static void vdin_write_mem(
span = devp->canvas_active_w;
for (j = 0; j < count; j++) {
highaddr = addr + j * devp->canvas_w;
dts = codec_mm_vmap(highaddr, span);
dts = vdin_vmap(highaddr, span);
if (!dts) {
pr_info("codec_mm_vmap error\n");
pr_info("vdin_vmap error\n");
return;
}
vfs_read(filp, dts, span, &pos);
codec_mm_unmap_phyaddr(dts);
vdin_dma_flush(devp, dts, span, DMA_TO_DEVICE);
vdin_unmap_phyaddr(dts);
}
vfs_fsync(filp, 0);
filp_close(filp, NULL);
@@ -1802,8 +1748,8 @@ start_chk:
} else if (!strcmp(parm[0], "force_recycle")) {
devp->flags |= VDIN_FLAG_FORCE_RECYCLE;
} else if (!strcmp(parm[0], "read_pic_afbce")) {
if (parm[1])
vdin_write_afbce_mem(devp, parm[1]);
if (parm[1] && parm[2])
vdin_write_afbce_mem(devp, parm[1], parm[2]);
else
pr_err("miss parameters.\n");
} else if (!strcmp(parm[0], "read_pic")) {
@@ -2172,7 +2118,7 @@ start_chk:
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);
vdin_dump_one_afbce_mem(parm[1], devp, 0);
}
} else {
pr_info("unknown command\n");

View File

@@ -135,7 +135,7 @@ MODULE_PARM_DESC(game_mode_phlock_switch_frames,
"game mode switch <n> frames for phase_lock");
#endif
static bool vdin_dbg_en;
bool vdin_dbg_en;
module_param(vdin_dbg_en, bool, 0664);
MODULE_PARM_DESC(vdin_dbg_en, "enable/disable vdin debug information");
@@ -642,14 +642,6 @@ void vdin_start_dec(struct vdin_dev_s *devp)
#endif
vf_notify_receiver(devp->name,
VFRAME_EVENT_PROVIDER_START, NULL);
if ((devp->parm.port != TVIN_PORT_VIU1) ||
(viu_hw_irq != 0)) {
/*enable irq */
enable_irq(devp->irq);
if (vdin_dbg_en)
pr_info("****[%s]enable_irq ifdef VDIN_V2****\n",
__func__);
}
if (vdin_dbg_en)
pr_info("****[%s]ok!****\n", __func__);
@@ -675,7 +667,6 @@ void vdin_start_dec(struct vdin_dev_s *devp)
if ((devp->afbce_mode == 1) && is_meson_tl1_cpu() &&
(devp->h_active >= 1920) && (devp->v_active >= 1080)) {
spin_lock_init(&tl1_preview_lock);
tl1_vdin1_preview_flag = 1;
max_ignore_frames[devp->index] = 9;
}
@@ -745,14 +736,16 @@ void vdin_stop_dec(struct vdin_dev_s *devp)
if (is_meson_tl1_cpu() && (devp->afbce_mode == 1))
vdin_afbce_hw_disable();
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
vdin_dolby_addr_release(devp, devp->vfp->size);
#endif
#ifdef CONFIG_CMA
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);
switch_vpu_mem_pd_vmod(devp->addr_offset?VPU_VIU_VDIN1:VPU_VIU_VDIN0,
VPU_MEM_POWER_DOWN);
memset(&devp->prop, 0, sizeof(struct tvin_sig_property_s));
@@ -824,18 +817,7 @@ int start_tvin_service(int no, struct vdin_parm_s *para)
else
return -EBUSY;
}
if ((para->port != TVIN_PORT_VIU1) ||
(viu_hw_irq != 0)) {
ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED,
devp->irq_name, (void *)devp);
if (ret != 0) {
pr_info("vdin_v4l2_isr request irq error.\n");
return -1;
}
devp->flags |= VDIN_FLAG_ISR_REQ;
/*disable vsync irq until vdin configured completely*/
disable_irq_nosync(devp->irq);
}
vdin_clk_onoff(devp, true);
/*config the vdin use default value*/
vdin_set_default_regmap(devp->addr_offset);
@@ -917,6 +899,16 @@ int start_tvin_service(int no, struct vdin_parm_s *para)
devp->flags |= VDIN_FLAG_DEC_OPENED;
devp->flags |= VDIN_FLAG_DEC_STARTED;
if ((para->port != TVIN_PORT_VIU1) ||
(viu_hw_irq != 0)) {
ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED,
devp->irq_name, (void *)devp);
if (ret != 0) {
pr_info("vdin_v4l2_isr request irq error.\n");
return -1;
}
devp->flags |= VDIN_FLAG_ISR_REQ;
}
return 0;
}
EXPORT_SYMBOL(start_tvin_service);
@@ -2373,6 +2365,16 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
vdin_start_dec(devp);
if ((devp->parm.port != TVIN_PORT_VIU1) ||
(viu_hw_irq != 0)) {
/*enable irq */
enable_irq(devp->irq);
if (vdin_dbg_en)
pr_info("****[%s]enable_irq ifdef VDIN_V2****\n",
__func__);
}
devp->flags |= VDIN_FLAG_DEC_STARTED;
if (vdin_dbg_en)
pr_info("TVIN_IOC_START_DEC port %s, decode started ok\n\n",
@@ -2383,29 +2385,19 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mutex_lock(&devp_vdin1->fe_lock);
if ((tl1_vdin1_preview_flag == 1) &&
!(devp_vdin1->flags & VDIN_FLAG_DEC_STARTED)) {
msleep(150);
/*msleep(150);*/
devp_vdin1->flags |= VDIN_FLAG_FS_OPENED;
if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) {
ret = request_irq(devp_vdin1->irq, vdin_isr,
IRQF_SHARED,
devp_vdin1->irq_name,
(void *)devp_vdin1);
if (ret != 0) {
pr_info("tl1_vdin1_preview request irq error.\n");
return -1;
}
devp_vdin1->flags |= VDIN_FLAG_ISR_REQ;
disable_irq_nosync(devp_vdin1->irq);
/*init queue*/
init_waitqueue_head(&devp_vdin1->queue);
}
devp_vdin1->unstable_flag = false;
devp_vdin1->parm.info.fmt = fmt;
devp_vdin1->parm.port = devp->parm.port;
devp_vdin1->fmt_info_p = (struct tvin_format_s *)
tvin_get_fmt_info(fmt);
tvin_get_fmt_info(fmt);
if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) {
/*init queue*/
init_waitqueue_head(&devp_vdin1->queue);
ret = vdin_open_fe(devp_vdin1->parm.port,
0, devp_vdin1);
if (ret) {
@@ -2430,6 +2422,23 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
vdin_start_dec(devp_vdin1);
devp_vdin1->flags |= VDIN_FLAG_DEC_STARTED;
if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) {
ret = request_irq(devp_vdin1->irq, vdin_isr,
IRQF_SHARED,
devp_vdin1->irq_name,
(void *)devp_vdin1);
if (ret != 0) {
pr_info("tl1_vdin1_preview request irq error.\n");
return -1;
}
devp_vdin1->flags |= VDIN_FLAG_ISR_REQ;
} else {
enable_irq(devp_vdin1->irq);
if (vdin_dbg_en)
pr_info("****[%s]enable_vdin1_irq****\n",
__func__);
}
pr_info("TVIN_IOC_START_DEC port %s, vdin1 used for preview\n",
tvin_port_str(devp_vdin1->parm.port));
}
@@ -3112,6 +3121,8 @@ static int vdin_drv_probe(struct platform_device *pdev)
else
vdevp->color_depth_mode = 0;
/* use for tl1 vdin1 preview */
spin_lock_init(&tl1_preview_lock);
/*set afbce mode*/
ret = of_property_read_u32(pdev->dev.of_node,
"afbce_bit_mode", &val);