static int fimc_open(struct file *filp) { struct fimc_control *ctrl; struct s3c_platform_fimc *pdata; int ret; ctrl = video_get_drvdata(video_devdata(filp)); pdata = to_fimc_plat(ctrl->dev); mutex_lock(&ctrl->lock); if (atomic_read(&ctrl->in_use)) { ret = -EBUSY; goto resource_busy; } else { atomic_inc(&ctrl->in_use); } if (pdata->clk_on) pdata->clk_on(to_platform_device(ctrl->dev), ctrl->clk); #if defined(CONFIG_VIDEO_FIMC_FIFO) fimc_hwset_clksrc(ctrl,FIMC_SCLK); fimc_hwset_sclk_enable(ctrl); #endif if (pdata->hw_ver == 0x40) fimc_hw_reset_camera(ctrl); /* Apply things to interface register */ fimc_hwset_reset(ctrl); filp->private_data = ctrl; ctrl->fb.open_fifo = s3cfb_open_fifo; ctrl->fb.close_fifo = s3cfb_close_fifo; ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_WIDTH, (unsigned long)&ctrl->fb.lcd_hres); if (ret < 0) fimc_err("Fail: S3CFB_GET_LCD_WIDTH\n"); ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_HEIGHT, (unsigned long)&ctrl->fb.lcd_vres); if (ret < 0) fimc_err("Fail: S3CFB_GET_LCD_HEIGHT\n"); ctrl->mem.curr = ctrl->mem.base; ctrl->status = FIMC_STREAMOFF; mutex_unlock(&ctrl->lock); return 0; resource_busy: mutex_unlock(&ctrl->lock); return ret; }
static int fimc_change_fifo_position(struct fimc_control *ctrl, struct fimc_ctx *ctx) { struct v4l2_rect fimd_rect; struct s3cfb_user_window window; int ret = -1; memset(&fimd_rect, 0, sizeof(struct v4l2_rect)); ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect); if (ret < 0) { fimc_err("fimc_fimd_rect fail\n"); return -EINVAL; } /* Update WIN position */ window.x = fimd_rect.left; window.y = fimd_rect.top; ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_WIN_POSITION, (unsigned long)&window); if (ret < 0) { fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n"); return -EINVAL; } return 0; }
static int fimc_init_camera(struct fimc_control *ctrl) { struct fimc_global *fimc = get_fimc_dev(); struct s3c_platform_fimc *pdata; struct s3c_platform_camera *cam; struct v4l2_streamparm stream; int ret; pdata = to_fimc_plat(ctrl->dev); if (pdata->default_cam >= FIMC_MAXCAMS) { dev_err(ctrl->dev, "%s: invalid camera index\n", __func__); return -EINVAL; } if (!fimc->camera[pdata->default_cam]) { dev_err(ctrl->dev, "no external camera device\n"); return -ENODEV; } /* * ctrl->cam may not be null if already s_input called, * otherwise, that should be default_cam if ctrl->cam is null. */ if (!ctrl->cam) ctrl->cam = fimc->camera[pdata->default_cam]; cam = ctrl->cam; /* do nothing if already initialized */ if (cam->initialized) return 0; /* * WriteBack mode doesn't need to set clock and power, * but it needs to set source width, height depend on LCD resolution. */ if (cam->id == CAMERA_WB) { s3cfb_direct_ioctl(0, S3CFB_GET_LCD_WIDTH, (unsigned long)&cam->width); s3cfb_direct_ioctl(0, S3CFB_GET_LCD_HEIGHT, (unsigned long)&cam->height); cam->window.width = cam->width; cam->window.height = cam->height; cam->initialized = 1; return 0; } /* set rate for mclk */ if (cam->clk->set_rate) { clk_disable(cam->clk); cam->clk->set_rate(cam->clk, cam->clk_rate); clk_enable(cam->clk); dev_info(ctrl->dev, "clock for camera: %d\n", cam->clk_rate); } /* enable camera power if needed */ if (cam->cam_power) cam->cam_power(1); /* camera s/w reset*/ fimc_hwset_hw_reset(); /* subdev call for init */ ret = v4l2_subdev_call(cam->sd, core, init, 0); if (ret == -ENOIOCTLCMD) { dev_err(ctrl->dev, "%s: init subdev api not supported\n", __func__); return ret; } /*set resolution SVGA*/ stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; stream.parm.capture.capturemode = 0; ret = v4l2_subdev_call(cam->sd, video, s_parm, &stream); if (ret == -ENOIOCTLCMD) { dev_err(ctrl->dev, "%s: init subdev api not supported\n", __func__); return ret; } if (cam->type == CAM_TYPE_MIPI) { /* * subdev call for sleep/wakeup: * no error although no s_stream api support */ v4l2_subdev_call(cam->sd, video, s_stream, 0); s3c_csis_start(cam->mipi_lanes, cam->mipi_settle, \ cam->mipi_align, cam->width, cam->height); v4l2_subdev_call(cam->sd, video, s_stream, 1); } cam->initialized = 1; return 0; }
static inline u32 fimc_irq_out_dma(struct fimc_control *ctrl) { struct fimc_buf_set buf_set; u32 next = 0, wakeup = 1; int idx = ctrl->out->idx.active; int ret = -1, i; if (ctrl->status == FIMC_READY_OFF) { ctrl->out->idx.active = -1; ctrl->status = FIMC_STREAMOFF; return wakeup; } /* Attach done buffer to outgoing queue. */ ret = fimc_attach_out_queue(ctrl, idx); if (ret < 0) fimc_err("Failed: fimc_attach_out_queue\n"); if(ctrl->out->overlay.mode == FIMC_OVERLAY_DMA_AUTO) { ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_WIN_ADDR, \ (unsigned long)ctrl->out->dst[idx].base[FIMC_ADDR_Y]); if (ret < 0) { fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n"); return -EINVAL; } if(ctrl->fb.is_enable == 0) { ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_WIN_ON, \ (unsigned long)NULL); if (ret < 0) { fimc_err("direct_ioctl(S3CFB_SET_WIN_ON) fail\n"); return -EINVAL; } ctrl->fb.is_enable = 1; } } /* Detach buffer from incomming queue. */ ret = fimc_detach_in_queue(ctrl, &next); if (ret == 0) { /* There is a buffer in incomming queue. */ fimc_outdev_set_src_addr(ctrl, ctrl->out->src[next].base); memset(&buf_set, 0x00, sizeof(buf_set)); buf_set.base[FIMC_ADDR_Y] = ctrl->out->dst[next].base[FIMC_ADDR_Y]; for (i = 0; i < FIMC_PHYBUFS; i++) fimc_hwset_output_address(ctrl, &buf_set, i); ret = fimc_outdev_start_camif(ctrl); if (ret < 0) fimc_err("Fail: fimc_start_camif\n"); ctrl->out->idx.active = next; ctrl->status = FIMC_STREAMON; } else { /* There is no buffer in incomming queue. */ ctrl->out->idx.active = -1; ctrl->status = FIMC_STREAMON_IDLE; } return wakeup; }
static int fimc_open(struct file *filp) { struct fimc_control *ctrl; struct s3c_platform_fimc *pdata; unsigned long flags; int ret; u32 cfg; #ifdef VIEW_FUNCTION_CALL printk("[FIMC_DEV] %s(%d)\n", __func__, __LINE__); #endif /* An ugly hack to make the i2c pins output low */ if (unlikely(make_i2c_pin_low == 1)) { cfg = readl(S5P64XX_GPD1DAT); cfg &= ~(0x1 << 0); writel(cfg, S5P64XX_GPD1DAT); cfg = readl(S5P64XX_GPD1DAT); cfg &= ~(0x1 << 1); writel(cfg, S5P64XX_GPD1DAT); make_i2c_pin_low = 0; } ctrl = video_get_drvdata(video_devdata(filp)); #ifdef S5P6442_POWER_GATING_CAM del_timer(&g_fimc_domain_timer); // fimc0 controller for Camera if(ctrl->id == CAM_ID){ spin_lock_irqsave(&fimc_domain_lock, flags); gFIMC_CNT[CAM_ID]++; s5p6442_idle_pm_gpiocfg(S5P6442_CAM_ID, S5P6442_ACTIVE_MODE); s5p6442_pwrgate_config(S5P6442_CAM_ID, S5P6442_ACTIVE_MODE); spin_unlock_irqrestore(&fimc_domain_lock, flags); } // gFIMC_CNT++; // } #endif #ifdef CONFIG_CPU_FREQ if(ctrl->id == CAM_ID){ set_dvfs_level(0); } #endif /* CONFIG_CPU_FREQ */ pdata = to_fimc_plat(ctrl->dev); mutex_lock(&ctrl->lock); if (atomic_read(&ctrl->in_use)) { ret = -EBUSY; goto resource_busy; } else { atomic_inc(&ctrl->in_use); } if (pdata->clk_on) pdata->clk_on(to_platform_device(ctrl->dev), ctrl->clk); /* Apply things to interface register */ fimc_hwset_reset(ctrl); filp->private_data = ctrl; ctrl->fb.open_fifo = s3cfb_open_fifo; ctrl->fb.close_fifo = s3cfb_close_fifo; ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_WIDTH, (unsigned long)&ctrl->fb.lcd_hres); if (ret < 0) dev_err(ctrl->dev, "Fail: S3CFB_GET_LCD_WIDTH\n"); ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_HEIGHT, (unsigned long)&ctrl->fb.lcd_vres); if (ret < 0) dev_err(ctrl->dev, "Fail: S3CFB_GET_LCD_HEIGHT\n"); ctrl->status = FIMC_STREAMOFF; #if 0 /* To do : have to send ctrl to the fimd driver. */ ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_SUSPEND_FIFO, (unsigned long)fimc_sleep); if (ret < 0) dev_err(ctrl->dev, "s3cfb_direct_ioctl(S3CFB_SET_SUSPEND_FIFO) fail\n"); ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_RESUME_FIFO, (unsigned long)fimc_wakeup); if (ret < 0) dev_err(ctrl->dev, "s3cfb_direct_ioctl(S3CFB_SET_SUSPEND_FIFO) fail\n"); #endif mutex_unlock(&ctrl->lock); return 0; resource_busy: mutex_unlock(&ctrl->lock); return ret; }
S3C_BC_ERROR S3C_BC_Register(void) { S3C_BC_DEVINFO *psDevInfo; int i; unsigned long addr; IMG_UINT32 pixelformat; struct fb_fix_screeninfo fix; struct fb_var_screeninfo var; s3cfb_direct_ioctl(FB_NUM, FBIOGET_FSCREENINFO, (unsigned long)&fix); s3cfb_direct_ioctl(FB_NUM, FBIOGET_VSCREENINFO, (unsigned long)&var); g_screen_w = var.xres; g_screen_h = var.yres; if ( g_screen_w >= g_screen_h ) g_screen_h = g_screen_w; else g_screen_w = g_screen_h; if (16 == var.bits_per_pixel) { pixelformat = PVRSRV_PIXEL_FORMAT_RGB565; g_screen_stride = g_screen_w*2; } else { pixelformat = PVRSRV_PIXEL_FORMAT_ARGB8888; g_screen_stride = g_screen_w*4; } g_buffer_size = ((g_screen_h * g_screen_stride + S3C_BC_DEVICE_PHYS_PAGE_SIZE - 1) & ~(S3C_BC_DEVICE_PHYS_PAGE_SIZE-1)); psDevInfo = GetAnchorPtr(); if (!psDevInfo) { psDevInfo = (S3C_BC_DEVINFO *)BCAllocKernelMem(sizeof(S3C_BC_DEVINFO)); if(!psDevInfo) { return (S3C_BC_ERROR_OUT_OF_MEMORY);/* failure */ } SetAnchorPtr((void*)psDevInfo); psDevInfo->ulRefCount = 0; psDevInfo->ulDeviceID = S3C_BC_DEVICE_ID; if(BCGetLibFuncAddr ("PVRGetBufferClassJTable", &pfnGetPVRJTable) != S3C_BC_OK) { return (S3C_BC_ERROR_INIT_FAILURE); } if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable)) { return (S3C_BC_ERROR_INIT_FAILURE); } psDevInfo->sBufferInfo.pixelformat = pixelformat; psDevInfo->sBufferInfo.ui32Width = g_screen_w; psDevInfo->sBufferInfo.ui32Height = g_screen_h; psDevInfo->sBufferInfo.ui32ByteStride = g_screen_stride; psDevInfo->sBufferInfo.ui32BufferDeviceID = S3C_BC_DEVICE_ID; psDevInfo->sBufferInfo.ui32Flags = 0; psDevInfo->sBufferInfo.ui32BufferCount = S3C_BC_DEVICE_BUFFER_COUNT; addr = S3C_BC_DEVICE_PHYS_ADDR_START; for(i = 0; i < S3C_BC_DEVICE_BUFFER_COUNT; i++, addr += g_buffer_size) { psDevInfo->sSystemBuffer[i].sSysAddr.uiAddr = (IMG_UINTPTR_T)addr; } psDevInfo->sBCJTable.ui32TableSize = sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE); psDevInfo->sBCJTable.pfnOpenBCDevice = OpenBCDevice; psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice; psDevInfo->sBCJTable.pfnGetBCBuffer = GetBCBuffer; psDevInfo->sBCJTable.pfnGetBCInfo = GetBCInfo; psDevInfo->sBCJTable.pfnGetBufferAddr = GetBCBufferAddr; if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterBCDevice (&psDevInfo->sBCJTable, (IMG_UINT32*)&psDevInfo->ulDeviceID ) != PVRSRV_OK) { return (S3C_BC_ERROR_DEVICE_REGISTER_FAILED); } } psDevInfo->ulRefCount++; return (S3C_BC_OK); }
int init() { IMG_UINT32 screen_w, screen_h; IMG_UINT32 pa_fb, va_fb; IMG_UINT32 byteSize; int i; int rgb_format, bytes_per_pixel; struct fb_fix_screeninfo fix; struct fb_var_screeninfo var; s3cfb_direct_ioctl(FB_NUM, FBIOGET_FSCREENINFO, (unsigned long)&fix); s3cfb_direct_ioctl(FB_NUM, FBIOGET_VSCREENINFO, (unsigned long)&var); screen_w = var.xres; screen_h = var.yres; pa_fb = fix.smem_start; printk("PA FB = 0x%X, bits per pixel = %d\n", (unsigned int)fix.smem_start, (unsigned int)var.bits_per_pixel); va_fb = (unsigned long)phys_to_virt(pa_fb); printk("screen width=%d height=%d va=0x%x pa=0x%x\n", (int)screen_w, (int)screen_h, (unsigned int)va_fb, (unsigned int)pa_fb); #if 1 regs = (volatile unsigned int)ioremap(0xF8000000, 0x00100000); #endif //spin_lock_init(g_psLCDInfo->psSwapChainLock); if (g_psLCDInfo == NULL) { PFN_CMD_PROC pfnCmdProcList[DC_S3C_LCD_COMMAND_COUNT]; IMG_UINT32 aui32SyncCountList[DC_S3C_LCD_COMMAND_COUNT][2]; g_psLCDInfo = (S3C_LCD_DEVINFO*)kmalloc(sizeof(S3C_LCD_DEVINFO),GFP_KERNEL); g_psLCDInfo->ui32NumFormats = S3C_DISPLAY_FORMAT_NUM; switch (var.bits_per_pixel) { case 16: rgb_format = PVRSRV_PIXEL_FORMAT_RGB565; bytes_per_pixel = 2; break; case 32: rgb_format = PVRSRV_PIXEL_FORMAT_ARGB8888; bytes_per_pixel = 4; break; default: rgb_format = PVRSRV_PIXEL_FORMAT_ARGB8888; bytes_per_pixel = 4; break; } g_psLCDInfo->asDisplayForamtList[0].pixelformat = rgb_format; g_psLCDInfo->ui32NumDims = S3C_DISPLAY_DIM_NUM; g_psLCDInfo->asDisplayDimList[0].ui32ByteStride = (bytes_per_pixel) * screen_w; g_psLCDInfo->asDisplayDimList[0].ui32Height = screen_h; g_psLCDInfo->asDisplayDimList[0].ui32Width = screen_w; g_psLCDInfo->sSysBuffer.bufferPAddr.uiAddr = pa_fb; g_psLCDInfo->sSysBuffer.bufferVAddr = (IMG_CPU_VIRTADDR)va_fb; byteSize = screen_w * screen_h * bytes_per_pixel; g_psLCDInfo->sSysBuffer.byteSize = (IMG_UINT32)byteSize; for (i=0; i<S3C_MAX_BACKBUFFERRS; i++) { g_psLCDInfo->asBackBuffers[i].byteSize = g_psLCDInfo->sSysBuffer.byteSize; #if 1 // modified by jamie (2010.04.09) // to use the frame buffer already allocated by LCD driver. g_psLCDInfo->asBackBuffers[i].bufferPAddr.uiAddr = pa_fb + byteSize * (i+1); g_psLCDInfo->asBackBuffers[i].bufferVAddr = (IMG_CPU_VIRTADDR)phys_to_virt(g_psLCDInfo->asBackBuffers[i].bufferPAddr.uiAddr); #else if(AllocLinearMemory( g_psLCDInfo->asBackBuffers[i].byteSize, (IMG_UINT32*)&(g_psLCDInfo->asBackBuffers[i].bufferVAddr), &(g_psLCDInfo->asBackBuffers[i].bufferPAddr.uiAddr))) return 1; #endif printk("Back frameBuffer[%d].VAddr=%p PAddr=%p size=%d\n", i, (void*)g_psLCDInfo->asBackBuffers[i].bufferVAddr, (void*)g_psLCDInfo->asBackBuffers[i].bufferPAddr.uiAddr, (int)g_psLCDInfo->asBackBuffers[i].byteSize); } g_psLCDInfo->bFlushCommands = S3C_FALSE; g_psLCDInfo->psSwapChain = NULL; PVRGetDisplayClassJTable(&(g_psLCDInfo->sPVRJTable)); g_psLCDInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE); g_psLCDInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice; g_psLCDInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice; g_psLCDInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats; g_psLCDInfo->sDCJTable.pfnEnumDCDims = EnumDCDims; g_psLCDInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer; g_psLCDInfo->sDCJTable.pfnGetDCInfo = GetDCInfo; g_psLCDInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr; g_psLCDInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain; g_psLCDInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain; g_psLCDInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect; g_psLCDInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect; g_psLCDInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey; g_psLCDInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey; g_psLCDInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers; g_psLCDInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer; g_psLCDInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem; g_psLCDInfo->sDCJTable.pfnSetDCState = S3CSetState; g_psLCDInfo->sDisplayInfo.ui32MinSwapInterval=0; g_psLCDInfo->sDisplayInfo.ui32MaxSwapInterval=0; g_psLCDInfo->sDisplayInfo.ui32MaxSwapChains=1; g_psLCDInfo->sDisplayInfo.ui32MaxSwapChainBuffers=S3C_NUM_TOTAL_BUFFER; g_psLCDInfo->sDisplayInfo.ui32PhysicalWidthmm=var.width; // width of lcd in mm g_psLCDInfo->sDisplayInfo.ui32PhysicalHeightmm=var.height; // height of lcd in mm strncpy(g_psLCDInfo->sDisplayInfo.szDisplayName, "s3c_lcd", MAX_DISPLAY_NAME_SIZE); if(g_psLCDInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (&(g_psLCDInfo->sDCJTable), (IMG_UINT32 *)(&(g_psLCDInfo->ui32DisplayID))) != PVRSRV_OK) { return 1; } //printk("deviceID:%d\n",(int)g_psLCDInfo->ui32DisplayID); // register flip command pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip; aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; aui32SyncCountList[DC_FLIP_COMMAND][1] = 2; if (g_psLCDInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(g_psLCDInfo->ui32DisplayID, &pfnCmdProcList[0], aui32SyncCountList, DC_S3C_LCD_COMMAND_COUNT) != PVRSRV_OK) { printk("failing register commmand proc list deviceID:%d\n",(int)g_psLCDInfo->ui32DisplayID); return PVRSRV_ERROR_CANT_REGISTER_CALLBACK; } LCDControllerBase = (volatile unsigned int *)ioremap(0xf8000000,1024); } return 0; }