static int pxa168fb_ovly_ioctl(struct fb_info *fi, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; struct pxa168fb_info *fbi = (struct pxa168fb_info *)fi->par; struct pxa168fb_mach_info *mi = fbi->dev->platform_data; int vid_on = 1; int val = 0, mask = 0; unsigned char param; int blendval = 0; int res, tmp; int ret = 0; unsigned long flags; #ifdef CONFIG_DYNAMIC_PRINTK_DEBUG debug_identify_called_ioctl(fi, cmd, arg); #endif switch (cmd) { case FB_IOCTL_CLEAR_FRAMEBUFFER: if (!mi->mmap) return -EINVAL; pxa168fb_clear_framebuffer(fi); return 0; break; case FB_IOCTL_WAIT_VSYNC: param = (arg & 0x3); wait_for_vsync(fbi, param); break; case FB_IOCTL_GET_VIEWPORT_INFO:/*if rotate 90/270, w/h swap*/ mutex_lock(&fbi->access_ok); if (fbi->surface.viewPortInfo.rotation == 90 || fbi->surface.viewPortInfo.rotation == 270) { tmp = fbi->surface.viewPortInfo.srcWidth; fbi->surface.viewPortInfo.srcWidth = fbi->surface.viewPortInfo.srcHeight; fbi->surface.viewPortInfo.srcHeight = tmp; fbi->surface.viewPortInfo.rotation = 360 - fbi->surface.viewPortInfo.rotation; } res = copy_to_user(argp, &fbi->surface.viewPortInfo, sizeof(struct _sViewPortInfo)) ? -EFAULT : 0; if (fbi->surface.viewPortInfo.rotation == 90 || fbi->surface.viewPortInfo.rotation == 270) { tmp = fbi->surface.viewPortInfo.srcWidth; fbi->surface.viewPortInfo.srcWidth = fbi->surface.viewPortInfo.srcHeight; fbi->surface.viewPortInfo.srcHeight = tmp; fbi->surface.viewPortInfo.rotation = 360 - fbi->surface.viewPortInfo.rotation; } mutex_unlock(&fbi->access_ok); return res; case FB_IOCTL_SET_VIEWPORT_INFO:/*if rotate 90/270, w/h swap*/ mutex_lock(&fbi->access_ok); memset(&gOvlySurface, 0, sizeof(gOvlySurface)); gOvlySurface.videoMode = -1; if (copy_from_user(&gOvlySurface.viewPortInfo, argp, sizeof(gOvlySurface.viewPortInfo))) { mutex_unlock(&fbi->access_ok); return -EFAULT; } if (unsupport_format(fbi, gOvlySurface.viewPortInfo, -1)) { mutex_unlock(&fbi->access_ok); return -EFAULT; } gOvlySurface.viewPortInfo.rotation = (360 - gOvlySurface.viewPortInfo.rotation) % 360; if (gOvlySurface.viewPortInfo.rotation == 90 || gOvlySurface.viewPortInfo.rotation == 270) { tmp = gOvlySurface.viewPortInfo.srcWidth; gOvlySurface.viewPortInfo.srcWidth = gOvlySurface.viewPortInfo.srcHeight; gOvlySurface.viewPortInfo.srcHeight = tmp; } ret = check_surface(fi, &gOvlySurface); if (ret > 0) { pxa168fb_set_par(fi); ret = 0; } else if (ret < 0) { pr_err("fbi %d (line %d): vid %d, check surface" "return error\n", fbi->id, __LINE__, fbi->vid); ret = -EFAULT; } mutex_unlock(&fbi->access_ok); return ret; break; case FB_IOCTL_SET_VIDEO_MODE: /* * Get data from user space. */ memset(&gOvlySurface, 0, sizeof(gOvlySurface)); if (copy_from_user(&gOvlySurface.videoMode, argp, sizeof(gOvlySurface.videoMode))) return -EFAULT; if (unsupport_format(fbi, gOvlySurface.viewPortInfo, gOvlySurface.videoMode)) return -EFAULT; ret = check_surface(fi, &gOvlySurface); if (ret > 0) { pxa168fb_set_par(fi); ret = 0; } else if (ret < 0) { pr_err("fbi %d (line %d): vid %d, check surface" "return error\n", fbi->id, __LINE__, fbi->vid); ret = -EFAULT; } return ret; break; case FB_IOCTL_GET_VIDEO_MODE: return copy_to_user(argp, &fbi->surface.videoMode, sizeof(u32)) ? -EFAULT : 0; case FB_IOCTL_FLIP_VID_BUFFER: return flip_buffer(fi, arg); case FB_IOCTL_GET_FREELIST: return get_freelist(fi, arg); case FB_IOCTL_FLIP_VSYNC: return flip_buffer_vsync(fi, arg); case FB_IOCTL_GET_BUFF_ADDR: { return copy_to_user(argp, &fbi->surface.videoBufferAddr, sizeof(struct _sVideoBufferAddr)) ? -EFAULT : 0; } case FB_IOCTL_SET_VID_OFFSET: mutex_lock(&fbi->access_ok); memset(&gOvlySurface, 0, sizeof(gOvlySurface)); gOvlySurface.videoMode = -1; if (copy_from_user(&gOvlySurface.viewPortOffset, argp, sizeof(gOvlySurface.viewPortOffset))) { mutex_unlock(&fbi->access_ok); return -EFAULT; } ret = check_surface(fi, &gOvlySurface); if (ret > 0) { pxa168fb_set_par(fi); ret = 0; } else if (ret < 0) { pr_err("fbi %d (line %d): vid %d, check surface" "return error\n", fbi->id, __LINE__, fbi->vid); ret = -EFAULT; } mutex_unlock(&fbi->access_ok); return ret; break; case FB_IOCTL_GET_VID_OFFSET: return copy_to_user(argp, &fbi->surface.viewPortOffset, sizeof(struct _sViewPortOffset)) ? -EFAULT : 0; case FB_IOCTL_SET_SURFACE: { mutex_lock(&fbi->access_ok); /* Get user-mode data. */ if (copy_from_user(&fbi->surface_bak, argp, sizeof(struct _sOvlySurface))) { mutex_unlock(&fbi->access_ok); return -EFAULT; } fbi->surface_set = 1; mutex_unlock(&fbi->access_ok); return 0; } case FB_IOCTL_GET_SURFACE: { mutex_lock(&fbi->access_ok); if (fbi->surface_set) { ret = copy_to_user(argp, &fbi->surface_bak, sizeof(struct _sOvlySurface)); } else { ret = copy_to_user(argp, &fbi->surface, sizeof(struct _sOvlySurface)); } ret = (ret ? -EFAULT : 0); mutex_unlock(&fbi->access_ok); return ret; } case FB_IOCTL_SET_COLORKEYnALPHA: if (copy_from_user(&fbi->ckey_alpha, argp, sizeof(struct _sColorKeyNAlpha))) return -EFAULT; pxa168fb_ovly_set_colorkeyalpha(fbi); break; case FB_IOCTL_GET_COLORKEYnALPHA: if (copy_to_user(argp, &fbi->ckey_alpha, sizeof(struct _sColorKeyNAlpha))) return -EFAULT; break; case FB_IOCTL_SWITCH_VID_OVLY: if (copy_from_user(&vid_on, argp, sizeof(int))) return -EFAULT; spin_lock_irqsave(&fbi->var_lock, flags); mask = CFG_DMA_ENA_MASK; fbi->dma_on = vid_on ? 1 : 0; val = CFG_DMA_ENA(check_modex_active(fbi)); if (!val && gfx_info.fbi[0]->active) { pxa688_vdma_release(fbi->id, fbi->vid); /* switch off, disable DMA */ dma_ctrl_set(fbi->id, 0, mask, val); } else if (list_empty(&fbi->buf_waitlist.dma_queue) && !fbi->buf_current) /* switch on, but no buf flipped, return error */ ; /* ret = -EAGAIN; */ printk(KERN_DEBUG "SWITCH_VID_OVLY fbi %d dma_on %d," " val %d, waitlist empty %d buf_current %p, ret %d\n", fbi->id, fbi->dma_on, val, list_empty(&fbi->buf_waitlist.dma_queue), fbi->buf_current, ret); pxa688fb_vsmooth_set(fbi->id, 1, vid_vsmooth & vid_on); spin_unlock_irqrestore(&fbi->var_lock, flags); return ret; break; case FB_IOCTL_SWAP_VIDEO_RED_BLUE: param = (arg & 0x1); dma_ctrl_set(fbi->id, 0, CFG_DMA_SWAPRB_MASK, CFG_DMA_SWAPRB(param)); return 0; break; case FB_IOCTL_SWAP_VIDEO_U_V: param = (arg & 0x1); dma_ctrl_set(fbi->id, 0, CFG_DMA_SWAPUV_MASK, CFG_DMA_SWAPUV(param)); return 0; break; case FB_IOCTL_SWAP_VIDEO_Y_UV: param = (arg & 0x1); dma_ctrl_set(fbi->id, 0, CFG_DMA_SWAPYU_MASK, CFG_DMA_SWAPYU(param)); return 0; break; case FB_IOCTL_PUT_VIDEO_ALPHABLEND: /* * This puts the blending control to the Video layer. */ mask = CFG_ALPHA_MODE_MASK | CFG_ALPHA_MASK; val = CFG_ALPHA_MODE(0) | CFG_ALPHA(0xff); dma_ctrl_set(fbi->id, 1, mask, val); return 0; break; case FB_IOCTL_PUT_GLOBAL_ALPHABLEND: /* * The userspace application can specify a byte value for the * amount of global blend between the video layer and thei * graphic layer. * * The alpha blending is per the formula below: * P = (V[P] * blendval/255) + (G[P] * (1 - blendval/255)) * where: P = Pixel value, V = Video Layer, * and G = Graphic Layer */ blendval = (arg & 0xff); mask = CFG_ALPHA_MODE_MASK | CFG_ALPHA_MASK; val = CFG_ALPHA_MODE(2) | CFG_ALPHA(blendval); dma_ctrl_set(fbi->id, 1, mask, val); return 0; break; case FB_IOCTL_PUT_GRAPHIC_ALPHABLEND: /* * This puts the blending back to the default mode of allowing * the graphic layer to do pixel level blending. */ mask = CFG_ALPHA_MODE_MASK | CFG_ALPHA_MASK; val = CFG_ALPHA_MODE(1) | CFG_ALPHA(0x0); dma_ctrl_set(fbi->id, 1, mask, val); return 0; break; default: break; } return 0; }
static u32 dovefb_ovly_set_colorkeyalpha(struct dovefb_layer_info *dfli) { unsigned int rb; unsigned int temp; unsigned int x, x_ckey; struct _sColorKeyNAlpha *color_a = &dfli->ckey_alpha; /* reset to 0x0 to disable color key. */ x = readl(dfli->reg_base + LCD_SPU_DMA_CTRL1) & ~(CFG_COLOR_KEY_MASK | CFG_ALPHA_MODE_MASK | CFG_ALPHA_MASK); /* switch to color key mode */ switch (color_a->mode) { case DOVEFB_DISABLE_COLORKEY_MODE: /* do nothing */ break; case DOVEFB_ENABLE_Y_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x1); break; case DOVEFB_ENABLE_U_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x2); break; case DOVEFB_ENABLE_V_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x4); break; case DOVEFB_ENABLE_RGB_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x3); /* check whether h/w turn on RB swap. */ rb = readl(dfli->reg_base + LCD_SPU_DMA_CTRL0); if (rb & CFG_DMA_SWAPRB_MASK) { /* exchange r b fields. */ temp = color_a->Y_ColorAlpha; color_a->Y_ColorAlpha = color_a->V_ColorAlpha; color_a->V_ColorAlpha = temp; } break; case DOVEFB_ENABLE_R_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x5); break; case DOVEFB_ENABLE_G_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x6); break; case DOVEFB_ENABLE_B_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x7); break; default: pr_debug("unknown mode"); return -1; } /* switch to alpha path selection */ switch (color_a->alphapath) { case DOVEFB_VID_PATH_ALPHA: x |= CFG_ALPHA_MODE(0x0); break; case DOVEFB_GRA_PATH_ALPHA: x |= CFG_ALPHA_MODE(0x1); break; case DOVEFB_CONFIG_ALPHA: x |= CFG_ALPHA_MODE(0x2); break; default: pr_debug("unknown alpha path"); return -1; } /* configure alpha */ x |= CFG_ALPHA((color_a->config & 0xff)); /* Have to program new regs to enable color key for new chip. */ x_ckey = readl(dfli->reg_base + LCD_SPU_ADV_REG); writel(x_ckey | (0x1 << 19), dfli->reg_base + LCD_SPU_ADV_REG); writel(x, dfli->reg_base + LCD_SPU_DMA_CTRL1); writel(color_a->Y_ColorAlpha, dfli->reg_base + LCD_SPU_COLORKEY_Y); writel(color_a->U_ColorAlpha, dfli->reg_base + LCD_SPU_COLORKEY_U); writel(color_a->V_ColorAlpha, dfli->reg_base + LCD_SPU_COLORKEY_V); return 0; }
static u32 pxa168fb_ovly_set_colorkeyalpha(struct pxa168fb_info *fbi) { struct _sColorKeyNAlpha color_a = fbi->ckey_alpha; unsigned int rb, x, layer, dma0, shift, r, b; struct pxa168fb_mach_info *mi; struct lcd_regs *regs; dev_dbg(fbi->fb_info->dev, "Enter %s\n", __func__); mi = fbi->dev->platform_data; regs = get_regs(fbi->id); dma0 = dma_ctrl_read(fbi->id, 0); shift = fbi->id ? 20 : 18; rb = layer = 0; r = color_a.Y_ColorAlpha; b = color_a.V_ColorAlpha; /* reset to 0x0 to disable color key. */ x = dma_ctrl_read(fbi->id, 1) & ~(CFG_COLOR_KEY_MASK | CFG_ALPHA_MODE_MASK | CFG_ALPHA_MASK); /* switch to color key mode */ switch (color_a.mode) { case FB_DISABLE_COLORKEY_MODE: /* do nothing */ break; case FB_ENABLE_Y_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x1); break; case FB_ENABLE_U_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x2); break; case FB_ENABLE_V_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x4); pr_info("V colorkey not supported, Chroma key instead\n"); break; case FB_ENABLE_RGB_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x3); rb = 1; break; case FB_ENABLE_R_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x1); rb = 1; break; case FB_ENABLE_G_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x6); pr_info("G colorkey not supported, Luma key instead\n"); break; case FB_ENABLE_B_COLORKEY_MODE: x |= CFG_COLOR_KEY_MODE(0x7); rb = 1; break; default: pr_info("unknown mode"); return -1; } /* switch to alpha path selection */ switch (color_a.alphapath) { case FB_VID_PATH_ALPHA: x |= CFG_ALPHA_MODE(0x0); layer = CFG_CKEY_DMA; if (rb) rb = ((dma0 & CFG_DMA_SWAPRB_MASK) >> 4) ^ (mi->panel_rbswap); break; case FB_GRA_PATH_ALPHA: x |= CFG_ALPHA_MODE(0x1); layer = CFG_CKEY_GRA; if (rb) rb = ((dma0 & CFG_GRA_SWAPRB_MASK) >> 12) ^ (mi->panel_rbswap); break; case FB_CONFIG_ALPHA: x |= CFG_ALPHA_MODE(0x2); rb = 0; break; default: pr_info("unknown alpha path"); return -1; } /* check whether DMA turn on RB swap for this pixelformat. */ if (rb) { if (color_a.mode == FB_ENABLE_R_COLORKEY_MODE) { x &= ~CFG_COLOR_KEY_MODE(0x1); x |= CFG_COLOR_KEY_MODE(0x7); } if (color_a.mode == FB_ENABLE_B_COLORKEY_MODE) { x &= ~CFG_COLOR_KEY_MODE(0x7); x |= CFG_COLOR_KEY_MODE(0x1); } /* exchange r b fields. */ r = color_a.V_ColorAlpha; b = color_a.Y_ColorAlpha; /* only alpha_Y take effect, switch back from V */ if (color_a.mode == FB_ENABLE_RGB_COLORKEY_MODE) { r &= 0xffffff00; r |= (color_a.Y_ColorAlpha & 0xff); } } /* configure alpha */ x |= CFG_ALPHA((color_a.config & 0xff)); dma_ctrl_write(fbi->id, 1, x); writel(r, ®s->v_colorkey_y); writel(color_a.U_ColorAlpha, ®s->v_colorkey_u); writel(b, ®s->v_colorkey_v); if (fbi->id != 2) { /* enable DMA colorkey on graphics/video layer * in panel/TV path */ x = readl(fbi->reg_base + LCD_TV_CTRL1); x &= ~(3<<shift); x |= layer<<shift; writel(x, fbi->reg_base + LCD_TV_CTRL1); } return 0; }