/* Unblank the screen */ OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo) { int res; OMAPLFB_CONSOLE_LOCK(); res = fb_blank(psDevInfo->psLINFBInfo, 0); OMAPLFB_CONSOLE_UNLOCK(); if (res != 0 && res != -EINVAL) { printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_blank failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res); return (OMAPLFB_ERROR_GENERIC); } return (OMAPLFB_OK); }
/* Blank the screen */ static void OMAPLFBBlankDisplay(OMAPLFB_DEVINFO *psDevInfo) { OMAPLFB_CONSOLE_LOCK(); fb_blank(psDevInfo->psLINFBInfo, 1); OMAPLFB_CONSOLE_UNLOCK(); }
/* Flip display to given buffer */ void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer) { struct fb_var_screeninfo sFBVar; int res; OMAPLFB_CONSOLE_LOCK(); sFBVar = psDevInfo->psLINFBInfo->var; sFBVar.xoffset = 0; sFBVar.yoffset = psBuffer->ulYOffset; #if defined(CONFIG_DSSCOMP) /* * If flipping to a NULL buffer, blank the screen to prevent * warnings/errors from the display subsystem. */ if (psBuffer->sSysAddr.uiAddr == 0) { struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo); OMAP_DSS_MANAGER(psDSSMan, psDSSDev); if (psDSSMan != NULL && psDSSMan->blank != NULL) { res = psDSSMan->blank(psDSSMan, false); if (res != 0) { DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: DSS manager blank call failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res)); } } } { /* * If using DSSCOMP, we need to use dsscomp queuing for normal * framebuffer updates, so that previously used overlays get * automatically disabled, and manager gets dirtied. We can * do that because DSSCOMP takes ownership of all pipelines on * a manager. */ struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix; struct dsscomp_setup_dispc_data d = { .num_ovls = 1, .num_mgrs = 1, .mgrs[0].alpha_blending = 1, .ovls[0] = { .cfg = { .win.w = sFBVar.xres, .win.h = sFBVar.yres, .crop.x = sFBVar.xoffset, .crop.y = sFBVar.yoffset, .crop.w = sFBVar.xres, .crop.h = sFBVar.yres, .width = sFBVar.xres_virtual, .height = sFBVar.yres_virtual, .stride = sFBFix.line_length, .enabled = (psBuffer->sSysAddr.uiAddr != 0), .global_alpha = 255, }, }, }; /* do not map buffer into TILER1D as it is contiguous */ struct tiler_pa_info *pas[] = { NULL }; d.ovls[0].ba = (u32) psBuffer->sSysAddr.uiAddr; omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode); res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL); if (res != 0) { DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: dsscomp_gralloc_queue failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res)); } } #else /* defined(CONFIG_DSSCOMP) */ { unsigned long ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres; /* * PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY should be defined to * work around flipping problems seen with the Taal LCDs on * Blaze. * The work around is safe to use with other types of screen * on Blaze (e.g. HDMI) and on other platforms (e.g. Panda * board). */ #if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) /* * Attempt to change the virtual screen resolution if it is too * small. Note that fb_set_var also pans the display. */ if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual) #endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */ { sFBVar.xres_virtual = sFBVar.xres; sFBVar.yres_virtual = ulYResVirtual; sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar); if (res != 0) { printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res); } } #if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) else { res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar); if (res != 0) { printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res); } } #endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */ } #endif /* defined(CONFIG_DSSCOMP) */ OMAPLFB_CONSOLE_UNLOCK(); }
int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile) { uint32_t *puiArgs; uint32_t uiCmd; unsigned uiPVRDevID; int ret = 0; OMAPLFB_DEVINFO *psDevInfo; if (arg == NULL) { return -EFAULT; } puiArgs = (uint32_t *)arg; uiCmd = puiArgs[PVR_DRM_DISP_ARG_CMD]; uiPVRDevID = puiArgs[PVR_DRM_DISP_ARG_DEV]; psDevInfo = OMAPLFBPVRDevIDToDevInfo(uiPVRDevID); if (psDevInfo == NULL) { return -EINVAL; } switch (uiCmd) { case PVR_DRM_DISP_CMD_LEAVE_VT: case PVR_DRM_DISP_CMD_ENTER_VT: { OMAPLFB_BOOL bLeaveVT = (uiCmd == PVR_DRM_DISP_CMD_LEAVE_VT); DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: %s\n", __FUNCTION__, uiPVRDevID, bLeaveVT ? "Leave VT" : "Enter VT")); OMAPLFBCreateSwapChainLock(psDevInfo); OMAPLFBAtomicBoolSet(&psDevInfo->sLeaveVT, bLeaveVT); if (psDevInfo->psSwapChain != NULL) { flush_workqueue(psDevInfo->psSwapChain->psWorkQueue); if (bLeaveVT) { OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer); (void) OMAPLFBCheckModeAndSync(psDevInfo); } } OMAPLFBCreateSwapChainUnLock(psDevInfo); (void) OMAPLFBUnblankDisplay(psDevInfo); break; } case PVR_DRM_DISP_CMD_ON: case PVR_DRM_DISP_CMD_STANDBY: case PVR_DRM_DISP_CMD_SUSPEND: case PVR_DRM_DISP_CMD_OFF: { int iFBMode; #if defined(DEBUG) { const char *pszMode; switch(uiCmd) { case PVR_DRM_DISP_CMD_ON: pszMode = "On"; break; case PVR_DRM_DISP_CMD_STANDBY: pszMode = "Standby"; break; case PVR_DRM_DISP_CMD_SUSPEND: pszMode = "Suspend"; break; case PVR_DRM_DISP_CMD_OFF: pszMode = "Off"; break; default: pszMode = "(Unknown Mode)"; break; } printk(KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n", __FUNCTION__, uiPVRDevID, pszMode); } #endif switch(uiCmd) { case PVR_DRM_DISP_CMD_ON: iFBMode = FB_BLANK_UNBLANK; break; case PVR_DRM_DISP_CMD_STANDBY: iFBMode = FB_BLANK_HSYNC_SUSPEND; break; case PVR_DRM_DISP_CMD_SUSPEND: iFBMode = FB_BLANK_VSYNC_SUSPEND; break; case PVR_DRM_DISP_CMD_OFF: iFBMode = FB_BLANK_POWERDOWN; break; default: return -EINVAL; } OMAPLFBCreateSwapChainLock(psDevInfo); if (psDevInfo->psSwapChain != NULL) { flush_workqueue(psDevInfo->psSwapChain->psWorkQueue); } OMAPLFB_CONSOLE_LOCK(); ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode); OMAPLFB_CONSOLE_UNLOCK(); OMAPLFBCreateSwapChainUnLock(psDevInfo); break; } default: { ret = -EINVAL; break; } } return ret; }
void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer) { struct fb_var_screeninfo sFBVar; int res; unsigned long ulYResVirtual; OMAPLFB_CONSOLE_LOCK(); sFBVar = psDevInfo->psLINFBInfo->var; sFBVar.xoffset = 0; sFBVar.yoffset = psBuffer->ulYOffset; ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres; #if defined(CONFIG_DSSCOMP) { struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix; struct dsscomp_setup_dispc_data d = { .num_ovls = 1, .num_mgrs = 1, .mgrs[0].alpha_blending = 1, .ovls[0] = { .cfg = { .win.w = sFBVar.xres, .win.h = sFBVar.yres, .crop.x = sFBVar.xoffset, .crop.y = sFBVar.yoffset, .crop.w = sFBVar.xres, .crop.h = sFBVar.yres, .width = sFBVar.xres_virtual, .height = sFBVar.yres_virtual, .stride = sFBFix.line_length, .enabled = 1, .global_alpha = 255, }, }, }; struct tiler_pa_info *pas[] = { NULL }; d.ovls[0].ba = sFBFix.smem_start; omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode); res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL); } #else #if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual) #endif { sFBVar.xres_virtual = sFBVar.xres; sFBVar.yres_virtual = ulYResVirtual; sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar); if (res != 0) { printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res); } } #if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) else { res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar); if (res != 0) { printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res); } } #endif #endif OMAPLFB_CONSOLE_UNLOCK(); }