summaryrefslogtreecommitdiff
path: root/drivers/video/wmt/wmtfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/wmt/wmtfb.c')
-rw-r--r--[-rwxr-xr-x]drivers/video/wmt/wmtfb.c2592
1 files changed, 2123 insertions, 469 deletions
diff --git a/drivers/video/wmt/wmtfb.c b/drivers/video/wmt/wmtfb.c
index 72029bbc..bac0973f 100755..100644
--- a/drivers/video/wmt/wmtfb.c
+++ b/drivers/video/wmt/wmtfb.c
@@ -2,7 +2,7 @@
* linux/drivers/video/wmt/wmtfb.c
* WonderMedia frame buffer 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
@@ -56,7 +56,7 @@
/* int fbut_xxx; *//*Example*/
static struct fb_fix_screeninfo wmtfb_fix = {
- .id = "wmtfbx",
+ .id = "wmtfb",
.smem_start = 0,
.smem_len = 0,
.type = FB_TYPE_PACKED_PIXELS,
@@ -66,16 +66,16 @@ static struct fb_fix_screeninfo wmtfb_fix = {
.ypanstep = 1,
.ywrapstep = 1,
.line_length = 0,
- .mmio_start = 0,
- .mmio_len = 0,
+ .mmio_start = 0xD8050000,
+ .mmio_len = 0x0700,
.accel = FB_ACCEL_NONE
};
static struct fb_var_screeninfo wmtfb_var = {
- .xres = 0,
- .yres = 0,
- .xres_virtual = 0,
- .yres_virtual = 0,
+ .xres = VPP_HD_DISP_RESX,
+ .yres = VPP_HD_DISP_RESY,
+ .xres_virtual = VPP_HD_DISP_RESX,
+ .yres_virtual = VPP_HD_DISP_RESY,
#if 0
.bits_per_pixel = 32,
.red = {16, 8, 0},
@@ -92,7 +92,7 @@ static struct fb_var_screeninfo wmtfb_var = {
.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE,
.height = -1,
.width = -1,
- .pixclock = 0,
+ .pixclock = (VPP_HD_DISP_RESX*VPP_HD_DISP_RESY*VPP_HD_DISP_FPS),
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
@@ -102,7 +102,7 @@ static struct fb_var_screeninfo wmtfb_var = {
.vmode = FB_VMODE_NONINTERLACED
};
-int wmtfb_probe_ready;
+int wmtfb_fb1_probe;
/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
/* void fbut_xxx(void); *//*Example*/
@@ -111,14 +111,12 @@ int wmtfb_probe_ready;
#ifdef DEBUG
void wmtfb_show_var(char *str, struct fb_var_screeninfo *var)
{
- int pixclk;
-
- pixclk = (var->pixclock) ? (PICOS2KHZ(var->pixclock) * 1000) : 0;
DPRINT("----- %s ------------------------\n", str);
DPRINT("res(%d,%d),vir(%d,%d),offset(%d,%d)\n",
var->xres, var->yres, var->xres_virtual,
var->yres_virtual, var->xoffset, var->yoffset);
- DPRINT("pixclk %d(%d),hsync %d,vsync %d\n", var->pixclock, pixclk,
+ DPRINT("pixclk %d(%d),hsync %d,vsync %d\n", var->pixclock,
+ (int)(PICOS2KHZ(var->pixclock) * 1000),
var->hsync_len, var->vsync_len);
DPRINT("left %d,right %d,upper %d,lower %d\n", var->left_margin,
var->right_margin, var->upper_margin, var->lower_margin);
@@ -132,30 +130,1448 @@ void wmtfb_show_var(char *str, struct fb_var_screeninfo *var)
}
#endif
-static DEFINE_SEMAPHORE(vpp_sem);
-static DEFINE_SEMAPHORE(vpp_sem2);
-void wmtfb_set_mutex(struct fb_info *info, int lock)
+#ifdef CONFIG_PROC_FS
+#define CONFIG_VPP_PROC
+#ifdef CONFIG_VPP_PROC
+unsigned int vpp_proc_value;
+char vpp_proc_str[16];
+static ctl_table vpp_table[];
+static int vpp_do_proc(ctl_table *ctl, int write,
+ void *buffer, size_t *len, loff_t *ppos)
{
- struct vout_info_t *par = (struct vout_info_t *) info->par;
+ int ret;
+ int ctl_name;
- if (lock)
- down(&par->sem);
- else
- up(&par->sem);
+ ctl_name = (((int)ctl - (int)vpp_table) / sizeof(ctl_table)) + 1;
+ if (!write) {
+ switch (ctl_name) {
+ case 1:
+ vpp_proc_value = g_vpp.dbg_msg_level;
+ break;
+ case 2:
+ vpp_proc_value = g_vpp.dbg_wait;
+ break;
+ case 3:
+ vpp_proc_value = g_vpp.dbg_flag;
+ break;
+ case 8:
+ case 9:
+ vpp_proc_value = vpp_get_base_clock((ctl_name == 8) ?
+ VPP_MOD_GOVRH : VPP_MOD_GOVRH2);
+ break;
+ case 10:
+ vpp_proc_value = p_scl->scale_mode;
+ break;
+ case 11:
+ vpp_proc_value = p_scl->filter_mode;
+ break;
+#ifdef CONFIG_WMT_HDMI
+ case 12:
+ vpp_proc_value = g_vpp.hdmi_cp_enable;
+ break;
+ case 13:
+ vpp_proc_value = g_vpp.hdmi_3d_type;
+ break;
+ case 14:
+ vpp_proc_value = g_vpp.hdmi_certify_flag;
+ break;
+#endif
+ case 15:
+ vpp_proc_value = govrh_get_brightness(p_govrh);
+ break;
+ case 16:
+ vpp_proc_value = govrh_get_contrast(p_govrh);
+ break;
+ case 17:
+ vpp_proc_value = govrh_get_saturation(p_govrh);
+ break;
+ default:
+ break;
+ }
+ }
+
+ ret = proc_dointvec(ctl, write, buffer, len, ppos);
+ if (write) {
+ switch (ctl_name) {
+ case 1:
+ DPRINT("---------- VPP debug level ----------\n");
+ DPRINT("0-disable,255-show all\n");
+ DPRINT("1-scale,2-disp fb,3-interrupt,4-timer\n");
+ DPRINT("5-ioctl,6-diag,7-stream\n");
+ DPRINT("-------------------------------------\n");
+ g_vpp.dbg_msg_level = vpp_proc_value;
+ break;
+ case 2:
+ g_vpp.dbg_wait = vpp_proc_value;
+ vpp_dbg_wake_up();
+ break;
+ case 3:
+ g_vpp.dbg_flag = vpp_proc_value;
+ break;
+#ifdef CONFIG_WMT_EDID
+ case 6:
+ {
+ vout_t *vo;
+
+ vo = vout_get_entry_adapter(vpp_proc_value);
+ if ((vo->inf) && (vo->inf->get_edid)) {
+ vo->status &= ~VPP_VOUT_STS_EDID;
+ if (vout_get_edid(vo->num)) {
+ int i;
+
+ vo->edid_info.option = 0;
+ edid_dump(vo->edid);
+ for (i = 1; i <= vo->edid[126]; i++)
+ edid_dump(vo->edid + 128 * i);
+ if (!edid_parse(vo->edid,
+ &vo->edid_info))
+ DBG_ERR("parse EDID\n");
+ } else {
+ DBG_ERR("read EDID\n");
+ }
+ }
+ }
+ break;
+#endif
+ case 8:
+ case 9:
+ govrh_set_clock((ctl_name == 8) ? p_govrh : p_govrh2,
+ vpp_proc_value);
+ DPRINT("set govr pixclk %d\n", vpp_proc_value);
+ break;
+ case 10:
+ DPRINT("---------- scale mode ----------\n");
+ DPRINT("0-recursive normal\n");
+ DPRINT("1-recursive sw bilinear\n");
+ DPRINT("2-recursive hw bilinear\n");
+ DPRINT("3-realtime noraml (quality but x/32 limit)\n");
+ DPRINT("4-realtime bilinear (fit edge w skip line)\n");
+ DPRINT("-------------------------------------\n");
+ p_scl->scale_mode = vpp_proc_value;
+ break;
+ case 11:
+ p_scl->filter_mode = vpp_proc_value;
+ break;
+#ifdef CONFIG_WMT_HDMI
+ case 12:
+ g_vpp.hdmi_cp_enable = vpp_proc_value;
+ hdmi_set_cp_enable(vpp_proc_value);
+ break;
+ case 13:
+ g_vpp.hdmi_3d_type = vpp_proc_value;
+ hdmi_tx_vendor_specific_infoframe_packet();
+ break;
+ case 14:
+ g_vpp.hdmi_certify_flag = vpp_proc_value;
+ break;
+#endif
+ case 15:
+ govrh_set_brightness(p_govrh, vpp_proc_value);
+ break;
+ case 16:
+ govrh_set_contrast(p_govrh, vpp_proc_value);
+ break;
+ case 17:
+ govrh_set_saturation(p_govrh, vpp_proc_value);
+ break;
+ default:
+ break;
+ }
+ }
+ return ret;
}
-int vpp_set_blank(struct fb_info *info, int blank)
+struct proc_dir_entry *vpp_proc_dir;
+static ctl_table vpp_table[] = {
+ { /* .ctl_name = 1, */
+ .procname = "dbg_msg",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 2, */
+ .procname = "dbg_wait",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 3, */
+ .procname = "dbg_flag",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 4, */
+ .procname = "edid_disable",
+ .data = &edid_disable,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 5, */
+ .procname = "edid_msg",
+ .data = &edid_msg_enable,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 6, */
+ .procname = "vout_edid",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 7, */
+ .procname = "vo_mode",
+ .data = vpp_proc_str,
+ .maxlen = 12,
+ .mode = 0666,
+ .proc_handler = &proc_dostring,
+ },
+ { /* .ctl_name = 8, */
+ .procname = "govr1_pixclk",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 9, */
+ .procname = "govr2_pixclk",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 10, */
+ .procname = "scl_scale_mode",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 11, */
+ .procname = "scl_filter",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 12 */
+ .procname = "hdmi_cp_enable",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 13 */
+ .procname = "hdmi_3d",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 14 */
+ .procname = "hdmi_certify",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 15 */
+ .procname = "brightness",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 16 */
+ .procname = "contrast",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* .ctl_name = 17 */
+ .procname = "saturation",
+ .data = &vpp_proc_value,
+ .maxlen = sizeof(int),
+ .mode = 0666,
+ .proc_handler = &vpp_do_proc,
+ },
+ { /* end of table */
+ }
+};
+
+static ctl_table vpp_root_table[] = {
+ {
+ .procname = "vpp", /* create path ==> /proc/sys/vpp */
+ .mode = 0555,
+ .child = vpp_table
+ },
+ { /* end of table */
+ }
+};
+static struct ctl_table_header *vpp_table_header;
+#endif
+
+static int vpp_sts_read_proc(char *buf, char **start, off_t offset,
+ int len, int *eof, void *data)
{
- struct vout_info_t *par = (struct vout_info_t *) info->par;
+ volatile struct govrh_regs *regs =
+ (volatile struct govrh_regs *) REG_GOVRH_BASE1_BEGIN;
+ unsigned int yaddr, caddr;
+ char *p = buf;
+ unsigned int reg;
+
+ p += sprintf(p, "--- VPP HW status ---\n");
+#ifdef WMT_FTBLK_GOVRH
+ p += sprintf(p, "GOVRH memory read underrun error %d,cnt %d,cnt2 %d\n",
+ (regs->interrupt.val & 0x200) ? 1 : 0,
+ p_govrh->underrun_cnt, p_govrh2->underrun_cnt);
+ p_govrh->clr_sts(VPP_INT_ALL);
+#endif
+
+#ifdef WMT_FTBLK_SCL
+ p += sprintf(p, "---------------------------------------\n");
+ p += sprintf(p, "SCL TG error %d\n",
+ vppif_reg32_read(SCL_INTSTS_TGERR));
+ p += sprintf(p, "SCLR MIF1 read error %d\n",
+ vppif_reg32_read(SCLR_INTSTS_R1MIFERR));
+ p += sprintf(p, "SCLR MIF2 read error %d\n",
+ vppif_reg32_read(SCLR_INTSTS_R2MIFERR));
+ p += sprintf(p, "SCLW RGB fifo overflow %d\n",
+ vppif_reg32_read(SCLW_INTSTS_MIFRGBERR));
+ p += sprintf(p, "SCLW Y fifo overflow %d\n",
+ vppif_reg32_read(SCLW_INTSTS_MIFYERR));
+ p += sprintf(p, "SCLW C fifo overflow %d\n",
+ vppif_reg32_read(SCLW_INTSTS_MIFCERR));
+ p_scl->clr_sts(VPP_INT_ALL);
+#endif
+
+ p += sprintf(p, "---------------------------------------\n");
+ p += sprintf(p, "(880.0)GOVRH Enable %d,(900.0)TG %d\n",
+ regs->mif.b.enable, regs->tg_enable.b.enable);
+
+ reg = REG32_VAL(PM_CTRL_BASE_ADDR + 0x258);
+ p += sprintf(p, "--- POWER CONTROL ---\n");
+ p += sprintf(p, "0x%x = 0x%x\n", PM_CTRL_BASE_ADDR + 0x258, reg);
+ p += sprintf(p, "HDCP %d,VPP %d,SCL %d,HDMI I2C %d\n",
+ (reg & BIT7) ? 1 : 0, (reg & BIT18) ? 1 : 0,
+ (reg & BIT21) ? 1 : 0, (reg & BIT22) ? 1 : 0);
+ p += sprintf(p, "HDMI %d,GOVR %d,NA12 %d\n",
+ (reg & BIT23) ? 1 : 0, (reg & BIT25) ? 1 : 0,
+ (reg & BIT16) ? 1 : 0);
+ p += sprintf(p, "DVO %d,HDMI OUT %d,LVDS %d\n", (reg & BIT29) ? 1 : 0,
+ (reg & BIT30) ? 1 : 0, (reg & BIT14) ? 1 : 0);
+
+ p += sprintf(p, "--- VPP fb Address ---\n");
+ p += sprintf(p, "GOV mb 0x%x 0x%x\n", g_vpp.mb[0], g_vpp.mb[1]);
+
+#ifdef WMT_FTBLK_GOVRH
+ govrh_get_fb_addr(p_govrh, &yaddr, &caddr);
+ p += sprintf(p, "GOVRH fb addr Y(0x%x) 0x%x, C(0x%x) 0x%x\n",
+ REG_GOVRH_YSA, yaddr, REG_GOVRH_CSA, caddr);
+ govrh_get_fb_addr(p_govrh2, &yaddr, &caddr);
+ p += sprintf(p, "GOVRH2 fb addr Y(0x%x) 0x%x, C(0x%x) 0x%x\n",
+ REG_GOVRH2_YSA, yaddr, REG_GOVRH2_CSA, caddr);
+#endif
+ p_govrh->underrun_cnt = 0;
+ p_govrh2->underrun_cnt = 0;
+ return p - buf;
+} /* End of vpp_sts_read_proc */
+
+static int vpp_reg_read_proc(char *buf, char **start, off_t offset,
+ int len, int *eof, void *data)
+{
+ char *p = buf;
+ vpp_mod_base_t *mod_p;
int i;
- DBG_MSG("(%d,%d)\n", info->node, blank);
+ DPRINT("Product ID:0x%x\n", vpp_get_chipid());
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p && mod_p->dump_reg)
+ mod_p->dump_reg();
+ }
+#ifdef WMT_FTBLK_HDMI
+ hdmi_reg_dump();
+#endif
+#ifdef WMT_FTBLK_LVDS
+ lvds_reg_dump();
+#endif
+ return p - buf;
+} /* End of vpp_reg_read_proc */
+#endif
+
+/*----------------------- fb ioctl --------------------------------------*/
+int vpp_common_ioctl(unsigned int cmd, unsigned long arg)
+{
+ vpp_mod_base_t *mod_p;
+ vpp_fb_base_t *mod_fb_p;
+ int retval = 0;
+
+ switch (cmd) {
+ case VPPIO_VPPGET_INFO:
+ {
+ int i;
+ vpp_cap_t parm;
+
+ parm.chip_id = vpp_get_chipid();
+ parm.version = 0x01;
+ parm.resx_max = VPP_HD_MAX_RESX;
+ parm.resy_max = VPP_HD_MAX_RESY;
+ parm.pixel_clk = 400000000;
+ parm.module = 0x0;
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p)
+ parm.module |= (0x01 << i);
+ }
+ parm.option = VPP_CAP_DUAL_DISPLAY;
+ copy_to_user((void *)arg, (void *) &parm, sizeof(vpp_cap_t));
+ }
+ break;
+ case VPPIO_VPPSET_INFO:
+ {
+ vpp_cap_t parm;
+
+ copy_from_user((void *)&parm, (const void *)arg,
+ sizeof(vpp_cap_t));
+ }
+ break;
+ case VPPIO_I2CSET_BYTE:
+ {
+ vpp_i2c_t parm;
+ unsigned int id;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_i2c_t));
+ id = (parm.addr & 0x0000FF00) >> 8;
+ vpp_i2c_write(id, (parm.addr & 0xFF), parm.index,
+ (char *)&parm.val, 1);
+ }
+ break;
+ case VPPIO_I2CGET_BYTE:
+ {
+ vpp_i2c_t parm;
+ unsigned int id;
+ int len;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_i2c_t));
+ id = (parm.addr & 0x0000FF00) >> 8;
+ len = parm.val;
+ {
+ unsigned char buf[len];
+
+ vpp_i2c_read(id, (parm.addr & 0xFF), parm.index,
+ buf, len);
+ parm.val = buf[0];
+ }
+ copy_to_user((void *)arg, (void *) &parm, sizeof(vpp_i2c_t));
+ }
+ break;
+ case VPPIO_VPPSET_FBDISP:
+ break;
+ case VPPIO_VPPGET_FBDISP:
+ {
+ vpp_dispfb_info_t parm;
+ copy_to_user((void *)arg, (void *) &parm,
+ sizeof(vpp_dispfb_info_t));
+ }
+ break;
+ case VPPIO_WAIT_FRAME:
+ vpp_wait_vsync(0, arg);
+ break;
+ case VPPIO_MODULE_FRAMERATE:
+ {
+ vpp_mod_arg_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_mod_arg_t));
+ mod_fb_p = vpp_mod_get_fb_base(parm.mod);
+ if (!mod_fb_p)
+ break;
+ if (parm.read) {
+ parm.arg1 = mod_fb_p->framerate;
+ copy_to_user((void *)arg, (void *) &parm,
+ sizeof(vpp_mod_arg_t));
+ } else {
+ mod_fb_p->framerate = parm.arg1;
+ }
+ }
+ break;
+ case VPPIO_MODULE_ENABLE:
+ {
+ vpp_mod_arg_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_mod_arg_t));
+ mod_p = vpp_mod_get_base(parm.mod);
+ if (!mod_p)
+ break;
+
+ if (parm.read) {
+ /* not used */
+ } else {
+ mod_p->set_enable(parm.arg1);
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+ if (parm.mod == VPP_MOD_CURSOR) {
+ p_cursor->enable = parm.arg1;
+ if (p_cursor->enable) {
+ vpp_irqproc_work(VPP_INT_GOVRH_PVBI,
+ (void *)govrh_CUR_irqproc, 0,
+ 0, 0);
+ } else {
+ vpp_irqproc_del_work(VPP_INT_GOVRH_PVBI,
+ (void *)govrh_CUR_irqproc);
+ }
+ }
+#endif
+ }
+ }
+ break;
+ case VPPIO_MODULE_TIMING:
+ DPRINT("remove for new arch\n");
+ break;
+ case VPPIO_MODULE_FBADDR:
+ {
+ vpp_mod_arg_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_mod_arg_t));
+ mod_fb_p = vpp_mod_get_fb_base(parm.mod);
+ if (!mod_fb_p)
+ break;
+ mod_p = vpp_mod_get_base(parm.mod);
+ if (parm.read) {
+ mod_fb_p->get_addr(&parm.arg1, &parm.arg2);
+ copy_to_user((void *)arg, (void *) &parm,
+ sizeof(vpp_mod_arg_t));
+ } else {
+ mod_fb_p->set_addr(parm.arg1, parm.arg2);
+ }
+ }
+ break;
+ case VPPIO_MODULE_FBINFO:
+ {
+ vpp_mod_fbinfo_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_mod_fbinfo_t));
+
+ if (g_vpp.virtual_display)
+ parm.mod = (hdmi_get_plugin()) ?
+ VPP_MOD_GOVRH : VPP_MOD_GOVRH2;
+ mod_fb_p = vpp_mod_get_fb_base(parm.mod);
+ if (!mod_fb_p)
+ break;
+ mod_p = vpp_mod_get_base(parm.mod);
+ if (parm.read) {
+ parm.fb = mod_fb_p->fb;
+ switch (parm.mod) {
+ case VPP_MOD_GOVRH:
+ case VPP_MOD_GOVRH2:
+ govrh_get_framebuffer((govrh_mod_t *)mod_p,
+ &parm.fb);
+ break;
+ default:
+ break;
+ }
+ copy_to_user((void *)arg, (void *) &parm,
+ sizeof(vpp_mod_fbinfo_t));
+ } else {
+ mod_fb_p->fb = parm.fb;
+ mod_fb_p->set_framebuf(&parm.fb);
+
+ if (g_vpp.virtual_display) {
+#ifdef CONFIG_VPP_STREAM_CAPTURE
+ if (g_vpp.stream_enable)
+ vpp_mb_scale_bitblit(&mod_fb_p->fb);
+ else
+#endif
+ {
+ if(g_vpp.mb[0] != 0)
+ vpp_free_framebuffer();
+ }
+
+ if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+ vpp_dbg_timer(
+ &vout_info[1].pandisp_timer,
+ "fbinfo", 2);
+ }
+ }
+ }
+ break;
+ case VPPIO_MODULE_VIEW:
+ {
+ vpp_mod_view_t parm;
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_mod_view_t));
+
+ mod_fb_p = vpp_mod_get_fb_base(parm.mod);
+ if (!mod_fb_p)
+ break;
+ mod_p = vpp_mod_get_base(parm.mod);
+ if (parm.read) {
+ mod_fb_p->fn_view(VPP_FLAG_RD, &parm.view);
+ copy_to_user((void *)arg, (void *) &parm,
+ sizeof(vpp_mod_view_t));
+ } else {
+ mod_fb_p->fn_view(0, &parm.view);
+ }
+ }
+ break;
+#ifdef CONFIG_VPP_STREAM_CAPTURE
+ case VPPIO_STREAM_ENABLE:
+ g_vpp.stream_enable = arg;
+ g_vpp.stream_mb_sync_flag = 0;
+
+ MSG("[VPP] VPPIO_STREAM_ENABLE %d\n", g_vpp.stream_enable);
+#ifdef CONFIG_VPP_STREAM_FIX_RESOLUTION
+ memset(&g_vpp.stream_fb, 0, sizeof(vdo_framebuf_t));
+ g_vpp.stream_fb.img_w = 1280;
+ g_vpp.stream_fb.img_h = 720;
+ g_vpp.stream_fb.fb_w =
+ vpp_calc_align(g_vpp.stream_fb.img_w, 64);
+ g_vpp.stream_fb.fb_h = g_vpp.stream_fb.img_h;
+ g_vpp.stream_fb.bpp = 16;
+ g_vpp.stream_fb.col_fmt = VDO_COL_FMT_YUV422H;
+ g_vpp.stream_fb.y_size = g_vpp.stream_fb.fb_w *
+ g_vpp.stream_fb.fb_h;
+ g_vpp.stream_fb.c_size = g_vpp.stream_fb.fb_w *
+ g_vpp.stream_fb.fb_h;
+#endif
+#ifdef CONFIG_VPP_STREAM_ROTATE
+ g_vpp.stream_mb_lock= 0;
+ g_vpp.stream_mb_index = 0xFF;
+ vpp_netlink_notify(WP_PID, DEVICE_STREAM,
+ (g_vpp.stream_enable) ? 1 : 0);
+#else
+#ifndef CONFIG_VPP_DYNAMIC_ALLOC
+ if (g_vpp.alloc_framebuf == 0) {
+#endif
+ {
+ if (arg) {
+#ifdef CONFIG_VPP_STREAM_FIX_RESOLUTION
+ vpp_alloc_framebuffer(g_vpp.stream_fb.fb_w,
+ g_vpp.stream_fb.fb_h);
+#else
+ vout_info_t *info;
+
+ info = vout_info_get_entry(0);
+ vpp_alloc_framebuffer(info->resx, info->resy);
+#endif
+ } else {
+ vpp_free_framebuffer();
+ }
+ }
+ vpp_mod_set_clock(VPP_MOD_SCL, g_vpp.stream_enable, 0);
+ vpp_pan_display(0, 0);
+ if (!g_vpp.stream_enable) {
+ vpp_lock();
+ vpp_mb_put(0);
+ vpp_unlock();
+ }
+#endif
+ {
+#if 0
+ vpp_int_t type;
+
+ type = (vout_info[0].govr_mod == VPP_MOD_GOVRH) ?
+ VPP_INT_GOVRH_VBIS : VPP_INT_GOVRH2_VBIS;
+ if (g_vpp.stream_enable) {
+ vpp_irqproc_work(type, (void *)vpp_mb_irqproc_sync,
+ vout_info[0].govr, 0, 0);
+ } else {
+ vpp_irqproc_del_work(type, (void *)vpp_mb_irqproc_sync);
+ }
+#endif
+ wmt_enable_mmfreq(WMT_MMFREQ_MIRACAST, g_vpp.stream_enable);
+ }
+ break;
+ case VPPIO_STREAM_GETFB:
+ {
+ vdo_framebuf_t fb;
+
+ vpp_lock();
+#ifdef CONFIG_VPP_STREAM_ROTATE
+ if (g_vpp.stream_mb_index == 0xFF) { /* not avail */
+ retval = -1;
+ vpp_unlock();
+ break;
+ }
+ fb = vout_info[1].fb;
+#else
+#ifdef CONFIG_VPP_STREAM_FIX_RESOLUTION
+ fb = g_vpp.stream_fb;
+#else
+ fb = vout_info[0].fb;
+#endif
+#endif
+ fb.fb_w = vpp_calc_align(fb.fb_w, 64);
+ fb.y_addr = g_vpp.stream_mb[g_vpp.stream_mb_index];
+ fb.y_size = fb.fb_w * fb.img_h;
+ fb.c_addr = fb.y_addr + fb.y_size;
+ fb.c_size = fb.y_size;
+ fb.col_fmt = VDO_COL_FMT_YUV422H;
+
+ copy_to_user((void *)arg, (void *) &fb, sizeof(vdo_framebuf_t));
+ retval = vpp_mb_get(fb.y_addr);
+ vpp_unlock();
+ }
+ break;
+ case VPPIO_STREAM_PUTFB:
+ {
+ vdo_framebuf_t fb;
+ copy_from_user((void *) &fb, (const void *)arg,
+ sizeof(vdo_framebuf_t));
+ vpp_lock();
+ vpp_mb_put(fb.y_addr);
+ vpp_unlock();
+ }
+ break;
+#endif
+ case VPPIO_MODULE_CSC:
+ {
+ vpp_mod_arg_t parm;
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_mod_arg_t));
+ mod_fb_p = vpp_mod_get_fb_base(parm.mod);
+ if (!mod_fb_p)
+ break;
+ mod_p = vpp_mod_get_base(parm.mod);
+ if (parm.read) {
+ parm.arg1 = mod_fb_p->csc_mode;
+ copy_to_user((void *)arg, (void *) &parm,
+ sizeof(vpp_mod_arg_t));
+ } else {
+ mod_fb_p->csc_mode = parm.arg1;
+ mod_fb_p->set_csc(mod_fb_p->csc_mode);
+ }
+ }
+ break;
+ case VPPIO_MULTIVD_ENABLE:
+ wmt_enable_mmfreq(WMT_MMFREQ_MULTI_VD, arg);
+ break;
+ default:
+ retval = -ENOTTY;
+ break;
+ }
+ return retval;
+} /* End of vpp_common_ioctl */
+
+int vout_ioctl(unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+
+ switch (cmd) {
+ case VPPIO_VOGET_INFO:
+ {
+ vpp_vout_info_t parm;
+ vout_t *vo;
+ int num;
+ vout_inf_t *inf;
+ int fb_num;
+ vout_info_t *vo_info;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_vout_info_t));
+ fb_num = (parm.num & 0xF0) >> 4;
+ num = parm.num & 0xF;
+ DBGMSG("VPPIO_VOGET_INFO %d,%d\n", fb_num, num);
+ if ((fb_num >= VPP_VOUT_INFO_NUM) || (num >= VOUT_MODE_MAX)) {
+ retval = -ENOTTY;
+ DBG_MSG("fb_num or num invalid\n");
+ break;
+ }
+ memset(&parm, 0, sizeof(vpp_vout_info_t));
+ vo = vout_get_entry_adapter(num);
+ if (vo == 0) {
+ retval = -ENOTTY;
+ DBG_MSG("vo null\n");
+ break;
+ }
+ inf = vout_get_inf_entry_adapter(num);
+ if (inf == 0) {
+ retval = -ENOTTY;
+ DBG_MSG("inf null\n");
+ break;
+ }
+ vo_info = vout_get_info_entry(vo->num);
+ if (vo_info == 0) {
+ retval = -ENOTTY;
+ DBG_MSG("vo_info null\n");
+ break;
+ }
+ if ((g_vpp.dual_display == 1) && (g_vpp.virtual_display == 0)
+ && (fb_num != vo_info->num)) {
+ retval = -ENOTTY;
+ DBG_MSG("fb num not match\n");
+ break;
+ }
+ DBGMSG("VPPIO_VOGET_INFO %d,fb%d,0x%x,0x%x\n", num,
+ vo_info->num, (int)vo, (int)inf);
+ if ((vo == 0) || (inf == 0))
+ goto label_get_info;
+
+ parm.num = num;
+ parm.status = vo->status | VPP_VOUT_STS_REGISTER;
+ strncpy(parm.name, vout_adpt_str[num], 10);
+ switch (inf->mode) {
+ case VOUT_INF_DVI:
+ parm.status &= ~VPP_VOUT_STS_ACTIVE;
+ if (vo->dev) {
+ /* check current DVI is dvi/dvo2hdmi/lcd */
+ switch (num) {
+ case VOUT_DVI:
+ if (strcmp("VT1632",
+ vo->dev->name) == 0)
+ parm.status |=
+ VPP_VOUT_STS_ACTIVE;
+ parm.status |= VPP_VOUT_STS_ACTIVE;
+ break;
+ case VOUT_LCD:
+ if (strcmp("LCD",
+ vo->dev->name) == 0)
+ parm.status |=
+ VPP_VOUT_STS_ACTIVE;
+ break;
+ case VOUT_DVO2HDMI:
+ if (strcmp("SIL902X",
+ vo->dev->name) == 0)
+ parm.status |=
+ VPP_VOUT_STS_ACTIVE;
+ break;
+ default:
+ break;
+ }
+ } else { /* dvi hw mode */
+ if (num == VOUT_DVI)
+ parm.status |= VPP_VOUT_STS_ACTIVE;
+ }
+
+ if (g_vpp.virtual_display) {
+ if (vout_chkplug(VPP_VOUT_NUM_HDMI))
+ parm.status &= ~VPP_VOUT_STS_ACTIVE;
+ }
+ break;
+ case VOUT_INF_HDMI:
+ case VOUT_INF_LVDS:
+ /* check current HDMI is HDMI or LVDS */
+ if (vo->inf != inf)
+ parm.status = VPP_VOUT_STS_REGISTER;
+ break;
+ default:
+ break;
+ }
+
+ if (parm.status & VPP_VOUT_STS_ACTIVE) {
+ if (vout_chkplug(vo->num))
+ parm.status |= VPP_VOUT_STS_PLUGIN;
+ else
+ parm.status &= ~VPP_VOUT_STS_PLUGIN;
+ } else {
+ parm.status = VPP_VOUT_STS_REGISTER;
+ }
+label_get_info:
+ copy_to_user((void *)arg, (const void *) &parm,
+ sizeof(vpp_vout_info_t));
+ }
+ break;
+ case VPPIO_VOSET_MODE:
+ {
+ vpp_vout_parm_t parm;
+ vout_t *vo;
+ vout_inf_t *inf;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_vout_parm_t));
+ vo = vout_get_entry_adapter(parm.num);
+ inf = vout_get_inf_entry_adapter(parm.num);
+ if (vo && inf) {
+ DBG_DETAIL("VPPIO_VOSET_MODE %d %d\n",
+ vo->num, parm.arg);
+ if (g_vpp.dual_display == 0) {
+ int plugin;
+
+ plugin = vout_chkplug(VPP_VOUT_NUM_HDMI);
+ vout_set_blank((0x1 << VPP_VOUT_NUM_HDMI),
+ (plugin) ? 0 : 1);
+ vout_set_blank((0x1 << VPP_VOUT_NUM_DVI),
+ (plugin) ? 1 : 0);
+ break;
+ }
+ vout_set_blank((0x1 << vo->num), (parm.arg) ? 0 : 1);
+ retval = vout_set_mode(vo->num, inf->mode);
+ }
+ }
+ break;
+ case VPPIO_VOSET_BLANK:
+ {
+ vpp_vout_parm_t parm;
+ vout_t *vo;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_vout_parm_t));
+ vo = vout_get_entry_adapter(parm.num);
+ if (vo)
+ retval = vout_set_blank((0x1 << vo->num), parm.arg);
+ }
+ break;
+ case VPPIO_VOSET_OPTION:
+ {
+ vpp_vout_option_t option;
+ vout_t *vo;
+ int num;
+ vout_inf_t *inf;
+
+ copy_from_user((void *) &option, (const void *)arg,
+ sizeof(vpp_vout_option_t));
+ num = option.num;
+ if (num >= VOUT_MODE_MAX) {
+ retval = -ENOTTY;
+ break;
+ }
+ vo = vout_get_entry_adapter(num);
+ inf = vout_get_inf_entry_adapter(num);
+ if (vo && inf) {
+ vo->option[0] = option.option[0];
+ vo->option[1] = option.option[1];
+ vo->option[2] = option.option[2];
+ vout_set_mode(vo->num, inf->mode);
+ }
+ }
+ break;
+ case VPPIO_VOGET_OPTION:
+ {
+ vpp_vout_option_t option;
+ vout_t *vo;
+ int num;
+
+ copy_from_user((void *) &option, (const void *)arg,
+ sizeof(vpp_vout_option_t));
+ num = option.num;
+ if (num >= VOUT_MODE_MAX) {
+ retval = -ENOTTY;
+ break;
+ }
+ memset(&option, 0, sizeof(vpp_vout_info_t));
+ vo = vout_get_entry_adapter(num);
+ if (vo) {
+ option.num = num;
+ option.option[0] = vo->option[0];
+ option.option[1] = vo->option[1];
+ option.option[2] = vo->option[2];
+ }
+ copy_to_user((void *)arg, (const void *) &option,
+ sizeof(vpp_vout_option_t));
+ }
+ break;
+ case VPPIO_VOUT_VMODE:
+ {
+ vpp_vout_vmode_t parm;
+ int i;
+ struct fb_videomode *vmode;
+ unsigned int resx, resy, fps;
+ unsigned int pre_resx, pre_resy, pre_fps;
+ int index, from_index;
+ int support;
+ unsigned int option, pre_option;
+#ifdef CONFIG_WMT_EDID
+ edid_info_t *edid_info;
+#endif
+ struct fb_videomode *edid_vmode;
+ vpp_vout_t mode;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_vout_vmode_t));
+ from_index = parm.num;
+ parm.num = 0;
+ mode = parm.mode & 0xF;
+#ifdef CONFIG_VPP_DEMO
+ parm.parm[parm.num].resx = 1920;
+ parm.parm[parm.num].resy = 1080;
+ parm.parm[parm.num].fps = 60;
+ parm.parm[parm.num].option = 0;
+ parm.num++;
+#else
+#ifdef CONFIG_WMT_EDID
+ {
+ vout_t *vo;
+
+ vo = vout_get_entry_adapter(mode);
+ if (!vo)
+ goto vout_vmode_end;
+
+ if (!(vo->status & VPP_VOUT_STS_PLUGIN)) {
+ DPRINT("*W* not plugin\n");
+ goto vout_vmode_end;
+ }
+
+ if (vout_get_edid(vo->num) == 0) {
+ DPRINT("*W* read EDID fail\n");
+ goto vout_vmode_end;
+ }
+ if (edid_parse(vo->edid, &vo->edid_info) == 0) {
+ DPRINT("*W* parse EDID fail\n");
+ goto vout_vmode_end;
+ }
+ edid_info = &vo->edid_info;
+ }
+#endif
+ index = 0;
+ resx = resy = fps = option = 0;
+ pre_resx = pre_resy = pre_fps = pre_option = 0;
+ for (i = 0; ; i++) {
+ vmode = (struct fb_videomode *) &vpp_videomode[i];
+ if (vmode->pixclock == 0)
+ break;
+ resx = vmode->xres;
+ resy = vmode->yres;
+ fps = vmode->refresh;
+ option = fps & EDID_TMR_FREQ;
+ option |= (vmode->vmode & FB_VMODE_INTERLACED) ?
+ EDID_TMR_INTERLACE : 0;
+ if ((pre_resx == resx) && (pre_resy == resy) &&
+ (pre_fps == fps) && (pre_option == option))
+ continue;
+ pre_resx = resx;
+ pre_resy = resy;
+ pre_fps = fps;
+ pre_option = option;
+ support = 0;
+#ifdef CONFIG_WMT_EDID
+ if (edid_find_support(edid_info, resx, resy,
+ option, &edid_vmode))
+#else
+ if (1)
+#endif
+ support = 1;
+
+ switch (mode) {
+ case VPP_VOUT_HDMI:
+ case VPP_VOUT_DVO2HDMI:
+ if (g_vpp.hdmi_video_mode) {
+ if (resy > g_vpp.hdmi_video_mode)
+ support = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (support) {
+ if (index >= from_index) {
+ parm.parm[parm.num].resx = resx;
+ parm.parm[parm.num].resy = resy;
+ parm.parm[parm.num].fps = fps;
+ parm.parm[parm.num].option =
+ vmode->vmode;
+ parm.num++;
+ }
+ index++;
+ if (parm.num >= VPP_VOUT_VMODE_NUM)
+ break;
+ }
+ }
+#ifdef CONFIG_WMT_EDID
+vout_vmode_end:
+#endif
+#endif
+ if(parm.num == 0) { /* if no EDID*/
+ if(g_vpp.virtual_display || (g_vpp.dual_display == 0)) {
+ if(mode == VPP_VOUT_DVI) {
+ char buf[40] = {0};
+ int varlen = 40;
+
+ if(wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) {
+ if(!strnicmp(buf, "PAL", 3) || !strnicmp(buf, "NTSC", 4)) {
+ parm.parm[0].resx = 720;
+ parm.parm[0].resy = 576;
+ parm.parm[0].fps = 50;
+ parm.parm[0].option = 0;
+
+ parm.parm[1].resx = 720;
+ parm.parm[1].resy = 480;
+ parm.parm[1].fps = 60;
+ parm.parm[1].option = 0;
+
+ parm.num = 2;
+ }
+ }
+ }
+ }
+ }
+
+ DBG_MSG("[VPP] get support vmode %d\n", parm.num);
+ copy_to_user((void *)arg, (const void *) &parm,
+ sizeof(vpp_vout_vmode_t));
+ }
+ break;
+ case VPPIO_VOGET_EDID:
+ {
+ vpp_vout_edid_t parm;
+ char *edid;
+ vout_t *vo;
+ int size;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_vout_edid_t));
+ size = 0;
+#ifdef CONFIG_WMT_EDID
+ vo = vout_get_entry_adapter(parm.mode);
+ if (!vo)
+ goto vout_edid_end;
+
+ if (!(vo->status & VPP_VOUT_STS_PLUGIN)) {
+ DBG_ERR("*W* not plugin\n");
+ goto vout_edid_end;
+ }
- for (i = 0; i < VPP_VOUT_NUM; i++) {
- if (par->vout[i] == 0)
+ edid = vout_get_edid(vo->num);
+ if (edid == 0) {
+ DBG_ERR("*W* read EDID fail\n");
+ goto vout_edid_end;
+ }
+ size = (edid[0x7E] + 1) * 128;
+ if (size > parm.size)
+ size = parm.size;
+ copy_to_user((void *) parm.buf, (void *) edid, size);
+vout_edid_end:
+#endif
+ parm.size = size;
+ copy_to_user((void *)arg, (const void *) &parm,
+ sizeof(vpp_vout_edid_t));
+ }
+ break;
+ case VPPIO_VOGET_CP_INFO:
+ {
+ vpp_vout_cp_info_t parm;
+ int num;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_vout_cp_info_t));
+ num = parm.num;
+ if (num >= VOUT_MODE_MAX) {
+ retval = -ENOTTY;
break;
- vout_set_blank(par->vout[i]->num, blank);
+ }
+ memset(&parm, 0, sizeof(vpp_vout_cp_info_t));
+ switch (num) {
+ case VOUT_HDMI:
+ if (!g_vpp.hdmi_certify_flag) {
+ if (g_vpp.hdmi_bksv[0] == 0) {
+ hdmi_get_bksv(&g_vpp.hdmi_bksv[0]);
+ DBG_MSG("get BKSV 0x%x 0x%x\n",
+ g_vpp.hdmi_bksv[0],
+ g_vpp.hdmi_bksv[1]);
+ }
+ }
+ case VOUT_DVO2HDMI:
+ parm.bksv[0] = g_vpp.hdmi_bksv[0];
+ parm.bksv[1] = g_vpp.hdmi_bksv[1];
+ break;
+ default:
+ parm.bksv[0] = parm.bksv[1] = 0;
+ break;
+ }
+ copy_to_user((void *)arg, (const void *) &parm,
+ sizeof(vpp_vout_cp_info_t));
+ }
+ break;
+ case VPPIO_VOSET_CP_KEY:
+ if (g_vpp.hdmi_cp_p == 0) {
+ g_vpp.hdmi_cp_p =
+ (char *)kmalloc(sizeof(vpp_vout_cp_key_t),
+ GFP_KERNEL);
+ }
+ if (g_vpp.hdmi_cp_p) {
+ copy_from_user((void *) g_vpp.hdmi_cp_p,
+ (const void *)arg, sizeof(vpp_vout_cp_key_t));
+ if (hdmi_cp)
+ hdmi_cp->init();
+ }
+ break;
+#ifdef WMT_FTBLK_HDMI
+ case VPPIO_VOSET_AUDIO_PASSTHRU:
+ vppif_reg32_write(HDMI_AUD_SUB_PACKET, (arg) ? 0xF : 0x0);
+ break;
+#endif
+#ifdef CONFIG_VPP_VIRTUAL_DISPLAY
+ case VPPIO_VOSET_VIRTUAL_FBDEV:
+ g_vpp.fb0_bitblit = (arg) ? 0 : 1;
+ MSG("[VPP] virtual display %d\n", (int)arg);
+ break;
+#endif
+ default:
+ retval = -ENOTTY;
+ break;
}
+ return retval;
+} /* End of vout_ioctl */
+
+int govr_ioctl(unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+
+ switch (cmd) {
+#ifdef WMT_FTBLK_GOVRH
+ case VPPIO_GOVRSET_DVO:
+ {
+ vdo_dvo_parm_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vdo_dvo_parm_t));
+ govrh_set_dvo_enable(p_govrh, parm.enable);
+ govrh_set_dvo_color_format(p_govrh, parm.color_fmt);
+ govrh_set_dvo_clock_delay(p_govrh, parm.clk_inv,
+ parm.clk_delay);
+ govrh_set_dvo_outdatw(p_govrh, parm.data_w);
+ govrh_set_dvo_sync_polar(p_govrh, parm.sync_polar,
+ parm.vsync_polar);
+ p_govrh->fb_p->set_csc(p_govrh->fb_p->csc_mode);
+ }
+ break;
+#endif
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+ case VPPIO_GOVRSET_CUR_COLKEY:
+ {
+ vpp_mod_arg_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vdo_dvo_parm_t));
+ govrh_CUR_set_color_key(p_cursor, VPP_FLAG_ENABLE,
+ 0, parm.arg1);
+ }
+ break;
+ case VPPIO_GOVRSET_CUR_HOTSPOT:
+ {
+ vpp_mod_arg_t parm;
+ vdo_view_t view;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vdo_dvo_parm_t));
+ p_cursor->hotspot_x = parm.arg1;
+ p_cursor->hotspot_y = parm.arg2;
+ view.posx = p_cursor->posx;
+ view.posy = p_cursor->posy;
+ p_cursor->fb_p->fn_view(0, &view);
+ }
+ break;
+#endif
+ default:
+ retval = -ENOTTY;
+ break;
+ }
+ return retval;
+} /* End of govr_ioctl */
+
+int scl_ioctl(unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+ extern int ge_do_alpha_bitblt(vdo_framebuf_t *src,
+ vdo_framebuf_t *src2, vdo_framebuf_t *dst);
+
+ switch (cmd) {
+ case VPPIO_SCL_SCALE_OVERLAP:
+ {
+ vpp_scale_overlap_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_scale_overlap_t));
+ if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+ vpp_dbg_timer(&p_scl->overlap_timer, 0, 1);
+
+ p_scl->scale_sync = 1;
+ retval = scl_set_scale_overlap(&parm.src_fb,
+ &parm.src2_fb, &parm.dst_fb);
+
+ if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+ vpp_dbg_timer(&p_scl->overlap_timer, "overlap", 2);
+ }
+ break;
+ case VPPIO_SCL_SCALE_ASYNC:
+ case VPPIO_SCL_SCALE:
+ {
+ vpp_scale_t parm;
+
+ p_scl->scale_sync = (cmd == VPPIO_SCL_SCALE) ? 1 : 0;
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_scale_t));
+ if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+ vpp_dbg_timer(&p_scl->scale_timer, 0, 1);
+
+ vpp_set_NA12_hiprio(1);
+ retval = vpp_set_recursive_scale(&parm.src_fb, &parm.dst_fb);
+ vpp_set_NA12_hiprio(0);
+
+ if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+ vpp_dbg_timer(&p_scl->scale_timer, "scale", 2);
+ copy_to_user((void *)arg, (void *)&parm, sizeof(vpp_scale_t));
+ }
+ break;
+#ifdef WMT_FTBLK_SCL
+ case VPPIO_SCL_DROP_LINE_ENABLE:
+ scl_set_drop_line(arg);
+ break;
+#endif
+ case VPPIO_SCL_SCALE_FINISH:
+ retval = p_scl->scale_finish();
+ break;
+ case VPPIO_SCLSET_OVERLAP:
+ {
+ vpp_overlap_t parm;
+
+ copy_from_user((void *) &parm, (const void *)arg,
+ sizeof(vpp_overlap_t));
+ vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_ENABLE, 0);
+ scl_set_overlap(&parm);
+ vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 0);
+ }
+ break;
+ default:
+ retval = -ENOTTY;
+ break;
+ }
+ return retval;
+} /* End of scl_ioctl */
+
+int vpp_ioctl(unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+ int err = 0;
+ int skip_mutex = 0;
+
+/* DBGMSG("vpp_ioctl\n"); */
+ switch (_IOC_TYPE(cmd)) {
+ case VPPIO_MAGIC:
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ /* check argument area */
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void __user *) arg,
+ _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void __user *) arg,
+ _IOC_SIZE(cmd));
+
+ if (err)
+ return -EFAULT;
+
+ if (vpp_check_dbg_level(VPP_DBGLVL_IOCTL)) {
+ switch (cmd) {
+ case VPPIO_VPPSET_FBDISP:
+ case VPPIO_VPPGET_FBDISP:
+ case VPPIO_MODULE_VIEW: /* cursor pos */
+ break;
+ default:
+ DPRINT("[VPP] ioctl cmd 0x%x,arg 0x%x\n",
+ _IOC_NR(cmd), (int)arg);
+ break;
+ }
+ }
+
+ switch (cmd) {
+ case VPPIO_STREAM_GETFB: /* block mode should wait vsync */
+ skip_mutex = 1;
+ break;
+ default:
+ /* scale should wait complete */
+ if ((_IOC_NR(cmd) >= VPPIO_SCL_BASE) &&
+ (_IOC_NR(cmd) < VPPIO_MAX))
+ skip_mutex = 1;
+ break;
+ }
+
+ if (!skip_mutex)
+ vpp_set_mutex(1, 1);
+
+ switch (_IOC_NR(cmd)) {
+ case VPPIO_VPP_BASE ... (VPPIO_VOUT_BASE-1):
+ /* DBGMSG("VPP command ioctl\n"); */
+ retval = vpp_common_ioctl(cmd, arg);
+ break;
+ case VPPIO_VOUT_BASE ... (VPPIO_GOVR_BASE-1):
+ /* DBGMSG("VOUT ioctl\n"); */
+ retval = vout_ioctl(cmd, arg);
+ break;
+ case VPPIO_GOVR_BASE ... (VPPIO_SCL_BASE-1):
+ /* DBGMSG("GOVR ioctl\n"); */
+ retval = govr_ioctl(cmd, arg);
+ break;
+ case VPPIO_SCL_BASE ... (VPPIO_MAX-1):
+ /* DBGMSG("SCL ioctl\n"); */
+ retval = scl_ioctl(cmd, arg);
+ break;
+ default:
+ retval = -ENOTTY;
+ break;
+ }
+
+ if (!skip_mutex)
+ vpp_set_mutex(1, 0);
+
+ if (vpp_check_dbg_level(VPP_DBGLVL_IOCTL)) {
+ switch (cmd) {
+ case VPPIO_VPPSET_FBDISP:
+ case VPPIO_VPPGET_FBDISP:
+ case VPPIO_MODULE_VIEW:
+ break;
+ default:
+ DPRINT("[VPP] ioctl cmd 0x%x,ret 0x%x\n",
+ _IOC_NR(cmd), (int)retval);
+ break;
+ }
+ }
+ return retval;
+} /* End of vpp_ioctl */
+
+int vpp_set_blank(struct fb_info *info, int blank)
+{
+ vout_info_t *vo_info;
+ unsigned int vout_blank_mask = 0, vout_unblank_mask = 0;
+
+ if ((g_vpp.dual_display == 0) && (info->node == 1))
+ return 0;
+
+ DBG_MSG("(%d,%d)\n", info->node, blank);
+
+ vo_info = vout_info_get_entry(info->node);
+ if (blank)
+ vout_blank_mask = vout_get_mask(vo_info);
+ else
+ vout_unblank_mask = vout_get_mask(vo_info);
+
+ if (g_vpp.virtual_display || (g_vpp.dual_display == 0)) {
+ if (blank) {
+ vout_blank_mask = ~0;
+ vout_unblank_mask = 0;
+ } else {
+ int plugin;
+
+ plugin = vout_chkplug(VPP_VOUT_NUM_HDMI);
+ vout_blank_mask &= ~((0x1 << VPP_VOUT_NUM_DVI) +
+ (0x1 << VPP_VOUT_NUM_HDMI));
+ vout_unblank_mask &= ~((0x1 << VPP_VOUT_NUM_DVI) +
+ (0x1 << VPP_VOUT_NUM_HDMI));
+ vout_blank_mask |= (plugin) ?
+ (0x1 << VPP_VOUT_NUM_DVI) :
+ (0x1 << VPP_VOUT_NUM_HDMI);
+ vout_unblank_mask |= (plugin) ?
+ (0x1 << VPP_VOUT_NUM_HDMI) :
+ (0x1 << VPP_VOUT_NUM_DVI);
+ }
+ }
+ vout_set_blank(vout_blank_mask, 1);
+ vout_set_blank(vout_unblank_mask, 0);
return 0;
}
@@ -165,29 +1581,266 @@ void vpp_set_lvds_blank(int blank)
return;
if (blank == 0) {
- outl(inl(GPIO_BASE_ADDR + 0xC0) | BIT10, GPIO_BASE_ADDR + 0xC0);
- outl(inl(GPIO_BASE_ADDR + 0x80) | BIT10, GPIO_BASE_ADDR + 0x80);
+ REG32_VAL(GPIO_BASE_ADDR+0xC0) |= 0x400;
+ REG32_VAL(GPIO_BASE_ADDR+0x80) |= 0x400;
mdelay(6);
}
if (blank)
msleep(50);
- vout_set_blank(VPP_VOUT_NUM_LVDS,
+ vout_set_blank((0x1 << VPP_VOUT_NUM_LVDS),
(blank) ? VOUT_BLANK_POWERDOWN : VOUT_BLANK_UNBLANK);
lvds_set_power_down((blank) ? 1 : 0);
if (blank) {
mdelay(6);
/* GPIO10 off 8ms -> clock -> off */
- outl(inl(GPIO_BASE_ADDR + 0xC0) & ~BIT10,
- GPIO_BASE_ADDR + 0xC0);
+ REG32_VAL(GPIO_BASE_ADDR + 0xC0) &= ~0x400;
+ }
+}
+
+irqreturn_t vpp_interrupt_routine(int irq, void *dev_id)
+{
+ vpp_int_t int_sts;
+
+ switch (irq) {
+ case VPP_IRQ_VPPM: /* VPP */
+ int_sts = p_vppm->get_sts();
+ p_vppm->clr_sts(int_sts);
+
+ vpp_dbg_show_val1(VPP_DBGLVL_INT, 0, "[VPP] VPPM INT", int_sts);
+ {
+ int i;
+ unsigned int mask;
+ vpp_irqproc_t *irqproc;
+
+ for (i = 0, mask = 0x1; (i < 32) && int_sts; i++, mask <<= 1) {
+ if ((int_sts & mask) == 0)
+ continue;
+
+ irqproc = vpp_irqproc_get_entry(mask);
+ if (irqproc) {
+ if (list_empty(&irqproc->list) == 0)
+ tasklet_schedule(&irqproc->tasklet);
+ } else {
+ irqproc = vpp_irqproc_get_entry(VPP_INT_MAX);
+ if (list_empty(&irqproc->list) == 0) {
+ vpp_proc_t *entry;
+ struct list_head *ptr;
+
+ ptr = (&irqproc->list)->next;
+ entry = list_entry(ptr, vpp_proc_t,
+ list);
+ if (entry->type == mask)
+ tasklet_schedule(
+ &irqproc->tasklet);
+ }
+ }
+ int_sts &= ~mask;
+ }
+ }
+ break;
+#ifdef WMT_FTBLK_SCL
+ case VPP_IRQ_SCL: /* SCL */
+ int_sts = p_scl->get_sts();
+ p_scl->clr_sts(int_sts);
+ vpp_dbg_show_val1(VPP_DBGLVL_INT, 0, "[VPP] SCL INT", int_sts);
+ break;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+ case VPP_IRQ_GOVR: /* GOVR */
+ case VPP_IRQ_GOVR2:
+ {
+ govrh_mod_t *govr;
+
+ govr = (irq == VPP_IRQ_GOVR) ? p_govrh : p_govrh2;
+ int_sts = govr->get_sts();
+ govr->clr_sts(int_sts);
+ vpp_dbg_show_val1(VPP_DBGLVL_INT, 0, "[VPP] GOVR INT", int_sts);
+ govr->underrun_cnt++;
+#ifdef VPP_DBG_DIAG_NUM
+ vpp_dbg_show(VPP_DBGLVL_DIAG, 3, "GOVR MIF Err");
+ vpp_dbg_diag_delay = 10;
+#endif
+ }
+ break;
+#endif
+ default:
+ DPRINT("*E* invalid vpp isr\n");
+ break;
+ }
+ return IRQ_HANDLED;
+} /* End of vpp_interrupt_routine */
+
+int vpp_dev_init(void)
+{
+ g_vpp.alloc_framebuf = vpp_alloc_framebuffer;
+ vpp_irqproc_init();
+ vpp_netlink_init();
+ vpp_init();
+#ifdef CONFIG_VPP_PROC
+ /* init system proc */
+ if (vpp_proc_dir == 0) {
+ struct proc_dir_entry *res;
+
+ vpp_proc_dir = proc_mkdir("driver/vpp", NULL);
+ res = create_proc_entry("sts", 0, vpp_proc_dir);
+ if (res)
+ res->read_proc = vpp_sts_read_proc;
+ res = create_proc_entry("reg", 0, vpp_proc_dir);
+ if (res)
+ res->read_proc = vpp_reg_read_proc;
+ vpp_table_header = register_sysctl_table(vpp_root_table);
+ }
+#endif
+
+ /* init interrupt service routine */
+#ifdef WMT_FTBLK_SCL
+ if (vpp_request_irq(VPP_IRQ_SCL, vpp_interrupt_routine,
+ SA_INTERRUPT, "scl", (void *)&g_vpp)) {
+ DPRINT("*E* request VPP ISR fail\n");
+ return -1;
+ }
+#endif
+ if (vpp_request_irq(VPP_IRQ_VPPM, vpp_interrupt_routine,
+ SA_INTERRUPT, "vpp", (void *)&g_vpp)) {
+ DPRINT("*E* request VPP ISR fail\n");
+ return -1;
+ }
+#ifdef WMT_FTBLK_GOVRH
+ if (vpp_request_irq(VPP_IRQ_GOVR, vpp_interrupt_routine,
+ SA_INTERRUPT, "govr", (void *)&g_vpp)) {
+ DPRINT("*E* request VPP ISR fail\n");
+ return -1;
+ }
+
+ if (vpp_request_irq(VPP_IRQ_GOVR2, vpp_interrupt_routine,
+ SA_INTERRUPT, "govr2", (void *)&g_vpp)) {
+ DPRINT("*E* request VPP ISR fail\n");
+ return -1;
+ }
+#endif
+ vpp_switch_state_init();
+ return 0;
+}
+
+int vpp_exit(struct fb_info *info)
+{
+ DBG_MSG("vpp_exit\n");
+
+ vout_exit();
+#ifdef CONFIG_VPP_PROC
+ unregister_sysctl_table(vpp_table_header);
+#endif
+ return 0;
+}
+
+void vpp_wait_vsync(int no, int cnt)
+{
+ int govr_mask = 0;
+
+ if (g_vpp.virtual_display || (g_vpp.dual_display == 0)) {
+ if (govrh_get_MIF_enable(p_govrh))
+ govr_mask |= BIT0;
+ if (govrh_get_MIF_enable(p_govrh2))
+ govr_mask |= BIT1;
+ } else {
+ vout_info_t *vo_info;
+ vout_t *vo;
+ int vo_mask;
+ int i;
+
+ vo_info = vout_info_get_entry(no);
+ vo_mask = vout_get_mask(vo_info);
+ for (i = 0; i < VPP_VOUT_NUM; i++) {
+ if ((vo_mask & (0x1 << i)) == 0)
+ continue;
+ vo = vout_get_entry(i);
+ if (vo) {
+ if (vo->govr == p_govrh)
+ govr_mask |= BIT0;
+ if (vo->govr == p_govrh2)
+ govr_mask |= BIT1;
+ }
+ }
}
+
+ if (govr_mask) {
+#if 0
+ if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+ MSG("[VPP] vpp_wait_vsync %d\n", no);
+#endif
+ vpp_irqproc_work((govr_mask & BIT0) ? VPP_INT_GOVRH_VBIS :
+ VPP_INT_GOVRH2_VBIS, 0, 0, 100 * cnt, cnt);
+ }
+} /* End of vpp_wait_vsync */
+
+/* struct list_head *vpp_modelist; */
+void vpp_get_info(int fbn, struct fb_var_screeninfo *var)
+{
+ static int vpp_init_flag = 1;
+ vout_info_t *info;
+ govrh_mod_t *govr;
+
+ if (vpp_init_flag) {
+#if 0
+ int num;
+
+ INIT_LIST_HEAD(vpp_modelist);
+ for (num = 0; ; num++) {
+ if (vpp_videomode[num].xres == 0)
+ break;
+ }
+ fb_videomode_to_modelist(vpp_videomode, num, vpp_modelist);
+#endif
+ vpp_dev_init();
+ vpp_init_flag = 0;
+ }
+
+ info = vout_info_get_entry(fbn);
+ govr = vout_info_get_govr(fbn);
+ if (govr) {
+ struct fb_videomode vmode;
+
+ govrh_get_framebuffer(govr, &info->fb);
+ govrh_get_videomode(govr, &vmode);
+ fb_videomode_to_var(var, &vmode);
+ } else {
+ var->pixclock =
+ KHZ2PICOS((info->resx * info->resy * 60) / 1000);
+ }
+ var->xres = info->resx;
+ var->yres = info->resy;
+ var->xres_virtual = info->fb.fb_w;
+ var->yres_virtual = var->yres * VPP_MB_ALLOC_NUM;
+ if (g_vpp.mb_colfmt == VDO_COL_FMT_ARGB) {
+ var->bits_per_pixel = 32;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->red.msb_right = 0;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->green.msb_right = 0;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->green.msb_right = 0;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ var->transp.msb_right = 0;
+ }
+ DBG_MSG("(%d,%dx%d,%dx%d,%d,%d)\n", fbn, var->xres, var->yres,
+ var->xres_virtual, var->yres_virtual,
+ var->pixclock, var->bits_per_pixel);
+#ifdef DEBUG
+ wmtfb_show_var("get_info", var);
+#endif
}
void vpp_var_to_fb(struct fb_var_screeninfo *var,
struct fb_info *info, vdo_framebuf_t *fb)
{
+ extern unsigned int fb_egl_swap;
unsigned int addr;
int y_bpp, c_bpp;
@@ -221,6 +1874,7 @@ void vpp_var_to_fb(struct fb_var_screeninfo *var,
y_bpp = 8;
c_bpp = 8;
}
+ var->xres_virtual = vpp_calc_fb_width(fb->col_fmt, var->xres);
fb->img_w = var->xres;
fb->img_h = var->yres;
@@ -239,157 +1893,163 @@ void vpp_var_to_fb(struct fb_var_screeninfo *var,
fb->c_addr = fb->y_addr + fb->y_size;
fb->c_size = var->xres_virtual * var->yres * (c_bpp >> 3);
}
-}
-
-void vpp_pan_display_bitblit(struct vout_info_t *par)
-{
- vdo_framebuf_t src, dst;
- struct fb_videomode vmode;
- struct govrh_mod_t *govr;
- struct fb_info *dfb_info;
- struct vout_info_t *d_info;
- int fb_no;
-
- /* DBG_MSG("fb0 bitblit\n"); */
- src = par->fb;
- for (fb_no = 1; ; fb_no++) {
- d_info = vout_info_get_entry(fb_no);
- if (!d_info)
- break;
-
- govr = vout_info_get_govr(fb_no);
- if (govr == 0)
- break;
- govrh_get_framebuffer(govr, &dst);
- govrh_get_videomode(govr, &vmode);
- dst.img_w = vmode.xres;
- dst.fb_w = vpp_calc_fb_width(dst.col_fmt, dst.img_w);
- dst.img_h = vmode.yres;
- dst.fb_h = vmode.yres;
- dst.y_size = dst.fb_w * dst.img_h * (dst.bpp >> 3);
-
- dfb_info = (struct fb_info *) d_info->fb_info_p;
- if (dfb_info) {
- dfb_info->var.yoffset =
- (dfb_info->var.yoffset) ? 0 : dst.img_h;
- dst.y_addr = dfb_info->fix.smem_start +
- (dst.fb_w * dfb_info->var.yoffset *
- (dst.bpp >> 3));
- dst.c_addr = 0;
- } else {
- govrh_get_fb_addr(govr, &dst.y_addr, &dst.c_addr);
- }
- if (d_info->alloc_mode == VOUT_ALLOC_GE_OVERSCAN) {
- if (!d_info->mb) {
- int size = dst.y_size * VPP_MB_ALLOC_NUM;
+ if (info && (info->node == 0) && (fb_egl_swap != 0)) /* for Android */
+ fb->y_addr = fb_egl_swap;
- d_info->mb = mb_alloc(size);
- if (d_info->mb) {
- MSG("mb alloc 0x%x,%d\n",
- d_info->mb, size);
- } else {
- DBG_ERR("alloc fail\n");
- return;
- }
- }
- dst.y_addr = d_info->mb +
- (dst.fb_w * dfb_info->var.yoffset *
- (dst.bpp >> 3));
- }
-
- if (dst.y_addr) {
- p_scl->scale_sync = 1;
- vpp_set_recursive_scale(&src, &dst);
- vout_set_framebuffer(d_info, &dst);
- }
- }
}
int vpp_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct vout_info_t *par = (struct vout_info_t *) info->par;
+ vout_info_t *vo_info;
+ vdo_framebuf_t *uboot_fb = 0;
if (g_vpp.hdmi_certify_flag)
return 0;
+ vo_info = vout_info_get_entry((info) ? info->node : 0);
+
DBG_DETAIL("fb %d\n", (info) ? info->node : 0);
- vpp_var_to_fb(var, info, &par->fb);
- if (wmtfb_probe_ready && g_vpp.fb0_bitblit && (info->node == 0))
- vpp_pan_display_bitblit(par);
- else
- vout_set_framebuffer(par, &par->fb);
+
+ if (wmtfb_fb1_probe == 0) {
+ uboot_fb = kmalloc(sizeof(vdo_framebuf_t), GFP_KERNEL);
+ *uboot_fb = vo_info->fb;
+ uboot_fb->img_h = g_vpp.govrh_init_yres;
+ }
+
+ vpp_var_to_fb(var, info, &vo_info->fb);
+
+ if (uboot_fb) {
+ DMSG("uboot copy fb%d\n", info->node);
+ p_scl->scale_sync = 1;
+ vpp_set_recursive_scale(uboot_fb, &vo_info->fb);
+ kfree(uboot_fb);
+ }
+
+ /* for 8:1:0 mode change resolution garbage frame */
+ if ((g_vpp.virtual_display_mode == 1) && (info->node == 1)) {
+ vdo_framebuf_t fb;
+
+ govrh_get_framebuffer(p_govrh, &fb);
+ vo_info->fb.y_addr = fb.y_addr;
+ vo_info->fb.c_addr = 0;
+ }
+ vout_set_framebuffer(vout_get_mask(vo_info), &vo_info->fb);
+
+ if (g_vpp.fb0_bitblit) {
+ vdo_framebuf_t src, dst;
+ struct fb_videomode vmode;
+ govrh_mod_t *govr;
+
+ src = vo_info->fb;
+ govr = vout_info_get_govr(1);
+ p_scl->scale_sync = 1;
+ govrh_get_framebuffer(govr, &dst);
+ govrh_get_videomode(govr, &vmode);
+ dst.img_w = vmode.xres;
+ dst.fb_w = vpp_calc_fb_width(dst.col_fmt, dst.img_w);
+ dst.img_h = vmode.yres;
+ dst.fb_h = vmode.yres;
+ dst.y_size = dst.fb_w * dst.img_h * dst.bpp / 8;
+#ifdef CONFIG_VPP_DYNAMIC_ALLOC
+ if (g_vpp.mb[0] == 0)
+ vpp_alloc_framebuffer(dst.img_w, dst.img_h);
+#endif
+ g_vpp.stream_mb_index = (g_vpp.stream_mb_index) ? 0 : 1;
+ dst.y_addr = g_vpp.mb[0] + (dst.y_size * g_vpp.stream_mb_index);
+ dst.c_addr = 0;
+ vpp_set_recursive_scale(&src, &dst);
+ vout_set_framebuffer(VPP_VOUT_ALL, &dst);
+ }
#ifdef CONFIG_VPP_STREAM_CAPTURE
- if (g_vpp.stream_enable && (par->hwc_mode == VOUT_HWC_VIRTUAL)) {
- g_vpp.stream_mb_index = var->yoffset / var->yres;
- vpp_dbg_show_val1(VPP_DBGLVL_STREAM, 0,
- "stream pan disp", g_vpp.stream_mb_index);
+ if (g_vpp.stream_enable) {
+#ifdef CONFIG_VPP_STREAM_ROTATE
+ if (info && (info->node == 1)) {
+ g_vpp.stream_mb_index = var->yoffset / var->yres;
+ vpp_dbg_show_val1(VPP_DBGLVL_STREAM, 0,
+ "stream pan disp", g_vpp.stream_mb_index);
+ }
+#else
+ if ((info && (info->node == 0)) || (info == 0))
+ vpp_mb_scale_bitblit(&vo_info->fb);
+#endif
}
#endif
- if (vpp_check_dbg_level(VPP_DBGLVL_DISPFB)) {
+ if (vo_info->govr && vpp_check_dbg_level(VPP_DBGLVL_DISPFB)) {
char buf[50];
- unsigned int yaddr = 0, caddr = 0;
- struct govrh_mod_t *govr;
+ unsigned int yaddr, caddr;
- govr = vout_info_get_govr(info->node);
- if (govr)
- govrh_get_fb_addr(govr, &yaddr, &caddr);
- sprintf(buf, "pan_display %d,0x%x", par->num, yaddr);
- vpp_dbg_show(VPP_DBGLVL_DISPFB, par->num + 1, buf);
+ govrh_get_fb_addr(vo_info->govr, &yaddr, &caddr);
+ sprintf(buf, "pan_display %d,%s,0x%x", vo_info->num,
+ vpp_mod_str[vo_info->govr_mod], yaddr);
+ vpp_dbg_show(VPP_DBGLVL_DISPFB, vo_info->num + 1, buf);
}
- if (vpp_check_dbg_level(VPP_DBGLVL_FPS)) {
- char buf[10];
-
- sprintf(buf, "fb%d", par->num);
- vpp_dbg_timer(&par->pandisp_timer, buf, 2);
- }
+ if (vo_info->govr && vpp_check_dbg_level(VPP_DBGLVL_FPS))
+ vpp_dbg_timer(&vo_info->pandisp_timer,
+ (vo_info->num == 0) ? "fb0" : "fb1", 2);
return 0;
}
int vpp_set_par(struct fb_info *info)
{
- struct vout_info_t *par = (struct vout_info_t *) info->par;
- vdo_framebuf_t fb;
- struct fb_videomode var, cur;
- struct govrh_mod_t *govr;
+ vout_info_t *vo_info;
+ unsigned int mask;
+ int i;
if (g_vpp.hdmi_certify_flag)
return 0;
- govr = vout_info_get_govr(info->node);
- if (!govr)
+ if ((g_vpp.dual_display == 0) && (info->node == 1))
return 0;
- wmtfb_set_mutex(info, 1);
+ if (g_vpp.govrh_preinit)
+ g_vpp.govrh_preinit = 0;
- /* check frame buffer */
- vpp_var_to_fb(&info->var, info, &fb);
- par->fb.fb_h = fb.fb_h;
- if (memcmp(&fb.img_w, &par->fb.img_w, 32)) {
- if ((wmtfb_probe_ready == 0) && g_vpp.govrh_preinit) {
- MSG("[uboot logo] fb%d\n", info->node);
- govrh_get_framebuffer(govr, &par->fb);
- vpp_set_recursive_scale(&par->fb, &fb);
- }
+ vpp_set_mutex(info->node, 1);
+
+for (i = 0; i < VPP_VOUT_INFO_NUM; i++) {
+ vo_info = vout_info_get_entry(i);
+ mask = vout_get_mask(vo_info);
+
+ /* set frame buffer */
+ if (mask) {
+ vdo_framebuf_t fb;
+
+ vpp_var_to_fb(&info->var, info, &fb);
+ vo_info->fb.fb_h = fb.fb_h;
+ if (memcmp(&fb.img_w, &vo_info->fb.img_w, 32)) {
#ifdef DEBUG
- MSG("set_par %d : set framebuf\n",
- info->node);
- vpp_show_framebuf("cur", &par->fb);
- vpp_show_framebuf("new", &fb);
+ DPRINT("[wmtfb_set_par] set_par %d : set framebuf\n",
+ info->node);
+ vpp_show_framebuf("cur", &vo_info->fb);
+ vpp_show_framebuf("new", &fb);
#endif
- par->fb = fb;
- } else {
- fb.img_w = 0;
+ vo_info->fb = fb;
+ vout_set_framebuffer(mask, &vo_info->fb);
+ }
}
- /* check timing */
- fb_var_to_videomode(&var, &info->var);
- govrh_get_videomode(govr, &cur);
- if ((cur.xres == var.xres) && (cur.yres == var.yres)) {
+ /* set timing */
+ if (vo_info->govr && !(g_vpp.virtual_display && (info->node == 0))) {
+ struct fb_videomode var, cur;
+ govrh_mod_t *govr;
unsigned int cur_pixclk, new_pixclk;
+ govr = vout_info_get_govr(info->node);
+ fb_var_to_videomode(&var, &info->var);
+ if(g_vpp.virtual_display) {
+ if (vout_find_match_mode(info->node, &var, 1)) {
+ DPRINT("[wmtfb] not support\n");
+ vpp_set_mutex(info->node, 0);
+ return -1;
+ }
+ fb_videomode_to_var(&info->var, &var);
+ var.flag = FB_MODE_IS_FROM_VAR;
+ }
+ govrh_get_videomode(govr, &cur);
+ if ((cur.xres == var.xres) && (cur.yres == var.yres)) {
/* diff less than 500K */
cur_pixclk = PICOS2KHZ(cur.pixclock);
new_pixclk = PICOS2KHZ(var.pixclock);
@@ -397,190 +2057,20 @@ int vpp_set_par(struct fb_info *info)
var.pixclock = cur.pixclock;
var.refresh = cur.refresh;
}
- /* diff less than 2 */
- if (abs(var.refresh - cur.refresh) <= 2)
+ if (abs(var.refresh - cur.refresh) <= 2) /* diff less than 2 */
var.refresh = cur.refresh;
- }
-
- //var.sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
- var.sync = cur.sync;
- if (memcmp(&var, &cur, sizeof(struct fb_videomode))) {
-#ifdef DEBUG
- DPRINT("[wmtfb] set_par %d: set timing\n", info->node);
- vpp_show_timing("cur", &cur, 0);
- vpp_show_timing("new", &var, 0);
-#endif
- } else {
- var.xres = 0;
- }
- vout_config(par, (var.xres) ? &var : 0, (fb.img_w) ? &fb : 0);
- wmtfb_set_mutex(info, 0);
- return 0;
-}
-
-int vpp_get_info(int fbn, struct fb_var_screeninfo *var)
-{
- struct vout_info_t *par;
-
- par = vout_info_get_entry(fbn);
- if (!par)
- return -1;
-
- var->xres = par->resx;
- var->yres = par->resy;
- var->xres_virtual = par->resx_virtual;
- var->yres_virtual = var->yres * VPP_MB_ALLOC_NUM;
- var->bits_per_pixel = (g_vpp.mb_colfmt == VDO_COL_FMT_ARGB) ? 32 : 16;
- var->pixclock = par->resx * par->resy * par->fps;
- var->pixclock = (var->pixclock) ? (var->pixclock / 1000) : 0;
- var->pixclock = (var->pixclock) ? KHZ2PICOS(var->pixclock) : 0;
- var->left_margin = 0;
- var->right_margin = 0;
- var->upper_margin = 0;
- var->lower_margin = 0;
- var->hsync_len = 0;
- var->vsync_len = 0;
- if (par->option & VPP_OPT_INTERLACE) {
- var->vmode |= FB_VMODE_INTERLACED;
- var->pixclock *= 2;
- }
-#ifdef DEBUG
- MSG("[get_info] fb%d\n", fbn);
- wmtfb_show_var("get_info", var);
-#endif
- return 0;
-}
-
-int wmtfb_alloc(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct vout_info_t *par = (struct vout_info_t *) info->par;
- unsigned int size;
- int no_alloc = 0;
- vdo_color_fmt colfmt;
- int y_bpp, c_bpp;
- unsigned int mb_resx, mb_resy, fb_num;
- int i;
-
- colfmt = (var->nonstd) ? WMT_FB_COLFMT(var->nonstd) :
- ((var->bits_per_pixel == 16) ?
- VDO_COL_FMT_RGB_565 : VDO_COL_FMT_ARGB);
- vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp);
-
- switch (par->alloc_mode) {
- case VOUT_ALLOC_FIX_MB:
- if (info->fix.smem_start) {
- no_alloc = 1;
- break;
- }
-
- {
- 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;
- fb_num = VPP_MB_ALLOC_NUM;
- }
- }
- break;
- case VOUT_ALLOC_DYNAMIC_MB:
- if ((par->hwc_mode == VOUT_HWC_VIRTUAL)
- && !wmtfb_probe_ready) {
- no_alloc = 1;
- break;
- }
- mb_resx = var->xres_virtual;
- mb_resy = var->yres;
- fb_num = VPP_MB_ALLOC_NUM;
- break;
- case VOUT_ALLOC_GE_OVERSCAN:
- if (!info->fix.smem_start) {
- struct vout_info_t *fb0_par;
- struct fb_info *fb0_info;
-
- fb0_par = vout_info_get_entry(0);
- fb0_info = (struct fb_info *) fb0_par->fb_info_p;
- info->fix.smem_start = fb0_info->fix.smem_start;
- info->fix.smem_len = fb0_info->fix.smem_len;
- info->screen_base = fb0_info->screen_base;
- info->screen_size = fb0_info->screen_size;
}
- default:
- no_alloc = 1;
- break;
- }
-#if 0
- DBG_MSG("fb%d,mode %d,size %d,len %d,%dx%d,no alloc %d\n",
- info->node, par->alloc_mode, size, info->fix.smem_len,
- var->xres, var->yres, no_alloc);
+ if (memcmp(&var, &cur, sizeof(struct fb_videomode))) {
+#ifdef DEBUG
+ DPRINT("[wmtfb] set_par %d: set timing\n", info->node);
+ vpp_show_timing("cur", &cur, 0);
+ vpp_show_timing("new", &var, 0);
#endif
- if (no_alloc)
- return 0; /* don't need */
-
- size = mb_resx * mb_resy * ((y_bpp + c_bpp) / 8) * fb_num ;
- if (size == info->fix.smem_len)
- return 0;
-
- /* free pre mb */
- if (info->fix.smem_start) {
- mb_free(info->fix.smem_start);
- info->fix.smem_start = 0;
- info->fix.smem_len = 0;
- info->screen_base = 0;
- info->screen_size = 0;
- MSG("[wmtfb] fb%d free mb\n", info->node);
- }
-
- if ((var->xres == 0) || (var->yres == 0))
- return -1;
-
- info->fix.smem_start = mb_alloc(size);
- if (!info->fix.smem_start) {
- DBG_ERR("fb%d alloc mb fail %d\n", info->node, size);
- return -1;
- }
- info->fix.smem_len = size;
- info->screen_base = mb_phys_to_virt(info->fix.smem_start);
- info->screen_size = size;
- MSG("[wmtfb] fb%d mb 0x%x,len %d,base 0x%x(%d,%d,%d)\n", info->node,
- (int) info->fix.smem_start, info->fix.smem_len,
- (int) info->screen_base, mb_resx, mb_resy, fb_num);
-
- if (wmtfb_probe_ready) {
- int ysize, csize;
-
- size = size / fb_num;
- ysize = mb_resx * mb_resy * y_bpp / 8;
- csize = mb_resx * mb_resy * c_bpp / 8;
- for (i = 0; i < fb_num; i++) {
- memset(info->screen_base + i * size, 0x0, ysize);
- if (c_bpp)
- memset(info->screen_base + i * size + ysize,
- 0x80, csize);
+ vout_config(mask, vo_info, &var);
}
}
-
- if (par->hwc_mode == VOUT_HWC_VIRTUAL) {
- vpp_lock();
- g_vpp.stream_mb_cnt = VPP_MB_ALLOC_NUM;
- size = var->xres_virtual * var->yres * ((y_bpp + c_bpp) / 8);
- for (i = 0; i < g_vpp.stream_mb_cnt; i++)
- g_vpp.stream_mb[i] = info->fix.smem_start + size * i;
- vpp_unlock();
- }
+}
+ vpp_set_mutex(info->node, 0);
return 0;
}
@@ -592,7 +2082,7 @@ static int wmtfb_open
{
DBG_MSG("Enter wmtfb_open\n");
return 0;
-}
+} /* End of wmtfb_open */
static int wmtfb_release
(
@@ -602,58 +2092,61 @@ static int wmtfb_release
{
DBG_MSG("Enter wmtfb_release\n");
return 0;
-}
+} /* End of wmtfb_release */
int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct vout_info_t *par;
int temp;
int force = 0;
-#ifdef DEBUG_DETAIL
- DMSG("Enter %d\n", info->node);
- wmtfb_show_var("[check_var beg] cur var", &info->var);
- wmtfb_show_var("[check_var beg] new var", var);
-#endif
- if (!info->par) { /* link fb & vout info */
- par = vout_info_get_entry(info->node);
- info->par = (void *) par;
- par->fb_info_p = (void *) info;
- }
+ DBG_DETAIL("Enter %d\n", info->node);
- par = (struct vout_info_t *) info->par;
- if (par->alloc_mode == VOUT_ALLOC_GE_OVERSCAN) {
- struct vout_info_t *fb0_par;
+ var->xres_virtual = vpp_calc_fb_width((var->bits_per_pixel == 16) ?
+ VDO_COL_FMT_RGB_565 : VDO_COL_FMT_ARGB, var->xres);
- fb0_par = vout_info_get_entry(0);
- var->xres_virtual = fb0_par->resx_virtual;
- var->yres_virtual = fb0_par->resy_virtual * VPP_MB_ALLOC_NUM;
- } else {
- var->xres_virtual = vpp_calc_fb_width(
- (var->bits_per_pixel == 16) ?
- VDO_COL_FMT_RGB_565 : VDO_COL_FMT_ARGB,
- (var->xres_virtual < var->xres) ?
- var->xres : var->xres_virtual);
+ if ((info->node == 1) && g_vpp.alloc_framebuf) {
+ if( (g_vpp.mb[0] == 0) || ((var->xres != info->var.xres) ||
+ (var->yres != info->var.yres))) {
+ if (var->nonstd) {
+ g_vpp.mb_colfmt = WMT_FB_COLFMT(var->nonstd);
+ } else {
+ g_vpp.mb_colfmt = (var->bits_per_pixel == 16) ?
+ VDO_COL_FMT_RGB_565 : VDO_COL_FMT_ARGB;
+ }
+ if (g_vpp.virtual_display_mode == 1) {
+#ifdef CONFIG_VPP_DYNAMIC_ALLOC
+ vpp_free_framebuffer();
+#endif
+ } else {
+ if (g_vpp.alloc_framebuf(var->xres, var->yres))
+ return -ENOMEM;
+
+ info->fix.smem_start = g_vpp.mb[0];
+ info->fix.smem_len =
+ g_vpp.mb_fb_size * VPP_MB_ALLOC_NUM;
+ info->screen_base =
+ mb_phys_to_virt(info->fix.smem_start);
+ }
+ }
}
- if (wmtfb_alloc(var, info))
- return -ENOMEM;
-
if ((var->xres == 0) || (var->yres == 0))
return -1;
- temp = var->xres_virtual * (var->bits_per_pixel >> 3);
- temp = (temp) ? (info->fix.smem_len / temp) : 0;
- if (temp < var->yres_virtual) {
- var->yres_virtual = temp;
+ temp = (info->fix.smem_len /
+ (var->xres_virtual * var->yres * (var->bits_per_pixel >> 3)));
+ if (temp < 2) {
+ DBG_MSG("smem_len %d,%d\n", info->fix.smem_len, temp);
+ temp = 2;
}
+ if (var->yres_virtual > (var->yres * temp))
+ var->yres_virtual = var->yres * temp;
/* more than 1M is khz not picos (for ut_vpp) */
if (var->pixclock > 1000000) {
- temp = var->pixclock / 1000;
- temp = (temp) ? KHZ2PICOS(temp) : 0;
- DBG_MSG("pixclock patch(>1000000)%d-->%d\n",
- var->pixclock, temp);
+ temp = KHZ2PICOS(var->pixclock / 1000);
+ DBG_MSG("pixclock patch(>1000000)%d-->%d(%d)\n",
+ var->pixclock, temp, (int)PICOS2KHZ(temp) * 1000);
var->pixclock = temp;
}
@@ -665,11 +2158,13 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->left_margin;
vtotal = var->yres + var->lower_margin + var->vsync_len +
var->upper_margin;
- temp = (htotal * vtotal * var->pixclock) / 1000;
- temp = (temp) ? KHZ2PICOS(temp) : 0;
- DBG_MSG("pixclock patch(<100)%d-->%d\n", var->pixclock, temp);
+ temp = htotal * vtotal * var->pixclock;
+ temp = KHZ2PICOS(temp / 1000);
+ DBG_MSG("pixclock patch(<100)%d-->%d(%d)\n",
+ var->pixclock, temp, (int)PICOS2KHZ(temp) * 1000);
var->pixclock = temp;
}
+
#ifdef DEBUG_DETAIL
wmtfb_show_var("cur var", &info->var);
wmtfb_show_var("new var", var);
@@ -688,7 +2183,7 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->transp.length = 0;
}
break;
- case 16: /* ARGB 1555 */
+ case 16: /* ARGB 1555 */
if (var->transp.length) {
var->red.offset = 10;
var->red.length = 5;
@@ -698,7 +2193,7 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.length = 5;
var->transp.offset = 15;
var->transp.length = 1;
- } else { /* RGB 565 */
+ } else { /* RGB 565 */
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
@@ -709,8 +2204,8 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->transp.length = 0;
}
break;
- case 24: /* RGB 888 */
- case 32: /* ARGB 8888 */
+ case 24: /* RGB 888 */
+ case 32: /* ARGB 8888 */
var->red.offset = 16;
var->red.length = 8;
var->green.offset = 8;
@@ -725,9 +2220,6 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if (g_vpp.fb_manual)
return 0;
- if (!wmtfb_probe_ready)
- force = 1;
-
if (g_vpp.fb_recheck & (0x1 << info->node)) {
force = 1;
g_vpp.fb_recheck &= ~(0x1 << info->node);
@@ -737,7 +2229,6 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
memcmp(&info->var.pixclock, &var->pixclock, 4 * 9) || force) {
struct fb_videomode varfbmode;
unsigned int yres_virtual;
- unsigned int xres_virtual;
DPRINT("[wmtfb_check_var] fb%d res(%d,%d)->(%d,%d),force %d\n",
info->node, info->var.xres, info->var.yres,
@@ -747,7 +2238,6 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
wmtfb_show_var("new var", var);
#endif
yres_virtual = var->yres_virtual;
- xres_virtual = var->xres_virtual;
fb_var_to_videomode(&varfbmode, var);
#ifdef DEBUG
DPRINT("new fps %d\n", varfbmode.refresh);
@@ -758,14 +2248,12 @@ int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
fb_videomode_to_var(var, &varfbmode);
var->yres_virtual = yres_virtual;
- var->xres_virtual = xres_virtual;
#ifdef DEBUG
wmtfb_show_var("[wmtfb] time change", var);
#endif
- vout_get_width_height(info->node, &var->width, &var->height);
}
return 0;
-}
+} /* End of wmtfb_check_var */
static int wmtfb_set_par
(
@@ -782,10 +2270,11 @@ static int wmtfb_set_par
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
else
info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->node = 1;
vpp_set_par(info);
info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
return 0;
-}
+} /* End of vt8430fb_set_par */
static int wmtfb_setcolreg
(
@@ -799,7 +2288,7 @@ static int wmtfb_setcolreg
{
return 0;
-}
+} /* End of wmtfb_setcolreg */
static int wmtfb_pan_display
(
@@ -811,7 +2300,7 @@ static int wmtfb_pan_display
DBG_DETAIL("Enter wmtfb_pan_display\n");
- wmtfb_set_mutex(info, 1);
+ vpp_set_mutex(1, 1);
if (var->activate & FB_ACTIVATE_VBL) {
struct timeval tv2;
@@ -828,47 +2317,30 @@ static int wmtfb_pan_display
}
vpp_pan_display(var, info);
do_gettimeofday(&tv1);
- wmtfb_set_mutex(info, 0);
+ vpp_set_mutex(1, 0);
DBG_DETAIL("Exit wmtfb_pan_display\n");
return 0;
-}
+} /* End of wmtfb_pan_display */
-#define UMP_INVALID_SECURE_ID ((unsigned int)-1)
-#define GET_UMP_SECURE_ID _IOWR('m', 310, unsigned int)
-#define GET_UMP_SECURE_ID_BUF1 _IOWR('m', 311, unsigned int)
-#define GET_UMP_SECURE_ID_BUF2 _IOWR('m', 312, unsigned int)
-int wmtfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+static int wmtfb_ioctl
+(
+ struct fb_info *info, /*!<; // a pointer point to struct fb_info */
+ unsigned int cmd, /*!<; // ioctl command */
+ unsigned long arg /*!<; // a argument pointer */
+)
{
int retval = 0;
- switch (cmd) {
- case FBIO_WAITFORVSYNC:
- vpp_wait_vsync(info->node, 1);
- break;
- case GET_UMP_SECURE_ID:
- case GET_UMP_SECURE_ID_BUF1:
- case GET_UMP_SECURE_ID_BUF2:
- {
- unsigned int ump_id;
- extern unsigned int (*mali_get_ump_secure_id)
- (unsigned int addr, unsigned int size);
- if (mali_get_ump_secure_id)
- ump_id = (*mali_get_ump_secure_id)(info->fix.smem_start,
- info->fix.smem_len);
- else
- ump_id = UMP_INVALID_SECURE_ID;
- printk("[wmtfb] ump_id %d,0x%x,len %d\n", ump_id,
- (int)info->fix.smem_start, info->fix.smem_len);
- return put_user((unsigned int) ump_id,
- (unsigned int __user *) arg);
- }
- break;
- default:
- break;
- }
+/* printk("Enter wmtfb_ioctl %x\n",cmd); */
+ if (_IOC_TYPE(cmd) != VPPIO_MAGIC)
+ return retval;
+
+ unlock_fb_info(info);
+ retval = vpp_ioctl(cmd, arg);
+ lock_fb_info(info);
return retval;
-}
+} /* End of wmtfb_ioctl */
static int wmtfb_mmap
(
@@ -905,14 +2377,13 @@ static int wmtfb_mmap
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
- DBGMSG("Exit wmtfb_mmap\n");
return 0;
-}
+} /* End of wmtfb_mmap */
int wmtfb_hw_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
return 0;
-}
+} /* End of wmtfb_hw_cursor */
int wmtfb_blank(int blank, struct fb_info *info)
{
@@ -951,58 +2422,102 @@ static int __init wmtfb_probe
)
{
struct fb_info *info;
- struct fb_var_screeninfo var;
- int i;
-
- DBG_MSG("Enter\n");
+ int cmap_len;
+ u32 map_size;
+ char mode_option[20];
- for (i = 1; ; i++) {
- memcpy(&var, &wmtfb_var, sizeof(struct fb_var_screeninfo));
- if (vpp_get_info(i, &var))
- break;
- info = framebuffer_alloc(0, &dev->dev);
- if (!info)
- return -ENOMEM;
- info->fbops = &wmtfb_ops;
- memcpy(&info->fix, &wmtfb_fix,
- sizeof(struct fb_fix_screeninfo));
- info->fix.id[5] = '0' + i;
- info->flags = FBINFO_DEFAULT;
- if (register_framebuffer(info) < 0)
- return -EINVAL;
+ sprintf(mode_option, "%dx%d@%d",
+ VPP_HD_DISP_RESX, VPP_HD_DISP_RESY, VPP_HD_DISP_FPS);
- MSG(KERN_INFO "fb%d: %s frame buffer device\n",
- info->node, info->fix.id);
+ /* Dynamically allocate memory for fb_info and par.*/
+ info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+ if (!info) {
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
+ return -ENOMEM;
+ }
- wmtfb_check_var(&var, info);
- memcpy(&info->var, &var, sizeof(struct fb_var_screeninfo));
- wmtfb_set_par(info);
- wmtfb_pan_display(&info->var, info);
+ /* Set default fb_info */
+ info->fbops = &wmtfb_ops;
+ info->fix = wmtfb_fix;
- if (info->node == 1) {
- info->dev->power.async_suspend = 1;
- dev_set_drvdata(&dev->dev, info);
- }
+#if 1
+ if (g_vpp.alloc_framebuf) {
+ info->fix.smem_start = g_vpp.mb[0];
+ info->fix.smem_len = g_vpp.mb_fb_size * VPP_MB_ALLOC_NUM;
+ info->screen_base = mb_phys_to_virt(info->fix.smem_start);
+ }
+#endif
+#if 0
+ /* Set video memory */
+ if (!request_mem_region(info->fix.smem_start,
+ info->fix.smem_len, "wmtfb")) {
+ printk(KERN_WARNING
+ "wmtfb: abort, cannot reserve video memory at 0x%lx\n",
+ info->fix.smem_start);
}
- for (i = 0; i < VPP_VOUT_NUM; i++) {
- int blank;
- struct vout_t *vout;
-
- vout = vout_get_entry(i);
- if (!vout)
- continue;
- blank = (vout->status & VPP_VOUT_STS_ACTIVE) ?
- VOUT_BLANK_UNBLANK : VOUT_BLANK_POWERDOWN;
- blank = (vout->status & VPP_VOUT_STS_BLANK) ?
- VOUT_BLANK_NORMAL : blank;
- vout_set_blank(i, blank);
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base) {
+ printk(KERN_ERR
+ "wmtfb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
+ info->fix.smem_len, info->fix.smem_start);
+ return -EIO;
}
- DBG_MSG("Leave\n");
- wmtfb_probe_ready = 1;
- g_vpp.govrh_preinit = 0;
+#endif
+ printk(KERN_INFO "wmtfb: framebuffer at 0x%lx, mapped to 0x%p, "
+ "using %d, total %d\n",
+ info->fix.smem_start, info->screen_base,
+ info->fix.smem_len, info->fix.smem_len);
+
+ /*
+ * Do as a normal fbdev does, but allocate a larger memory for GE.
+ */
+ map_size = PAGE_ALIGN(info->fix.smem_len);
+
+ /*
+ * The pseudopalette is an 16-member array for fbcon.
+ */
+ info->pseudo_palette = info->par;
+ info->par = NULL;
+ info->flags = FBINFO_DEFAULT; /* flag for fbcon. */
+
+ /*
+ * This has to been done !!!
+ */
+ cmap_len = 256; /* Be the same as VESA. */
+ fb_alloc_cmap(&info->cmap, cmap_len, 0);
+
+ /*
+ * The following is done in the case of
+ * having hardware with a static mode.
+ */
+ info->var = wmtfb_var;
+ vpp_get_info(1, &info->var);
+
+ /*
+ * This should give a reasonable default video mode.
+ */
+
+ /*
+ * For drivers that can...
+ */
+ wmtfb_check_var(&info->var, info);
+
+ /*
+ * It's safe to allow fbcon to do it for you.
+ * But in this case, we need it here.
+ */
+ wmtfb_set_par(info);
+
+ if (register_framebuffer(info) < 0)
+ return -EINVAL;
+ info->dev->power.async_suspend = 1;
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+ dev_set_drvdata(&dev->dev, info);
+ wmtfb_fb1_probe = 1;
return 0;
-}
+} /* End of wmtfb_probe */
static int wmtfb_remove
(
@@ -1020,37 +2535,176 @@ static int wmtfb_remove
}
#ifdef CONFIG_PM
+unsigned int vpp_vout_blank_mask;
+
static int wmtfb_suspend
(
struct platform_device *pDev, /*!<; // a pointer struct device */
pm_message_t state /*!<; // suspend state */
)
{
+ vpp_mod_base_t *mod_p;
+ vout_t *vo;
+ int i;
+
+ DBGMSG("Enter wmtfb_suspend\n");
+ vpp_vout_blank_mask = 0;
+ for (i = 0; i <= VPP_VOUT_NUM; i++) {
+ vo = vout_get_entry(i);
+ if (vo && !(vo->status & VPP_VOUT_STS_BLANK))
+ vpp_vout_blank_mask |= (0x1 << i);
+ }
+ vout_set_blank(VPP_VOUT_ALL, VOUT_BLANK_POWERDOWN);
+ if (vout_check_plugin(1))
+ vpp_netlink_notify_plug(VPP_VOUT_ALL ,0);
+ else
+ wmt_set_mmfreq(0);
+
+ /* disable module */
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p && mod_p->suspend)
+ mod_p->suspend(0);
+ }
+#ifdef WMT_FTBLK_HDMI
+ hdmi_suspend(0);
+#endif
+ wmt_suspend_mmfreq();
+#ifdef WMT_FTBLK_LVDS
+ lvds_suspend(0);
+#endif
+ /* disable tg */
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p && mod_p->suspend)
+ mod_p->suspend(1);
+ }
+#ifdef WMT_FTBLK_HDMI
+ hdmi_suspend(1);
+#endif
+#ifdef WMT_FTBLK_LVDS
+ lvds_suspend(1);
+#endif
+ /* backup registers */
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p && mod_p->suspend)
+ mod_p->suspend(2);
+ }
+#ifdef WMT_FTBLK_HDMI
+ hdmi_suspend(2);
+#endif
+#ifdef WMT_FTBLK_LVDS
+ lvds_suspend(2);
+#endif
+#if 0
+ if (lcd_get_lvds_id() == LCD_LVDS_1024x600) {
+ mdelay(5);
+ /* GPIO10 off 8ms -> clock -> off */
+ REG32_VAL(GPIO_BASE_ADDR + 0xC0) &= ~0x400;
+ }
+#endif
return 0;
-}
+} /* End of wmtfb_suspend */
static int wmtfb_resume
(
struct platform_device *pDev /*!<; // a pointer struct device */
)
{
+ vpp_mod_base_t *mod_p;
+ int i;
+
+#if 0
+ if (lcd_get_lvds_id() == LCD_LVDS_1024x600) {
+ /* GPIO10 6ms -> clock r0.02.04 */
+ REG32_VAL(GPIO_BASE_ADDR+0x80) |= 0x400;
+ REG32_VAL(GPIO_BASE_ADDR+0xC0) |= 0x400;
+ }
+#endif
+
+ DBGMSG("Enter wmtfb_resume\n");
+
+ /* restore registers */
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p && mod_p->resume)
+ mod_p->resume(0);
+ }
+#ifdef WMT_FTBLK_LVDS
+ lvds_resume(0);
+#endif
+#ifdef WMT_FTBLK_HDMI
+ hdmi_check_plugin(0);
+ hdmi_resume(0);
+#endif
+ /* enable tg */
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p && mod_p->resume)
+ mod_p->resume(1);
+ }
+#ifdef WMT_FTBLK_LVDS
+ lvds_resume(1);
+#endif
+#ifdef WMT_FTBLK_HDMI
+ hdmi_resume(1);
+#endif
+ /* wait */
+ if(!(g_vpp.virtual_display || g_vpp.dual_display == 0))
+ msleep(150);
+
+ /* enable module */
+ for (i = 0; i < VPP_MOD_MAX; i++) {
+ mod_p = vpp_mod_get_base(i);
+ if (mod_p && mod_p->resume)
+ mod_p->resume(2);
+ }
+#ifdef WMT_FTBLK_LVDS
+ lvds_resume(2);
+#endif
+ if (lcd_get_lvds_id() != LCD_LVDS_1024x600)
+ vout_set_blank(vpp_vout_blank_mask, VOUT_BLANK_UNBLANK);
+ wmt_resume_mmfreq();
+ if (vout_check_plugin(0))
+ vpp_netlink_notify_plug(VPP_VOUT_ALL, 1);
+ else {
+ wmt_set_mmfreq(0);
+ }
+
+#ifdef WMT_FTBLK_HDMI
+ hdmi_resume(2);
+#endif
return 0;
+} /* End of wmtfb_resume */
+
+static void wmtfb_shutdown
+(
+ struct platform_device *pDev /*!<; // a pointer struct device */
+)
+{
+ DPRINT("wmtfb_shutdown\n");
+ hdmi_set_power_down(1);
+ lvds_set_power_down(1);
}
+
#else
#define wmtfb_suspend NULL
#define wmtfb_resume NULL
+#define wmtfb_shutdown NULL
#endif
/***************************************************************************
device driver struct define
****************************************************************************/
static struct platform_driver wmtfb_driver = {
- .driver.name = "wmtfb",
- .driver.bus = &platform_bus_type,
- .probe = wmtfb_probe,
- .remove = wmtfb_remove,
- .suspend = wmtfb_suspend,
- .resume = wmtfb_resume,
+ .driver.name = "wmtfb",
+ .driver.bus = &platform_bus_type,
+ .probe = wmtfb_probe,
+ .remove = wmtfb_remove,
+ .suspend = wmtfb_suspend,
+ .resume = wmtfb_resume,
+ .shutdown = wmtfb_shutdown,
};
/***************************************************************************
@@ -1090,7 +2744,7 @@ static int __init wmtfb_init(void)
}
return ret;
-}
+} /* End of wmtfb_init */
module_init(wmtfb_init);
static void __exit wmtfb_exit(void)
@@ -1100,7 +2754,7 @@ static void __exit wmtfb_exit(void)
platform_driver_unregister(&wmtfb_driver);
platform_device_unregister(&wmtfb_device);
return;
-}
+} /* End of wmtfb_exit */
module_exit(wmtfb_exit);
MODULE_AUTHOR("WonderMedia SW Team");