diff options
author | Sandor Yu <R01008@freescale.com> | 2013-12-27 17:10:03 +0800 |
---|---|---|
committer | Sandor Yu <R01008@freescale.com> | 2014-01-21 18:40:32 +0800 |
commit | 1effa4e8970265f5e7a7cd0f4657939b4fb22fb6 (patch) | |
tree | 884f0fe995d43ed02088b3f5bfd72d134ef79adf /drivers | |
parent | dc8d95e479a90ebe13df5454e20d1597ef6e8c34 (diff) |
ENGR00293488 ipu: vdi: Support more memory type
__va function only can handle frame buffer from low memory.
Use page_address function to replace it, that can handle
frame buffer from both lower and high memory.
Use ioremap_nocache function to handle Frame buffer
from GPU reserve memory pool.
Correct vdi data save buffer size, save both luma and chroma part for
interleaved YUV format.
For non-interleaved and partial-interleaved YUV format,
save luma part data, chroma part is not covered in the patch.
Signed-off-by: Sandor Yu <R01008@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mxc/ipu3/ipu_device.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c index 19ee573e8020..8f6b957de3b0 100644 --- a/drivers/mxc/ipu3/ipu_device.c +++ b/drivers/mxc/ipu3/ipu_device.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2014 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -2386,6 +2386,7 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) u32 stripe_mode; u32 task_no; u32 i, offset_addr; + u32 line_size; unsigned char *base_off; struct ipu_task_entry *parent = t->parent; @@ -2396,15 +2397,17 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) stripe_mode = t->task_no & 0xf; task_no = t->task_no >> 4; - base_off = (char *) __va(t->output.paddr); - if (base_off == NULL) { - dev_err(t->dev, "ERR[0x%p]Falied get vitual address\n", t); - return; - } + /* Save both luma and chroma part for interleaved YUV(e.g. YUYV). + * Save luma part for non-interleaved and partial-interleaved + * YUV format (e.g NV12 and YV12). */ + if (t->output.format == IPU_PIX_FMT_YUYV || + t->output.format == IPU_PIX_FMT_UYVY) + line_size = t->output.crop.w * fmt_to_bpp(t->output.format)/8; + else + line_size = t->output.crop.w; vdi_save_lines = (t->output.crop.h - t->set.sp_setting.ud_split_line)/2; - vdi_size = vdi_save_lines * t->output.crop.w * 2; - + vdi_size = vdi_save_lines * line_size; if (vdi_save_lines <= 0) { dev_err(t->dev, "[0x%p] vdi_save_line error\n", (void *)t); return; @@ -2438,6 +2441,19 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) parent->old_size = vdi_size; } + if (pfn_valid(t->output.paddr >> PAGE_SHIFT)) { + base_off = page_address(pfn_to_page(t->output.paddr >> PAGE_SHIFT)); + base_off += t->output.paddr & ((1 << PAGE_SHIFT) - 1); + } else { + base_off = (char *)ioremap_nocache(t->output.paddr, + t->output.width * t->output.height * + fmt_to_bpp(t->output.format)/8); + } + if (base_off == NULL) { + dev_err(t->dev, "ERR[0x%p]Failed get virtual address\n", t); + return; + } + /* UP stripe or UP&LEFT stripe */ if ((stripe_mode == UP_STRIPE) || (stripe_mode == (UP_STRIPE | LEFT_STRIPE))) { @@ -2450,17 +2466,16 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) t->output.paddr + offset_addr + vdi_size); for (i = 0; i < vdi_save_lines; i++) - memcpy(parent->vditmpbuf[0] + i*t->output.crop.w*2, + memcpy(parent->vditmpbuf[0] + i*line_size, base_off + offset_addr + - i*t->set.ostride, t->output.crop.w*2); + i*t->set.ostride, line_size); parent->buf0filled = true; } else { offset_addr = t->set.o_off + (t->output.crop.h - vdi_save_lines) * t->set.ostride; for (i = 0; i < vdi_save_lines; i++) memcpy(base_off + offset_addr + i*t->set.ostride, - parent->vditmpbuf[0] + i*t->output.crop.w*2, - t->output.crop.w*2); + parent->vditmpbuf[0] + i*line_size, line_size); dmac_flush_range(base_off + offset_addr, base_off + offset_addr + i*t->set.ostride); @@ -2480,16 +2495,16 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) t->output.paddr + offset_addr + vdi_size); for (i = 0; i < vdi_save_lines; i++) - memcpy(parent->vditmpbuf[0] + i*t->output.crop.w*2, + memcpy(parent->vditmpbuf[0] + i*line_size, base_off + offset_addr + i*t->set.ostride, - t->output.crop.w*2); + line_size); parent->buf0filled = true; } else { offset_addr = t->set.o_off; for (i = 0; i < vdi_save_lines; i++) memcpy(base_off + offset_addr + i*t->set.ostride, - parent->vditmpbuf[0] + i*t->output.crop.w*2, - t->output.crop.w*2); + parent->vditmpbuf[0] + i*line_size, + line_size); dmac_flush_range(base_off + offset_addr, base_off + offset_addr + i*t->set.ostride); @@ -2509,17 +2524,17 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) t->output.paddr + offset_addr + vdi_size); for (i = 0; i < vdi_save_lines; i++) - memcpy(parent->vditmpbuf[1] + i*t->output.crop.w*2, + memcpy(parent->vditmpbuf[1] + i*line_size, base_off + offset_addr + i*t->set.ostride, - t->output.crop.w*2); + line_size); parent->buf1filled = true; } else { offset_addr = t->set.o_off + (t->output.crop.h - vdi_save_lines)*t->set.ostride; for (i = 0; i < vdi_save_lines; i++) memcpy(base_off + offset_addr + i*t->set.ostride, - parent->vditmpbuf[1] + i*t->output.crop.w*2, - t->output.crop.w*2); + parent->vditmpbuf[1] + i*line_size, + line_size); dmac_flush_range(base_off + offset_addr, base_off + offset_addr + i*t->set.ostride); @@ -2538,16 +2553,16 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) t->output.paddr + offset_addr + vdi_save_lines*t->set.ostride); for (i = 0; i < vdi_save_lines; i++) - memcpy(parent->vditmpbuf[1] + i*t->output.crop.w*2, + memcpy(parent->vditmpbuf[1] + i*line_size, base_off + offset_addr + i*t->set.ostride, - t->output.crop.w*2); + line_size); parent->buf1filled = true; } else { offset_addr = t->set.o_off; for (i = 0; i < vdi_save_lines; i++) memcpy(base_off + offset_addr + i*t->set.ostride, - parent->vditmpbuf[1] + i*t->output.crop.w*2, - t->output.crop.w*2); + parent->vditmpbuf[1] + i*line_size, + line_size); dmac_flush_range(base_off + offset_addr, base_off + offset_addr + vdi_save_lines*t->set.ostride); @@ -2556,6 +2571,8 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t) parent->buf1filled = false; } } + if (!pfn_valid(t->output.paddr >> PAGE_SHIFT)) + iounmap(base_off); } static void do_task_release(struct ipu_task_entry *t, int fail) |