summaryrefslogtreecommitdiff
path: root/drivers/video/wmt/vpp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/wmt/vpp.c')
-rw-r--r--[-rwxr-xr-x]drivers/video/wmt/vpp.c731
1 files changed, 496 insertions, 235 deletions
diff --git a/drivers/video/wmt/vpp.c b/drivers/video/wmt/vpp.c
index 544d9dbf..8b0865ac 100755..100644
--- a/drivers/video/wmt/vpp.c
+++ b/drivers/video/wmt/vpp.c
@@ -2,7 +2,7 @@
* linux/drivers/video/wmt/vpp.c
* WonderMedia video post processor (VPP) driver
*
- * Copyright c 2014 WonderMedia Technologies, Inc.
+ * Copyright c 2013 WonderMedia Technologies, Inc.
*
* 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
@@ -28,16 +28,16 @@
#include "vpp.h"
-struct vpp_mod_base_t *vpp_mod_base_list[VPP_MOD_MAX];
+vpp_mod_base_t *vpp_mod_base_list[VPP_MOD_MAX];
unsigned int vpp_get_chipid(void)
{
/* byte 3,2: chip id, byte 1:ver id, byte 0:sub id */
/* ex: 0x34290101 (0x3429 A0), 0x34290102 (0x3429 A1) */
- return inl(SYSTEM_CFG_CTRL_BASE_ADDR);
+ return REG32_VAL(SYSTEM_CFG_CTRL_BASE_ADDR);
}
-inline void vpp_cache_sync(void)
+__inline__ void vpp_cache_sync(void)
{
/* TODO */
}
@@ -67,7 +67,7 @@ void vpp_set_clock_enable(enum dev_id dev, int enable, int force)
/*----------------------- vpp module --------------------------------------*/
void vpp_mod_unregister(vpp_mod_t mod)
{
- struct vpp_mod_base_t *mod_p;
+ vpp_mod_base_t *mod_p;
if (mod >= VPP_MOD_MAX)
return;
@@ -81,10 +81,10 @@ void vpp_mod_unregister(vpp_mod_t mod)
vpp_mod_base_list[mod] = 0;
}
-struct vpp_mod_base_t *vpp_mod_register(vpp_mod_t mod,
+vpp_mod_base_t *vpp_mod_register(vpp_mod_t mod,
int size, unsigned int flags)
{
- struct vpp_mod_base_t *mod_p;
+ vpp_mod_base_t *mod_p;
if (mod >= VPP_MOD_MAX)
return 0;
@@ -101,10 +101,10 @@ struct vpp_mod_base_t *vpp_mod_register(vpp_mod_t mod,
mod_p->mod = mod;
if (flags & VPP_MOD_FLAG_FRAMEBUF) {
- mod_p->fb_p = kmalloc(sizeof(struct vpp_fb_base_t), GFP_KERNEL);
+ mod_p->fb_p = kmalloc(sizeof(vpp_fb_base_t), GFP_KERNEL);
if (!mod_p->fb_p)
goto error;
- memset(mod_p->fb_p, 0, sizeof(struct vpp_fb_base_t));
+ memset(mod_p->fb_p, 0, sizeof(vpp_fb_base_t));
}
DBG_DETAIL(" %d,0x%x,0x%x\n", mod, (int)mod_p, (int)mod_p->fb_p);
return mod_p;
@@ -114,16 +114,16 @@ error:
return 0;
}
-struct vpp_mod_base_t *vpp_mod_get_base(vpp_mod_t mod)
+vpp_mod_base_t *vpp_mod_get_base(vpp_mod_t mod)
{
if (mod >= VPP_MOD_MAX)
return 0;
return vpp_mod_base_list[mod];
}
-struct vpp_fb_base_t *vpp_mod_get_fb_base(vpp_mod_t mod)
+vpp_fb_base_t *vpp_mod_get_fb_base(vpp_mod_t mod)
{
- struct vpp_mod_base_t *mod_p;
+ vpp_mod_base_t *mod_p;
mod_p = vpp_mod_get_base(mod);
if (mod_p)
return mod_p->fb_p;
@@ -132,7 +132,7 @@ struct vpp_fb_base_t *vpp_mod_get_fb_base(vpp_mod_t mod)
vdo_framebuf_t *vpp_mod_get_framebuf(vpp_mod_t mod)
{
- struct vpp_mod_base_t *mod_p;
+ vpp_mod_base_t *mod_p;
mod_p = vpp_mod_get_base(mod);
if (mod_p && mod_p->fb_p)
@@ -142,7 +142,7 @@ vdo_framebuf_t *vpp_mod_get_framebuf(vpp_mod_t mod)
void vpp_mod_set_clock(vpp_mod_t mod, vpp_flag_t enable, int force)
{
- struct vpp_mod_base_t *base;
+ vpp_mod_base_t *base;
enum dev_id pll_dev;
int cur_sts;
int ret;
@@ -209,20 +209,17 @@ unsigned int vpp_get_base_clock(vpp_mod_t mod)
return clock;
}
+#if 1
void vpp_show_timing(char *str, struct fb_videomode *vmode,
vpp_clock_t *clk)
{
DPRINT("----- %s timing -----\n", str);
if (vmode) {
- int pixclk;
-
- pixclk = (vmode->pixclock) ? PICOS2KHZ(vmode->pixclock) : 0;
- pixclk *= 1000;
-
DPRINT("res(%d,%d),fps %d\n",
vmode->xres, vmode->yres, vmode->refresh);
DPRINT("pixclk %d(%d),hsync %d,vsync %d\n", vmode->pixclock,
- pixclk, vmode->hsync_len, vmode->vsync_len);
+ (int)(PICOS2KHZ(vmode->pixclock) * 1000),
+ vmode->hsync_len, vmode->vsync_len);
DPRINT("left %d,right %d,upper %d,lower %d\n",
vmode->left_margin, vmode->right_margin,
vmode->upper_margin, vmode->lower_margin);
@@ -275,6 +272,7 @@ void vpp_show_videomode(char *str, struct fb_videomode *v)
(v->vmode & FB_VMODE_DOUBLE) ? 1 : 0);
DPRINT("-----------------------\n");
}
+#endif
vpp_csc_t vpp_check_csc_mode(vpp_csc_t mode, vdo_color_fmt src_fmt,
vdo_color_fmt dst_fmt, unsigned int flags)
@@ -322,6 +320,19 @@ int vpp_set_recursive_scale(vdo_framebuf_t *src_fb,
#endif
}
+void vpp_reg_dump(unsigned int addr, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i += 16) {
+ DPRINT("0x%8x : 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ addr + i, vppif_reg32_in(addr + i),
+ vppif_reg32_in(addr + i + 4),
+ vppif_reg32_in(addr + i + 8),
+ vppif_reg32_in(addr + i + 12));
+ }
+} /* End of vpp_reg_dump */
+
unsigned int vpp_convert_colfmt(int yuv2rgb, unsigned int data)
{
unsigned int r, g, b;
@@ -367,6 +378,39 @@ unsigned int vpp_convert_colfmt(int yuv2rgb, unsigned int data)
return data;
}
+unsigned int *vpp_backup_reg(unsigned int addr, unsigned int size)
+{
+ unsigned int *ptr;
+ int i;
+
+ size += 4;
+ ptr = kmalloc(size, GFP_KERNEL);
+ if (ptr == 0) {
+ DPRINT("[VPP] *E* malloc backup fail\n");
+ return 0;
+ }
+
+ for (i = 0; i < size; i += 4)
+ ptr[i / 4] = REG32_VAL(addr + i);
+ return ptr;
+} /* End of vpp_backup_reg */
+
+int vpp_restore_reg(unsigned int addr, unsigned int size,
+ unsigned int *reg_ptr)
+{
+ int i;
+
+ if (reg_ptr == NULL)
+ return 0;
+
+ size += 4;
+ for (i = 0; i < size; i += 4)
+ REG32_VAL(addr + i) = reg_ptr[i / 4];
+ kfree(reg_ptr);
+ reg_ptr = 0;
+ return 0;
+} /* End of vpp_restore_reg */
+
void vpp_get_sys_parameter(void)
{
#ifndef CONFIG_VPOST
@@ -381,15 +425,11 @@ void vpp_get_sys_parameter(void)
g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_SPDIF;
g_vpp.hdmi_cp_enable = 1;
-#ifdef CONFIG_KERNEL
- if (govrh_get_MIF_enable(p_govrh))
- g_vpp.govrh_preinit = 1;
- if (govrh_get_MIF_enable(p_govrh2))
- g_vpp.govrh_preinit = 1;
- MSG("[VPP] govrh preinit %d\n", g_vpp.govrh_preinit);
-#else
- g_vpp.govrh_preinit = 0;
- p_scl->scale_sync = 1;
+#if 0
+ if (wmt_getsyspara("wmt.display.direct_path", buf, &varlen) == 0) {
+ sscanf(buf, "%d", &g_vpp.direct_path);
+ DPRINT("[VPP] direct path %d\n", g_vpp.direct_path);
+ }
#endif
#ifndef CONFIG_VPOST
@@ -400,6 +440,16 @@ void vpp_get_sys_parameter(void)
g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_SPDIF;
}
+ if (wmt_getsyspara("wmt.display.hdmi.vmode", buf, &varlen) == 0) {
+ if (memcmp(buf, "720p", 4) == 0)
+ g_vpp.hdmi_video_mode = 720;
+ else if (memcmp(buf, "1080p", 5) == 0)
+ g_vpp.hdmi_video_mode = 1080;
+ else
+ g_vpp.hdmi_video_mode = 0;
+ DPRINT("[VPP] HDMI video mode %d\n", g_vpp.hdmi_video_mode);
+ }
+
g_vpp.mb_colfmt = VPP_UBOOT_COLFMT;
/* [uboot parameter] fb param : no:xresx:yres:xoffset:yoffset */
if (wmt_getsyspara("wmt.gralloc.param", buf, &varlen) == 0) {
@@ -414,6 +464,19 @@ void vpp_get_sys_parameter(void)
p_govrh->fb_p->fb.col_fmt = g_vpp.mb_colfmt;
p_govrh2->fb_p->fb.col_fmt = g_vpp.mb_colfmt;
+ /* [uboot parameter] dual display : 0-single display, 1-dual display */
+ g_vpp.dual_display = 1;
+ if (wmt_getsyspara("wmt.display.dual", buf, &varlen) == 0) {
+ unsigned int parm[1];
+
+ MSG("display dual : %s\n", buf);
+ vpp_parse_param(buf, (unsigned int *)parm, 1, 0);
+ g_vpp.dual_display = parm[0];
+ }
+
+ if (g_vpp.dual_display == 0)
+ g_vpp.alloc_framebuf = 0;
+
if (wmt_getsyspara("wmt.display.hdmi", buf, &varlen) == 0) {
unsigned int parm[1];
@@ -424,47 +487,6 @@ void vpp_get_sys_parameter(void)
if (wmt_getsyspara("wmt.hdmi.disable", buf, &varlen) == 0)
g_vpp.hdmi_disable = 1;
-
- /* [uboot parameter] reg operation : addr op val */
- if (wmt_getsyspara("wmt.display.regop", buf, &varlen) == 0) {
- unsigned int addr;
- unsigned int val;
- char op;
- char *p, *endp;
-
- p = buf;
- while (1) {
- addr = simple_strtoul(p, &endp, 16);
- if (*endp == '\0')
- break;
-
- op = *endp;
- if (endp[1] == '~') {
- val = simple_strtoul(endp + 2, &endp, 16);
- val = ~val;
- } else
- val = simple_strtoul(endp + 1, &endp, 16);
-
- DBG_DETAIL(" reg op: 0x%X %c 0x%X\n", addr, op, val);
- switch (op) {
- case '|':
- outl(inl(addr) | val, addr);
- break;
- case '=':
- outl(val, addr);
- break;
- case '&':
- outl(inl(addr) & val, addr);
- break;
- default:
- DBG_ERR("Error, Unknown operator %c\n", op);
- }
-
- if (*endp == '\0')
- break;
- p = endp + 1;
- }
- }
#else
if (env_read_para("wmt.display.hdmi", &param) == 0) {
g_vpp.hdmi_sp_mode = strtoul(param.value, 0, 16);
@@ -475,9 +497,12 @@ void vpp_get_sys_parameter(void)
void vpp_init(void)
{
- struct vpp_mod_base_t *mod_p;
+ vpp_mod_base_t *mod_p;
unsigned int mod_mask;
int i;
+ int no;
+
+ vpp_get_sys_parameter();
auto_pll_divisor(DEV_NA12, CLK_ENABLE, 0, 0);
auto_pll_divisor(DEV_VPP, CLK_ENABLE, 0, 0);
@@ -489,8 +514,20 @@ void vpp_init(void)
auto_pll_divisor(DEV_LVDS, CLK_ENABLE, 0, 0);
auto_pll_divisor(DEV_HDMILVDS, CLK_ENABLE, 0, 0);
auto_pll_divisor(DEV_SCL444U, CLK_ENABLE, 0, 0);
+#ifdef CONFIG_KERNEL
+ if (1) {
+ if (govrh_get_MIF_enable(p_govrh))
+ g_vpp.govrh_preinit = 1;
+ if (govrh_get_MIF_enable(p_govrh2))
+ g_vpp.govrh_preinit = 1;
+ MSG("[VPP] govrh preinit %d\n", g_vpp.govrh_preinit);
+ }
+#endif
- vpp_get_sys_parameter();
+#ifndef CONFIG_VPP_DYNAMIC_ALLOC
+ if (g_vpp.alloc_framebuf)
+ g_vpp.alloc_framebuf(VPP_HD_MAX_RESX, VPP_HD_MAX_RESY);
+#endif
/* init video out module first */
if (g_vpp.govrh_preinit == 0) {
@@ -505,14 +542,11 @@ void vpp_init(void)
}
}
-#ifdef CONFIG_UBOOT
- mod_mask = BIT(VPP_MOD_SCL) | BIT(VPP_MOD_SCLW);
-#else
+#ifndef CONFIG_UBOOT
/* init other module */
mod_mask = BIT(VPP_MOD_GOVW) | BIT(VPP_MOD_GOVM) | BIT(VPP_MOD_SCL)
| BIT(VPP_MOD_SCLW) | BIT(VPP_MOD_VPU) | BIT(VPP_MOD_VPUW)
| BIT(VPP_MOD_PIP) | BIT(VPP_MOD_VPPM);
-#endif
for (i = 0; i < VPP_MOD_MAX; i++) {
if (!(mod_mask & (0x01 << i)))
continue;
@@ -520,6 +554,7 @@ void vpp_init(void)
if (mod_p && mod_p->init)
mod_p->init(mod_p);
}
+#endif
#ifdef WMT_FTBLK_LVDS
if (!g_vpp.govrh_preinit)
@@ -529,11 +564,53 @@ void vpp_init(void)
hdmi_init();
#endif
+ vpp_set_clock_enable(DEV_SCL444U, 0, 1);
+
#ifndef CONFIG_VPOST
/* init vout device & get default resolution */
vout_init();
#endif
- vpp_set_clock_enable(DEV_SCL444U, 0, 1);
+
+#ifdef CONFIG_KERNEL
+ no = (g_vpp.virtual_display_mode == 1) ? 1 : 0;
+ if (g_vpp.govrh_preinit) {
+ struct fb_videomode vmode;
+ vout_info_t *info;
+ govrh_mod_t *govr;
+
+ info = vout_get_info_entry(no);
+ govr = vout_info_get_govr(no);
+ govrh_get_videomode(govr, &vmode);
+ govrh_get_framebuffer(govr, &info->fb);
+ g_vpp.govrh_init_yres = vmode.yres;
+ if ((info->resx != vmode.xres) || (info->resy != vmode.yres)) {
+ g_vpp.govrh_preinit = 0;
+ DPRINT("preinit not match (%dx%d) --> (%dx%d)\n",
+ vmode.xres, vmode.yres, info->resx, info->resy);
+ if (g_vpp.virtual_display || (g_vpp.dual_display == 0)) {
+ if(!hdmi_get_plugin()) {
+ vout_t *vo = vout_get_entry(VPP_VOUT_NUM_DVI);
+ if(vo->dev && !strcmp(vo->dev->name, "CS8556") && vo->dev->init) {
+ vo->dev->init(vo);
+ }
+ }
+ }
+ }
+ }
+
+ if (!g_vpp.govrh_preinit) {
+ struct fb_videomode vmode;
+ vout_info_t *info;
+
+ info = vout_get_info_entry(no);
+ memset(&vmode, 0, sizeof(struct fb_videomode));
+ vmode.xres = info->resx;
+ vmode.yres = info->resy;
+ vmode.refresh = info->fps;
+ if (vout_find_match_mode(no, &vmode, 1) == 0)
+ vout_config(VPP_VOUT_ALL, info, &vmode);
+ }
+#endif
vpp_set_clock_enable(DEV_HDMII2C, 0, 0);
vpp_set_clock_enable(DEV_HDMI, 0, 0);
vpp_set_clock_enable(DEV_HDCE, 0, 0);
@@ -614,20 +691,20 @@ void vpp_set_NA12_hiprio(int type)
switch (type) {
case 0: /* restore NA12 priority */
- outl(reg1, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
- outl(reg2, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+ vppif_reg32_out(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8, reg1);
+ vppif_reg32_out(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC, reg2);
break;
case 1: /* set NA12 to high priority */
- reg1 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
- reg2 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
- outl(0x600000, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
- outl(0x0ff00000, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+ reg1 = vppif_reg32_in(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
+ reg2 = vppif_reg32_in(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+ vppif_reg32_out(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8, 0x600000);
+ vppif_reg32_out(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC, 0x0ff00000);
break;
case 2:
- reg1 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
- reg2 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
- outl(0x20003f, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
- outl(0x00ffff00, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+ reg1 = vppif_reg32_in(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
+ reg2 = vppif_reg32_in(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+ vppif_reg32_out(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8, 0x20003f);
+ vppif_reg32_out(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC, 0x00ffff00);
break;
default:
break;
@@ -638,16 +715,170 @@ void vpp_set_NA12_hiprio(int type)
#ifdef __KERNEL__
int vpp_set_audio(int format, int sample_rate, int channel)
{
- struct vout_audio_t info;
+ vout_audio_t info;
- MSG("set audio(fmt %d,rate %d,ch %d)\n",
+ DBG_MSG("set audio(fmt %d,rate %d,ch %d)\n",
format, sample_rate, channel);
info.fmt = format;
info.sample_rate = sample_rate;
info.channel = channel;
return vout_set_audio(&info);
}
+
+static DEFINE_SEMAPHORE(vpp_sem);
+static DEFINE_SEMAPHORE(vpp_sem2);
+void vpp_set_mutex(int idx, int lock)
+{
+ struct semaphore *sem;
+
+ sem = ((g_vpp.dual_display == 0) || (idx == 0)) ? &vpp_sem : &vpp_sem2;
+ if (lock)
+ down(sem);
+ else
+ up(sem);
+}
+
+void vpp_free_framebuffer(void)
+{
+ if (g_vpp.mb[0] == 0)
+ return;
+ MSG("mb free 0x%x\n", g_vpp.mb[0]);
+ mb_free(g_vpp.mb[0]);
+ vpp_lock();
+ g_vpp.mb[0] = 0;
+ vpp_unlock();
+}
+
+int vpp_alloc_framebuffer(unsigned int resx, unsigned int resy)
+{
+ unsigned int y_size;
+ unsigned int fb_size;
+ unsigned int colfmt;
+ int y_bpp, c_bpp;
+ int i;
+
+#ifdef CONFIG_VPP_DYNAMIC_ALLOC
+ if (g_vpp.mb[0]) {
+ vpp_free_framebuffer();
+ }
+#endif
+
+ if ((resx == 0) && (resy == 0)) {
+ return -1;
+ }
+
+ /* alloc govw & govrh frame buffer */
+ if (g_vpp.mb[0] == 0) {
+ unsigned int mb_resx, mb_resy;
+ int fb_num;
+ unsigned int phy_base;
+
+#ifdef CONFIG_VPP_DYNAMIC_ALLOC
+ mb_resx = resx;
+ mb_resy = resy;
+ colfmt = g_vpp.mb_colfmt;
+ vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp);
+ fb_num = VPP_MB_ALLOC_NUM;
+#else
+ char buf[100];
+ int varlen = 100;
+
+ if (wmt_getsyspara("wmt.display.mb", (unsigned char *)buf,
+ &varlen) == 0) {
+ unsigned int parm[10];
+
+ vpp_parse_param(buf, (unsigned int *)parm, 4, 0);
+ MSG("boot parm mb (%d,%d),bpp %d,fb %d\n",
+ parm[0], parm[1], parm[2], parm[3]);
+ mb_resx = parm[0];
+ mb_resy = parm[1];
+ y_bpp = parm[2] * 8;
+ c_bpp = 0;
+ fb_num = parm[3];
+ } else {
+ mb_resx = VPP_HD_MAX_RESX;
+ mb_resy = VPP_HD_MAX_RESY;
+ colfmt = g_vpp.mb_colfmt;
+ vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp);
+ fb_num = VPP_MB_ALLOC_NUM;
+ }
#endif
+ mb_resx = vpp_calc_align(mb_resx,
+ VPP_FB_ADDR_ALIGN / (y_bpp / 8));
+ y_size = mb_resx * mb_resy * y_bpp / 8;
+ fb_size = mb_resx * mb_resy * (y_bpp + c_bpp) / 8;
+ g_vpp.mb_fb_size = fb_size;
+ g_vpp.mb_y_size = y_size;
+ phy_base = mb_alloc(fb_size * fb_num);
+ if (phy_base) {
+ MSG("mb alloc 0x%x,%d\n", phy_base, fb_size * fb_num);
+ for (i = 0; i < fb_num; i++) {
+ g_vpp.mb[i] = (unsigned int)(phy_base +
+ (fb_size * i));
+ MSG("mb 0x%x,fb %d,y %d\n", g_vpp.mb[i],
+ fb_size, y_size);
+ }
+ } else {
+ DBG_ERR("alloc fail\n");
+ return -1;
+ }
+ if (!g_vpp.govrh_preinit) { /* keep uboot logo */
+ memset(mb_phys_to_virt(phy_base), 0, fb_size);
+ MSG("mb clean 0x%x %d\n", phy_base, fb_size);
+ }
+ }
+
+ vpp_lock();
+#ifdef CONFIG_VPP_STREAM_ROTATE
+ {
+ unsigned int resx_mb;
+
+ g_vpp.stream_mb_cnt = VPP_MB_ALLOC_NUM;
+ colfmt = VDO_COL_FMT_YUV422H;
+ vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp);
+ resx_mb = vpp_calc_fb_width(colfmt, resx);
+ y_size = resx_mb * resy * y_bpp / 8;
+ fb_size = vpp_calc_align(resx_mb, 64) * resy *
+ (y_bpp + c_bpp) / 8;
+ for (i = 0; i < g_vpp.stream_mb_cnt; i++) {
+ g_vpp.stream_mb[i] = g_vpp.mb[0] + fb_size * i;
+ }
+ }
+#else
+ /* assign mb to stream mb */
+ {
+ int index = 0, offset = 0;
+ unsigned int size = g_vpp.mb_fb_size;
+ unsigned int resx_fb;
+
+ colfmt = VPP_UBOOT_COLFMT;
+ vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp);
+ resx_fb = vpp_calc_fb_width(colfmt, resx);
+ y_size = resx_fb * resy * y_bpp / 8;
+ fb_size = vpp_calc_align(resx_fb, 64) * resy * (y_bpp + c_bpp) / 8;
+ g_vpp.stream_mb_y_size = y_size;
+ g_vpp.stream_mb_cnt = VPP_STREAM_MB_ALLOC_NUM;
+ for (i = 0; i < VPP_STREAM_MB_ALLOC_NUM; i++) {
+ if (size < fb_size) {
+ index++;
+ if (index >= VPP_MB_ALLOC_NUM) {
+ index = 0;
+ g_vpp.stream_mb_cnt = i;
+ break;
+ }
+ offset = 0;
+ size = g_vpp.mb_fb_size;
+ }
+ g_vpp.stream_mb[i] = g_vpp.mb[index] + offset;
+ size -= fb_size;
+ offset += fb_size;
+ DBG_DETAIL("stream mb %d 0x%x\n", i, g_vpp.stream_mb[i]);
+ }
+ }
+#endif
+ vpp_unlock();
+ return 0;
+} /* End of vpp_alloc_framebuffer */
/*----------------------- vpp mb for stream ---------------------------------*/
#ifdef CONFIG_VPP_STREAM_CAPTURE
@@ -677,12 +908,11 @@ int vpp_mb_get(unsigned int phy)
#ifdef CONFIG_VPP_STREAM_BLOCK
vpp_unlock();
- if (g_vpp.stream_mb_sync_flag)
- vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "mb_get wait");
-
- i = wait_event_interruptible_timeout(vpp_mb_event,
- (g_vpp.stream_mb_sync_flag != 1), HZ / 20);
+ i = wait_event_interruptible(vpp_mb_event,
+ (g_vpp.stream_mb_sync_flag != 1));
vpp_lock();
+ if (i)
+ return -1;
#else /* non-block */
if (g_vpp.stream_mb_sync_flag) { /* not new mb updated */
vpp_dbg_show(VPP_DBGLVL_STREAM, 0,
@@ -766,10 +996,49 @@ int vpp_mb_irqproc_sync(int arg)
return 0;
}
+void vpp_mb_scale_bitblit(vdo_framebuf_t *fb)
+{
+ int index = g_vpp.stream_mb_index;
+ vdo_framebuf_t src, dst;
+
+ if (p_scl->scale_complete == 0)
+ return;
+
+#ifdef CONFIG_VPP_STREAM_ROTATE
+ index = g_vpp.stream_mb_index + 1;
+ index = (index >= g_vpp.stream_mb_cnt) ? 0 : index;
+#else
+ do {
+ index++;
+ if (index >= g_vpp.stream_mb_cnt)
+ index = 0;
+
+ if (g_vpp.stream_mb_lock & (0x1 << index))
+ continue;
+ break;
+ } while (1);
+#endif
+
+ g_vpp.stream_mb_index = index;
+ p_scl->scale_sync = 1;
+ src = *fb;
+#ifdef CONFIG_VPP_STREAM_FIX_RESOLUTION
+ dst = g_vpp.stream_fb;
+#else
+ dst = *fb;
+ dst.col_fmt = VDO_COL_FMT_YUV422H;
+ dst.fb_w = vpp_calc_align(dst.fb_w, 64);
+#endif
+ dst.y_addr = g_vpp.stream_mb[index];
+ dst.c_addr = dst.y_addr + (dst.fb_w * dst.img_h);
+ vpp_set_recursive_scale(&src, &dst);
+}
+#endif
+
/*----------------------- irq proc --------------------------------------*/
-struct vpp_irqproc_t *vpp_irqproc_array[32];
+vpp_irqproc_t *vpp_irqproc_array[32];
struct list_head vpp_irqproc_free_list;
-struct vpp_proc_t vpp_proc_array[VPP_PROC_NUM];
+vpp_proc_t vpp_proc_array[VPP_PROC_NUM];
static void vpp_irqproc_do_tasklet(unsigned long data);
void vpp_irqproc_init(void)
@@ -782,7 +1051,7 @@ void vpp_irqproc_init(void)
list_add_tail(&vpp_proc_array[i].list, &vpp_irqproc_free_list);
}
-struct vpp_irqproc_t *vpp_irqproc_get_entry(enum vpp_int_t vpp_int)
+vpp_irqproc_t *vpp_irqproc_get_entry(vpp_int_t vpp_int)
{
int no;
@@ -795,9 +1064,9 @@ struct vpp_irqproc_t *vpp_irqproc_get_entry(enum vpp_int_t vpp_int)
}
if (vpp_irqproc_array[no] == 0) { /* will create in first use */
- struct vpp_irqproc_t *irqproc;
+ vpp_irqproc_t *irqproc;
- irqproc = kmalloc(sizeof(struct vpp_irqproc_t), GFP_KERNEL);
+ irqproc = kmalloc(sizeof(vpp_irqproc_t), GFP_KERNEL);
vpp_irqproc_array[no] = irqproc;
INIT_LIST_HEAD(&irqproc->list);
tasklet_init(&irqproc->tasklet,
@@ -807,8 +1076,8 @@ struct vpp_irqproc_t *vpp_irqproc_get_entry(enum vpp_int_t vpp_int)
return vpp_irqproc_array[no];
} /* End of vpp_irqproc_get_entry */
-void vpp_irqproc_set_ref(struct vpp_irqproc_t *irqproc,
- enum vpp_int_t type, int enable)
+void vpp_irqproc_set_ref(vpp_irqproc_t *irqproc,
+ vpp_int_t type, int enable)
{
if (enable) {
irqproc->ref++;
@@ -826,20 +1095,20 @@ static void vpp_irqproc_do_tasklet
unsigned long data /*!<; // tasklet input data */
)
{
- struct vpp_irqproc_t *irqproc;
+ vpp_irqproc_t *irqproc;
vpp_lock();
irqproc = vpp_irqproc_get_entry(data);
if (irqproc) {
struct list_head *cur;
struct list_head *next;
- struct vpp_proc_t *entry;
+ vpp_proc_t *entry;
next = (&irqproc->list)->next;
while (next != &irqproc->list) {
cur = next;
next = cur->next;
- entry = list_entry(cur, struct vpp_proc_t, list);
+ entry = list_entry(cur, vpp_proc_t, list);
if (entry->func) {
if (entry->func(entry->arg))
continue;
@@ -864,7 +1133,7 @@ static void vpp_irqproc_do_tasklet
} /* End of vpp_irqproc_do_tasklet */
int vpp_irqproc_work(
- enum vpp_int_t type, /* interrupt type */
+ vpp_int_t type, /* interrupt type */
int (*func)(void *argc), /* proc function pointer */
void *arg, /* proc argument */
int wait_ms, /* wait complete timeout (ms) */
@@ -872,14 +1141,12 @@ int vpp_irqproc_work(
)
{
int ret;
- struct vpp_proc_t *entry;
+ vpp_proc_t *entry;
struct list_head *ptr;
- struct vpp_irqproc_t *irqproc;
+ vpp_irqproc_t *irqproc;
+
+ /* DPRINT("[VPP] vpp_irqproc_work(type 0x%x,wait %d)\n",type,wait); */
-#if 0
- DPRINT("[VPP] vpp_irqproc_work(type 0x%x,wait %d,cnt %d)\n",
- type, wait_ms, work_cnt);
-#endif
if ((vpp_irqproc_free_list.next == 0) ||
list_empty(&vpp_irqproc_free_list)) {
if (func)
@@ -891,7 +1158,7 @@ int vpp_irqproc_work(
vpp_lock();
ptr = vpp_irqproc_free_list.next;
- entry = list_entry(ptr, struct vpp_proc_t, list);
+ entry = list_entry(ptr, vpp_proc_t, list);
list_del_init(ptr);
entry->func = func;
entry->arg = arg;
@@ -940,24 +1207,24 @@ int vpp_irqproc_work(
} /* End of vpp_irqproc_work */
void vpp_irqproc_del_work(
- enum vpp_int_t type, /* interrupt type */
+ vpp_int_t type, /* interrupt type */
int (*func)(void *argc) /* proc function pointer */
)
{
- struct vpp_irqproc_t *irqproc;
+ vpp_irqproc_t *irqproc;
vpp_lock();
irqproc = vpp_irqproc_get_entry(type);
if (irqproc) {
struct list_head *cur;
struct list_head *next;
- struct vpp_proc_t *entry;
+ vpp_proc_t *entry;
next = (&irqproc->list)->next;
while (next != &irqproc->list) {
cur = next;
next = cur->next;
- entry = list_entry(cur, struct vpp_proc_t, list);
+ entry = list_entry(cur, vpp_proc_t, list);
if (entry->func == func) {
vpp_irqproc_set_ref(irqproc, type, 0);
list_del_init(cur);
@@ -986,9 +1253,11 @@ static struct switch_dev vpp_sdev_hdcp = {
.name = "hdcp",
};
+#if 0
static struct switch_dev vpp_sdev_audio = {
.name = "hdmi_audio",
};
+#endif
struct vpp_netlink_proc_t vpp_netlink_proc[VPP_NETLINK_PROC_MAX];
static struct sock *vpp_nlfd;
@@ -1056,109 +1325,107 @@ static ssize_t attr_show_parsed_edid(struct device *dev,
if(strlen(edid_parsed.tv_name.monitor_name) != 0)
DPRINT("Monitor Name: %s\n", edid_parsed.tv_name.monitor_name);
- for (i = 0; i < AUD_SAD_NUM; i++) {
- if (edid_parsed.sad[i].flag == 0) {
- if (i == 0)
- DPRINT("No SAD Data\n");
+ for(i = 0; i < AUD_SAD_NUM; i++) {
+ if(edid_parsed.sad[i].flag == 0) {
+ if(i == 0)
+ printk("No SAD Data\n");
break;
}
DPRINT("SAD %d: 0x%02X 0x%02X 0x%02X\n", i,
- edid_parsed.sad[i].sad_byte[0],
- edid_parsed.sad[i].sad_byte[1],
+ edid_parsed.sad[i].sad_byte[0], edid_parsed.sad[i].sad_byte[1],
edid_parsed.sad[i].sad_byte[2]);
}
DPRINT("--------------------------\n");
#endif
/* print Vendor Name */
- if (strlen(edid_parsed.tv_name.vendor_name) != 0) {
+ if(strlen(edid_parsed.tv_name.vendor_name) != 0) {
len += sprintf(buf + len, "%-16s", "Vendor Name");
len += sprintf(buf + len, ": %s\n", edid_parsed.tv_name.vendor_name);
}
/* print Monitor Name */
- if (strlen(edid_parsed.tv_name.monitor_name) != 0) {
+ if(strlen(edid_parsed.tv_name.monitor_name) != 0) {
len += sprintf(buf + len, "%-16s", "Monitor Name");
len += sprintf(buf + len, ": %s\n", edid_parsed.tv_name.monitor_name);
}
- for (i = 0; i < AUD_SAD_NUM; i++) {
- if (edid_parsed.sad[i].flag == 0)
+ for(i = 0; i < AUD_SAD_NUM; i++) {
+ if(edid_parsed.sad[i].flag == 0)
break;
/*
SAD Byte 1 (format and number of channels):
- bit 7: Reserved (0)
- bit 6..3: Audio format code
- 1 = Linear Pulse Code Modulation (LPCM)
- 2 = AC-3
- 3 = MPEG1 (Layers 1 and 2)
- 4 = MP3
- 5 = MPEG2
- 6 = AAC
- 7 = DTS
- 8 = ATRAC
- 0, 15: Reserved
- 9 = One-bit audio aka SACD
- 10 = DD+
- 11 = DTS-HD
- 12 = MLP/Dolby TrueHD
- 13 = DST Audio
- 14 = Microsoft WMA Pro
- bit 2..0: number of channels minus 1
- (i.e. 000 = 1 channel; 001 = 2 channels; 111 =
- 8 channels)
+ bit 7: Reserved (0)
+ bit 6..3: Audio format code
+ 1 = Linear Pulse Code Modulation (LPCM)
+ 2 = AC-3
+ 3 = MPEG1 (Layers 1 and 2)
+ 4 = MP3
+ 5 = MPEG2
+ 6 = AAC
+ 7 = DTS
+ 8 = ATRAC
+ 0, 15: Reserved
+ 9 = One-bit audio aka SACD
+ 10 = DD+
+ 11 = DTS-HD
+ 12 = MLP/Dolby TrueHD
+ 13 = DST Audio
+ 14 = Microsoft WMA Pro
+ bit 2..0: number of channels minus 1 (i.e. 000 = 1 channel; 001 = 2 channels; 111 =
+ 8 channels)
*/
audio_format = (edid_parsed.sad[i].sad_byte[0] & 0x78) >> 3;
- if (audio_format == 0 || audio_format == 15)
+ if(audio_format == 0 || audio_format == 15)
continue;
/* print header */
len += sprintf(buf + len, "%-16s", "Audio Format");
len += sprintf(buf + len, ": ");
- switch (audio_format) {
- case 1:
- len += sprintf(buf + len, "pcm");
+ switch(audio_format) {
+ case 1:
+ len += sprintf(buf + len, "pcm");
break;
- case 2:
- len += sprintf(buf + len, "ac3");
+ case 2:
+ len += sprintf(buf + len, "ac3");
break;
- case 3:
- len += sprintf(buf + len, "mpeg1");
+ case 3:
+ len += sprintf(buf + len, "mpeg1");
break;
- case 4:
- len += sprintf(buf + len, "mp3");
+ case 4:
+ len += sprintf(buf + len, "mp3");
break;
- case 5:
- len += sprintf(buf + len, "mpeg2");
+ case 5:
+ len += sprintf(buf + len, "mpeg2");
break;
- case 6:
- len += sprintf(buf + len, "aac");
+ case 6:
+ len += sprintf(buf + len, "aac");
break;
- case 7:
- len += sprintf(buf + len, "dts");
+ case 7:
+ len += sprintf(buf + len, "dts");
break;
- case 8:
- len += sprintf(buf + len, "atrac");
+ case 8:
+ len += sprintf(buf + len, "atrac");
break;
- case 9:
- len += sprintf(buf + len, "one_bit_audio");
+ case 9:
+ len += sprintf(buf + len, "one_bit_audio");
break;
- case 10:
- len += sprintf(buf + len, "eac3");
+ case 10:
+ len += sprintf(buf + len, "eac3");
break;
- case 11:
- len += sprintf(buf + len, "dts-hd");
+ case 11:
+ len += sprintf(buf + len, "dts-hd");
break;
- case 12:
- len += sprintf(buf + len, "mlp");
+ case 12:
+ len += sprintf(buf + len, "mlp");
break;
- case 13:
- len += sprintf(buf + len, "dst");
+ case 13:
+ len += sprintf(buf + len, "dst");
break;
- case 14:
- len += sprintf(buf + len, "wmapro");
+ case 14:
+ len += sprintf(buf + len, "wmapro");
break;
- default:
+ default:
break;
}
@@ -1166,8 +1433,7 @@ static ssize_t attr_show_parsed_edid(struct device *dev,
len += sprintf(buf + len, ",");
/* number of channels */
- len += sprintf(buf + len, "%d",
- (edid_parsed.sad[i].sad_byte[0] & 0x7) + 1);
+ len += sprintf(buf + len, "%d", (edid_parsed.sad[i].sad_byte[0] & 0x7) + 1);
/* separator */
len += sprintf(buf + len, ",");
@@ -1185,85 +1451,78 @@ static ssize_t attr_show_parsed_edid(struct device *dev,
*/
sample_freq = edid_parsed.sad[i].sad_byte[1];
sample_freq_num = 0;
- for (j = 0; j < 7; j++) {
- if (sample_freq & (1 << j)) {
- if (sample_freq_num != 0)
- len += sprintf(buf + len,
- "|"); /* separator */
- switch (j) {
- case 0:
- len += sprintf(buf + len, "32KHz");
+ for(j = 0; j < 7; j++) {
+ if(sample_freq & (1 << j)) {
+ if(sample_freq_num != 0)
+ len += sprintf(buf + len, "|"); /* separator */
+ switch(j) {
+ case 0:
+ len += sprintf(buf + len, "32KHz");
break;
- case 1:
- len += sprintf(buf + len, "44KHz");
+ case 1:
+ len += sprintf(buf + len, "44KHz");
break;
- case 2:
- len += sprintf(buf + len, "48KHz");
+ case 2:
+ len += sprintf(buf + len, "48KHz");
break;
- case 3:
- len += sprintf(buf + len, "88KHz");
+ case 3:
+ len += sprintf(buf + len, "88KHz");
break;
- case 4:
- len += sprintf(buf + len, "96KHz");
+ case 4:
+ len += sprintf(buf + len, "96KHz");
break;
- case 5:
- len += sprintf(buf + len, "176KHz");
+ case 5:
+ len += sprintf(buf + len, "176KHz");
break;
- case 6:
- len += sprintf(buf + len, "192KHz");
+ case 6:
+ len += sprintf(buf + len, "192KHz");
break;
- default:
+ default:
break;
}
sample_freq_num++;
}
}
- if (sample_freq_num == 0)
- len += sprintf(buf + len, "0");
+ if(sample_freq_num == 0)
+ len += sprintf(buf +len, "0");
/* separator */
len += sprintf(buf + len, ",");
/*
SAD Byte 3 (bitrate):
- For LPCM, bits 7:3 are reserved and the remaining bits
- define bit depth
- bit 2: 24 bit
- bit 1: 20 bit
- bit 0: 16 bit
- For all other sound formats, bits 7..0 designate the maximum
- supported bitrate divided by 8 kbit/s.
+ For LPCM, bits 7:3 are reserved and the remaining bits define bit depth
+ bit 2: 24 bit
+ bit 1: 20 bit
+ bit 0: 16 bit
+ For all other sound formats, bits 7..0 designate the maximum supported bitrate divided by
+ 8 kbit/s.
*/
bitrate = edid_parsed.sad[i].sad_byte[2];
bitrate_num = 0;
- if (audio_format == 1) { /* for LPCM */
- for (j = 0; j < 3; j++) {
- if (bitrate & (1 << j)) {
- if (bitrate_num != 0)
- len += sprintf(buf + len,
- "|"); /* separator */
- switch (j) {
- case 0:
- len += sprintf(buf + len,
- "16bit");
+ if(audio_format == 1) { /* for LPCM */
+ for(j = 0; j < 3; j++) {
+ if(bitrate & (1 << j)) {
+ if(bitrate_num != 0)
+ len += sprintf(buf + len, "|"); /* separator */
+ switch(j) {
+ case 0:
+ len += sprintf(buf + len, "16bit");
break;
- case 1:
- len += sprintf(buf + len,
- "20bit");
+ case 1:
+ len += sprintf(buf + len, "20bit");
break;
- case 2:
- len += sprintf(buf + len,
- "24bit");
+ case 2:
+ len += sprintf(buf + len, "24bit");
break;
- default:
+ default:
break;
}
bitrate_num++;
}
}
- } else if (audio_format >= 2 &&
- audio_format <= 8) /* From AC3 to ATRAC */
+ } else if(audio_format >= 2 && audio_format <= 8) /* From AC3 to ATRAC */
len += sprintf(buf + len, "%dkbps", bitrate * 8);
else /* From One-bit-audio to WMA Pro*/
len += sprintf(buf + len, "%d", bitrate);
@@ -1271,7 +1530,7 @@ static ssize_t attr_show_parsed_edid(struct device *dev,
len += sprintf(buf + len, "\n");
}
- if (len == 0)
+ if(len == 0)
len += sprintf(buf + len, "\n");
return len;
@@ -1286,7 +1545,9 @@ void vpp_switch_state_init(void)
switch_set_state(&vpp_sdev, hdmi_get_plugin() ? 1 : 0);
switch_dev_register(&vpp_sdev_hdcp);
switch_set_state(&vpp_sdev_hdcp, 0);
+#if 0
switch_dev_register(&vpp_sdev_audio);
+#endif
device_create_file(vpp_sdev.dev, &dev_attr_edid_parsed);
}
@@ -1376,10 +1637,12 @@ void vpp_netlink_notify_plug(int vo_num, int plugin)
if (plugin == 0) {
int mask = 0;
- if (vo_num == VPP_VOUT_ALL)
+ if (g_vpp.virtual_display)
+ mask = ~1;
+ else if (vo_num == VPP_VOUT_ALL)
mask = ~0;
else {
- struct vout_info_t *vo_info;
+ vout_info_t *vo_info;
vo_info = vout_get_info_entry(vo_num);
if (vo_info)
mask = 0x1 << (vo_info->num);
@@ -1391,8 +1654,8 @@ void vpp_netlink_notify_plug(int vo_num, int plugin)
return;
/* if hdmi unplug, clear edid_parsed */
- if (hdmi_get_plugin() == 0)
- memset(&edid_parsed, 0, sizeof(struct edid_parsed_t));
+ if(hdmi_get_plugin() == 0)
+ memset(&edid_parsed, 0, sizeof(edid_parsed_t));
vpp_netlink_notify(USER_PID, DEVICE_PLUG_IN, plugin);
vpp_netlink_notify(WP_PID, DEVICE_PLUG_IN, plugin);
@@ -1407,7 +1670,5 @@ void vpp_netlink_notify_cp(int enable)
{
switch_set_state(&vpp_sdev_hdcp, enable);
}
-EXPORT_SYMBOL(vpp_netlink_notify_cp);
-
#endif /* CONFIG_VPP_NOTIFY */
#endif /* __KERNEL__ */