tvin: vdin: fix vdin CMA layout adaptation [1/1]

PD#SWPL-2526

Problem:
1.CMA layout adaptation cause crash
2.vdin buff dump error
3.read_pic error

Solution:
1.codec mm has be moved to high memory area,
	we should map memory use vmap.
2.make vdin high mem and low mem to be compatible
	when we dump vdin buff.
3.fix read_pic bug.

Verify:
TXLX R311

Change-Id: I90e4f46ba91d38c6ce0f8bfd65b5c22e6be3b83f
Signed-off-by: Xuhua Zhang <xuhua.zhang@amlogic.com>
This commit is contained in:
Xuhua Zhang
2018-11-29 14:28:43 +08:00
committed by Jianxin Pan
parent 87d67d8a20
commit 482e11b95d
2 changed files with 251 additions and 61 deletions

View File

@@ -69,7 +69,7 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp)
char vdin_name[6]; char vdin_name[6];
unsigned int mem_size, h_size, v_size; unsigned int mem_size, h_size, v_size;
int flags = CODEC_MM_FLAGS_CMA_FIRST|CODEC_MM_FLAGS_CMA_CLEAR| int flags = CODEC_MM_FLAGS_CMA_FIRST|CODEC_MM_FLAGS_CMA_CLEAR|
CODEC_MM_FLAGS_CPU; CODEC_MM_FLAGS_DMA;
unsigned int max_buffer_num = min_buf_num; unsigned int max_buffer_num = min_buf_num;
unsigned int i; unsigned int i;
/*head_size:3840*2160*3*9/32*/ /*head_size:3840*2160*3*9/32*/

View File

@@ -24,6 +24,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/amlogic/media/codec_mm/codec_mm.h> #include <linux/amlogic/media/codec_mm/codec_mm.h>
/* Local Headers */ /* Local Headers */
@@ -273,7 +274,11 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp,
struct file *filp = NULL; struct file *filp = NULL;
loff_t pos = 0; loff_t pos = 0;
void *buf = NULL; void *buf = NULL;
unsigned int i; unsigned int i, j;
unsigned int span = 0, count = 0;
int highmem_flag;
unsigned long highaddr;
unsigned long phys;
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
@@ -288,7 +293,22 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp,
pr_info("%s:no cma alloc mem!!!\n", __func__); pr_info("%s:no cma alloc mem!!!\n", __func__);
return; return;
} }
if (buf_num < devp->canvas_max_num) {
if (buf_num >= devp->canvas_max_num) {
vfs_fsync(filp, 0);
filp_close(filp, NULL);
set_fs(old_fs);
pr_info("buf_num > canvas_max_num, vdin exit dump\n");
return;
}
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 == 0) {
pr_info("low mem area\n");
if (devp->cma_config_flag == 0x1) if (devp->cma_config_flag == 0x1)
buf = codec_mm_phys_to_virt(devp->mem_start + buf = codec_mm_phys_to_virt(devp->mem_start +
devp->canvas_max_size*buf_num); devp->canvas_max_size*buf_num);
@@ -307,6 +327,33 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp,
/*vfs_write(filp, buf, devp->canvas_max_size, &pos);*/ /*vfs_write(filp, buf, devp->canvas_max_size, &pos);*/
pr_info("write buffer %2d of %2u to %s.\n", pr_info("write buffer %2d of %2u to %s.\n",
buf_num, devp->canvas_max_num, path); buf_num, devp->canvas_max_num, path);
} else {
pr_info("high mem area\n");
count = devp->canvas_h;
span = devp->canvas_active_w;
if (devp->cma_config_flag == 0x1)
phys = devp->mem_start + devp->canvas_max_size*buf_num;
else if (devp->cma_config_flag == 0x101)
phys = devp->vfmem_start[buf_num];
else if (devp->cma_config_flag == 0x100)
phys = devp->vfmem_start[buf_num];
else
phys = devp->mem_start + devp->canvas_max_size*buf_num;
for (j = 0; j < count; j++) {
highaddr = phys + j * devp->canvas_w;
buf = codec_mm_vmap(highaddr, span);
if (!buf) {
pr_info("codec_mm_vmap error\n");
return;
}
vfs_write(filp, buf, span, &pos);
codec_mm_unmap_phyaddr(buf);
}
pr_info("high-mem write buffer %2d of %2u to %s.\n",
buf_num, devp->canvas_max_num, path);
} }
vfs_fsync(filp, 0); vfs_fsync(filp, 0);
filp_close(filp, NULL); filp_close(filp, NULL);
@@ -317,15 +364,20 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp)
{ {
struct file *filp = NULL; struct file *filp = NULL;
loff_t pos = 0; loff_t pos = 0;
loff_t i = 0, j = 0; loff_t mem_size = 0;
unsigned int mem_size = 0; unsigned int i = 0, j = 0;
unsigned int span = 0;
unsigned int count = 0;
unsigned long highaddr;
unsigned long phys;
int highmem_flag;
void *buf = NULL; void *buf = NULL;
void *vfbuf[VDIN_CANVAS_MAX_CNT]; void *vfbuf[VDIN_CANVAS_MAX_CNT];
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
filp = filp_open(path, O_RDWR|O_CREAT, 0666); filp = filp_open(path, O_RDWR|O_CREAT, 0666);
mem_size = devp->canvas_active_w * devp->canvas_h; mem_size = (loff_t)devp->canvas_active_w * devp->canvas_h;
for (i = 0; i < VDIN_CANVAS_MAX_CNT; i++) for (i = 0; i < VDIN_CANVAS_MAX_CNT; i++)
vfbuf[i] = NULL; vfbuf[i] = NULL;
if (IS_ERR(filp)) { if (IS_ERR(filp)) {
@@ -337,33 +389,77 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp)
pr_info("%s:no cma alloc mem!!!\n", __func__); pr_info("%s:no cma alloc mem!!!\n", __func__);
return; return;
} }
for (i = 0; i < devp->canvas_max_num; i++) {
pos = mem_size * i; if (devp->cma_config_flag & 0x100)
if (devp->cma_config_flag == 0x1) highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0]));
buf = codec_mm_phys_to_virt(devp->mem_start + else
devp->canvas_max_size*i); highmem_flag = PageHighMem(phys_to_page(devp->mem_start));
else if (devp->cma_config_flag == 0x101)
vfbuf[i] = codec_mm_phys_to_virt( if (highmem_flag == 0) {
devp->vfmem_start[i]); /*low mem area*/
else if (devp->cma_config_flag == 0x100) pr_info("low mem area\n");
vfbuf[i] = phys_to_virt(devp->vfmem_start[i]); for (i = 0; i < devp->canvas_max_num; i++) {
else pos = mem_size * i;
buf = phys_to_virt(devp->mem_start + if (devp->cma_config_flag == 0x1)
devp->canvas_max_size*i); buf = codec_mm_phys_to_virt(devp->mem_start +
/*only write active data*/ devp->canvas_max_size*i);
for (j = 0; j < devp->canvas_h; j++) { else if (devp->cma_config_flag == 0x101)
if (devp->cma_config_flag & 0x100) { vfbuf[i] = codec_mm_phys_to_virt(
vfs_write(filp, vfbuf[i], devp->vfmem_start[i]);
devp->canvas_active_w, &pos); else if (devp->cma_config_flag == 0x100)
vfbuf[i] += devp->canvas_w; vfbuf[i] = phys_to_virt(devp->vfmem_start[i]);
} else { else
vfs_write(filp, buf, buf = phys_to_virt(devp->mem_start +
devp->canvas_active_w, &pos); devp->canvas_max_size*i);
buf += devp->canvas_w; /*only write active data*/
for (j = 0; j < devp->canvas_h; j++) {
if (devp->cma_config_flag & 0x100) {
vfs_write(filp, vfbuf[i],
devp->canvas_active_w, &pos);
vfbuf[i] += devp->canvas_w;
} else {
vfs_write(filp, buf,
devp->canvas_active_w, &pos);
buf += devp->canvas_w;
}
} }
pr_info("write buffer %2d of %2u to %s.\n",
i, devp->canvas_max_num, path);
}
} else {
/*high mem area*/
pr_info("high mem area\n");
count = devp->canvas_h;
span = devp->canvas_active_w;
for (i = 0; i < devp->canvas_max_num; i++) {
pos = mem_size * i;
if (devp->cma_config_flag == 0x1) {
phys = devp->mem_start +
devp->canvas_max_size*i;
} else if (devp->cma_config_flag == 0x101)
phys = devp->vfmem_start[i];
else if (devp->cma_config_flag == 0x100)
phys = devp->vfmem_start[i];
else {
phys = devp->mem_start +
devp->canvas_max_size*i;
}
for (j = 0; j < count; j++) {
highaddr = phys + j * devp->canvas_w;
buf = codec_mm_vmap(highaddr, span);
if (!buf) {
pr_info("codec_mm_vmap error\n");
return;
}
vfs_write(filp, buf, span, &pos);
codec_mm_unmap_phyaddr(buf);
}
pr_info("high-mem write buffer %2d of %2u to %s.\n",
i, devp->canvas_max_num, path);
} }
pr_info("write buffer %lld of %2u to %s.\n",
i, devp->canvas_max_num, path);
} }
vfs_fsync(filp, 0); vfs_fsync(filp, 0);
filp_close(filp, NULL); filp_close(filp, NULL);
@@ -378,6 +474,14 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
void *buf_head = NULL; void *buf_head = NULL;
void *buf_table = NULL; void *buf_table = NULL;
void *buf_body = NULL; void *buf_body = NULL;
unsigned long highaddr;
unsigned long phys;
int highmem_flag = 0;
unsigned int span = 0;
unsigned int remain = 0;
unsigned int count = 0;
unsigned int j = 0;
void *vbuf = NULL;
unsigned char buff[100]; unsigned char buff[100];
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
@@ -392,30 +496,54 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
return; return;
} }
if (devp->cma_config_flag == 0x101) { if (devp->cma_config_flag == 0x101)
buf_head = codec_mm_phys_to_virt( highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0]));
devp->afbce_info->fm_head_paddr[buf_num]); else
buf_table = codec_mm_phys_to_virt( highmem_flag = PageHighMem(phys_to_page(devp->mem_start));
devp->afbce_info->fm_table_paddr[buf_num]);
buf_body = codec_mm_phys_to_virt( if (highmem_flag == 0) {
devp->afbce_info->fm_body_paddr[buf_num]); /*low mem area*/
pr_info("low mem area\n");
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]);
}
} else {
/*high mem area*/
pr_info("high mem area\n");
buf_head = codec_mm_vmap(
devp->afbce_info->fm_head_paddr[buf_num],
devp->afbce_info->frame_head_size);
buf_table = codec_mm_vmap(
devp->afbce_info->fm_table_paddr[buf_num],
devp->afbce_info->frame_table_size);
pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", 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_head_paddr[buf_num],
(devp->afbce_info->fm_table_paddr[buf_num]), (devp->afbce_info->fm_table_paddr[buf_num]),
devp->afbce_info->fm_body_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); set_fs(KERNEL_DS);
@@ -459,7 +587,40 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp,
pr_info("create %s body error.\n", buff); pr_info("create %s body error.\n", buff);
return; return;
} }
vfs_write(filp, buf_body, devp->afbce_info->frame_body_size, &pos); if (highmem_flag == 0) {
vfs_write(filp, buf_body,
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[buf_num];
for (j = 0; j < count; j++) {
highaddr = phys + j * span;
vbuf = codec_mm_vmap(highaddr, span);
if (!vbuf) {
pr_info("codec_mm_vmap error\n");
return;
}
vfs_write(filp, vbuf, span, &pos);
codec_mm_unmap_phyaddr(vbuf);
}
if (remain) {
span = devp->afbce_info->frame_body_size - remain;
highaddr = phys + span;
vbuf = codec_mm_vmap(highaddr, remain);
if (!vbuf) {
pr_info("codec_mm_vmap1 error\n");
return;
}
vfs_write(filp, vbuf, span, &pos);
codec_mm_unmap_phyaddr(vbuf);
}
}
pr_info("write buffer %2d of %2u body to %s.\n", pr_info("write buffer %2d of %2u body to %s.\n",
buf_num, devp->canvas_max_num, buff); buf_num, devp->canvas_max_num, buff);
vfs_fsync(filp, 0); vfs_fsync(filp, 0);
@@ -946,8 +1107,10 @@ static void vdin_write_mem(
mm_segment_t old_fs; mm_segment_t old_fs;
void *dts = NULL; void *dts = NULL;
long val; long val;
int index; int index, j, span;
int highmem_flag, count;
unsigned long addr; unsigned long addr;
unsigned long highaddr;
struct vf_pool *p = devp->vfp; struct vf_pool *p = devp->vfp;
/* vtype = simple_strtol(type, NULL, 10); */ /* vtype = simple_strtol(type, NULL, 10); */
@@ -996,15 +1159,42 @@ static void vdin_write_mem(
addr = canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr); addr = canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr);
/* dts = ioremap(canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr), */ /* dts = ioremap(canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr), */
/* real_size); */ /* real_size); */
dts = phys_to_virt(addr);
size = vfs_read(filp, dts, devp->canvas_max_size, &pos);
pr_info("warning: %s read %u < %u\n",
__func__, size, devp->canvas_max_size);
vfs_fsync(filp, 0); if (devp->cma_config_flag & 0x100)
iounmap(dts); highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0]));
filp_close(filp, NULL); else
set_fs(old_fs); highmem_flag = PageHighMem(phys_to_page(devp->mem_start));
if (highmem_flag == 0) {
pr_info("low mem area\n");
dts = phys_to_virt(addr);
for (j = 0; j < devp->canvas_h; j++) {
vfs_read(filp, dts+(devp->canvas_w*j),
devp->canvas_active_w, &pos);
}
vfs_fsync(filp, 0);
iounmap(dts);
filp_close(filp, NULL);
set_fs(old_fs);
} else {
pr_info("high mem area\n");
count = devp->canvas_h;
span = devp->canvas_active_w;
for (j = 0; j < count; j++) {
highaddr = addr + j * devp->canvas_w;
dts = codec_mm_vmap(highaddr, span);
if (!dts) {
pr_info("codec_mm_vmap error\n");
return;
}
vfs_read(filp, dts, span, &pos);
codec_mm_unmap_phyaddr(dts);
}
vfs_fsync(filp, 0);
filp_close(filp, NULL);
set_fs(old_fs);
}
if (vtype == 8) { if (vtype == 8) {
old_fs = get_fs(); old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
@@ -1020,7 +1210,7 @@ static void vdin_write_mem(
u8 *c = devp->vfp->dv_buf_ori[index]; u8 *c = devp->vfp->dv_buf_ori[index];
pos = 0; pos = 0;
size = vfs_read(md_flip, size = (unsigned int)vfs_read(md_flip,
devp->vfp->dv_buf_ori[index], devp->vfp->dv_buf_ori[index],
4096, &pos); 4096, &pos);
p->dv_buf_size[index] = size; p->dv_buf_size[index] = size;