2010-08-03 16:50:29 +04:00
/*
* Register interface file for Samsung Camera Interface ( FIMC ) driver
*
* Copyright ( c ) 2010 Samsung Electronics
*
* Sylwester Nawrocki , s . nawrocki @ samsung . com
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/io.h>
# include <linux/delay.h>
# include <mach/map.h>
2010-12-27 20:42:15 +03:00
# include <media/s5p_fimc.h>
2010-08-03 16:50:29 +04:00
# include "fimc-core.h"
void fimc_hw_reset ( struct fimc_dev * dev )
{
u32 cfg ;
cfg = readl ( dev - > regs + S5P_CISRCFMT ) ;
cfg | = S5P_CISRCFMT_ITU601_8BIT ;
writel ( cfg , dev - > regs + S5P_CISRCFMT ) ;
/* Software reset. */
cfg = readl ( dev - > regs + S5P_CIGCTRL ) ;
cfg | = ( S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL ) ;
writel ( cfg , dev - > regs + S5P_CIGCTRL ) ;
2010-10-08 12:01:14 +04:00
udelay ( 1000 ) ;
2010-08-03 16:50:29 +04:00
cfg = readl ( dev - > regs + S5P_CIGCTRL ) ;
cfg & = ~ S5P_CIGCTRL_SWRST ;
writel ( cfg , dev - > regs + S5P_CIGCTRL ) ;
}
static u32 fimc_hw_get_in_flip ( u32 ctx_flip )
{
u32 flip = S5P_MSCTRL_FLIP_NORMAL ;
switch ( ctx_flip ) {
case FLIP_X_AXIS :
flip = S5P_MSCTRL_FLIP_X_MIRROR ;
break ;
case FLIP_Y_AXIS :
flip = S5P_MSCTRL_FLIP_Y_MIRROR ;
break ;
case FLIP_XY_AXIS :
flip = S5P_MSCTRL_FLIP_180 ;
break ;
}
return flip ;
}
static u32 fimc_hw_get_target_flip ( u32 ctx_flip )
{
u32 flip = S5P_CITRGFMT_FLIP_NORMAL ;
switch ( ctx_flip ) {
case FLIP_X_AXIS :
flip = S5P_CITRGFMT_FLIP_X_MIRROR ;
break ;
case FLIP_Y_AXIS :
flip = S5P_CITRGFMT_FLIP_Y_MIRROR ;
break ;
case FLIP_XY_AXIS :
flip = S5P_CITRGFMT_FLIP_180 ;
break ;
case FLIP_NONE :
break ;
}
return flip ;
}
2010-10-08 12:01:22 +04:00
void fimc_hw_set_rotation ( struct fimc_ctx * ctx )
{
u32 cfg , flip ;
struct fimc_dev * dev = ctx - > fimc_dev ;
cfg = readl ( dev - > regs + S5P_CITRGFMT ) ;
cfg & = ~ ( S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 |
S5P_CITRGFMT_FLIP_180 ) ;
flip = readl ( dev - > regs + S5P_MSCTRL ) ;
flip & = ~ S5P_MSCTRL_FLIP_MASK ;
/*
* The input and output rotator cannot work simultaneously .
* Use the output rotator in output DMA mode or the input rotator
* in direct fifo output mode .
*/
if ( ctx - > rotation = = 90 | | ctx - > rotation = = 270 ) {
if ( ctx - > out_path = = FIMC_LCDFIFO ) {
cfg | = S5P_CITRGFMT_INROT90 ;
if ( ctx - > rotation = = 270 )
flip | = S5P_MSCTRL_FLIP_180 ;
} else {
cfg | = S5P_CITRGFMT_OUTROT90 ;
if ( ctx - > rotation = = 270 )
cfg | = S5P_CITRGFMT_FLIP_180 ;
}
} else if ( ctx - > rotation = = 180 ) {
if ( ctx - > out_path = = FIMC_LCDFIFO )
flip | = S5P_MSCTRL_FLIP_180 ;
else
cfg | = S5P_CITRGFMT_FLIP_180 ;
}
if ( ctx - > rotation = = 180 | | ctx - > rotation = = 270 )
writel ( flip , dev - > regs + S5P_MSCTRL ) ;
cfg | = fimc_hw_get_target_flip ( ctx - > flip ) ;
writel ( cfg , dev - > regs + S5P_CITRGFMT ) ;
}
2010-08-03 16:50:29 +04:00
void fimc_hw_set_target_format ( struct fimc_ctx * ctx )
{
u32 cfg ;
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_frame * frame = & ctx - > d_frame ;
dbg ( " w= %d, h= %d color: %d " , frame - > width ,
frame - > height , frame - > fmt - > color ) ;
cfg = readl ( dev - > regs + S5P_CITRGFMT ) ;
cfg & = ~ ( S5P_CITRGFMT_FMT_MASK | S5P_CITRGFMT_HSIZE_MASK |
S5P_CITRGFMT_VSIZE_MASK ) ;
switch ( frame - > fmt - > color ) {
case S5P_FIMC_RGB565 :
case S5P_FIMC_RGB666 :
case S5P_FIMC_RGB888 :
cfg | = S5P_CITRGFMT_RGB ;
break ;
case S5P_FIMC_YCBCR420 :
cfg | = S5P_CITRGFMT_YCBCR420 ;
break ;
case S5P_FIMC_YCBYCR422 :
case S5P_FIMC_YCRYCB422 :
case S5P_FIMC_CBYCRY422 :
case S5P_FIMC_CRYCBY422 :
2010-12-08 20:05:08 +03:00
if ( frame - > fmt - > colplanes = = 1 )
2010-08-03 16:50:29 +04:00
cfg | = S5P_CITRGFMT_YCBCR422_1P ;
else
cfg | = S5P_CITRGFMT_YCBCR422 ;
break ;
default :
break ;
}
2010-10-08 12:01:22 +04:00
if ( ctx - > rotation = = 90 | | ctx - > rotation = = 270 ) {
cfg | = S5P_CITRGFMT_HSIZE ( frame - > height ) ;
cfg | = S5P_CITRGFMT_VSIZE ( frame - > width ) ;
} else {
2010-08-03 16:50:29 +04:00
2010-10-08 12:01:22 +04:00
cfg | = S5P_CITRGFMT_HSIZE ( frame - > width ) ;
cfg | = S5P_CITRGFMT_VSIZE ( frame - > height ) ;
2010-08-03 16:50:29 +04:00
}
2010-10-08 12:01:22 +04:00
2010-08-03 16:50:29 +04:00
writel ( cfg , dev - > regs + S5P_CITRGFMT ) ;
cfg = readl ( dev - > regs + S5P_CITAREA ) & ~ S5P_CITAREA_MASK ;
cfg | = ( frame - > width * frame - > height ) ;
writel ( cfg , dev - > regs + S5P_CITAREA ) ;
}
static void fimc_hw_set_out_dma_size ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_frame * frame = & ctx - > d_frame ;
2010-10-08 12:01:22 +04:00
u32 cfg ;
2010-08-03 16:50:29 +04:00
2010-10-08 12:01:22 +04:00
cfg = S5P_ORIG_SIZE_HOR ( frame - > f_width ) ;
cfg | = S5P_ORIG_SIZE_VER ( frame - > f_height ) ;
2010-08-03 16:50:29 +04:00
writel ( cfg , dev - > regs + S5P_ORGOSIZE ) ;
2010-10-07 17:06:16 +04:00
/* Select color space conversion equation (HD/SD size).*/
cfg = readl ( dev - > regs + S5P_CIGCTRL ) ;
if ( frame - > f_width > = 1280 ) /* HD */
cfg | = S5P_CIGCTRL_CSC_ITU601_709 ;
else /* SD */
cfg & = ~ S5P_CIGCTRL_CSC_ITU601_709 ;
writel ( cfg , dev - > regs + S5P_CIGCTRL ) ;
2010-08-03 16:50:29 +04:00
}
void fimc_hw_set_out_dma ( struct fimc_ctx * ctx )
{
u32 cfg ;
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_frame * frame = & ctx - > d_frame ;
struct fimc_dma_offset * offset = & frame - > dma_offset ;
/* Set the input dma offsets. */
cfg = 0 ;
cfg | = S5P_CIO_OFFS_HOR ( offset - > y_h ) ;
cfg | = S5P_CIO_OFFS_VER ( offset - > y_v ) ;
writel ( cfg , dev - > regs + S5P_CIOYOFF ) ;
cfg = 0 ;
cfg | = S5P_CIO_OFFS_HOR ( offset - > cb_h ) ;
cfg | = S5P_CIO_OFFS_VER ( offset - > cb_v ) ;
writel ( cfg , dev - > regs + S5P_CIOCBOFF ) ;
cfg = 0 ;
cfg | = S5P_CIO_OFFS_HOR ( offset - > cr_h ) ;
cfg | = S5P_CIO_OFFS_VER ( offset - > cr_v ) ;
writel ( cfg , dev - > regs + S5P_CIOCROFF ) ;
fimc_hw_set_out_dma_size ( ctx ) ;
/* Configure chroma components order. */
cfg = readl ( dev - > regs + S5P_CIOCTRL ) ;
cfg & = ~ ( S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
S5P_CIOCTRL_YCBCR_PLANE_MASK ) ;
2010-12-08 20:05:08 +03:00
if ( frame - > fmt - > colplanes = = 1 )
2010-08-03 16:50:29 +04:00
cfg | = ctx - > out_order_1p ;
2010-12-08 20:05:08 +03:00
else if ( frame - > fmt - > colplanes = = 2 )
2010-08-03 16:50:29 +04:00
cfg | = ctx - > out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE ;
2010-12-08 20:05:08 +03:00
else if ( frame - > fmt - > colplanes = = 3 )
2010-08-03 16:50:29 +04:00
cfg | = S5P_CIOCTRL_YCBCR_3PLANE ;
writel ( cfg , dev - > regs + S5P_CIOCTRL ) ;
}
static void fimc_hw_en_autoload ( struct fimc_dev * dev , int enable )
{
u32 cfg = readl ( dev - > regs + S5P_ORGISIZE ) ;
if ( enable )
cfg | = S5P_CIREAL_ISIZE_AUTOLOAD_EN ;
else
cfg & = ~ S5P_CIREAL_ISIZE_AUTOLOAD_EN ;
writel ( cfg , dev - > regs + S5P_ORGISIZE ) ;
}
void fimc_hw_en_lastirq ( struct fimc_dev * dev , int enable )
{
2010-10-07 17:06:16 +04:00
u32 cfg = readl ( dev - > regs + S5P_CIOCTRL ) ;
2010-08-03 16:50:29 +04:00
if ( enable )
cfg | = S5P_CIOCTRL_LASTIRQ_ENABLE ;
else
cfg & = ~ S5P_CIOCTRL_LASTIRQ_ENABLE ;
writel ( cfg , dev - > regs + S5P_CIOCTRL ) ;
}
2010-10-08 12:01:14 +04:00
static void fimc_hw_set_prescaler ( struct fimc_ctx * ctx )
2010-08-03 16:50:29 +04:00
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_scaler * sc = & ctx - > scaler ;
2010-10-08 12:01:14 +04:00
u32 cfg , shfactor ;
2010-08-03 16:50:29 +04:00
shfactor = 10 - ( sc - > hfactor + sc - > vfactor ) ;
2010-10-08 12:01:14 +04:00
cfg = S5P_CISCPRERATIO_SHFACTOR ( shfactor ) ;
2010-08-03 16:50:29 +04:00
cfg | = S5P_CISCPRERATIO_HOR ( sc - > pre_hratio ) ;
cfg | = S5P_CISCPRERATIO_VER ( sc - > pre_vratio ) ;
writel ( cfg , dev - > regs + S5P_CISCPRERATIO ) ;
2010-10-08 12:01:14 +04:00
cfg = S5P_CISCPREDST_WIDTH ( sc - > pre_dst_width ) ;
2010-08-03 16:50:29 +04:00
cfg | = S5P_CISCPREDST_HEIGHT ( sc - > pre_dst_height ) ;
writel ( cfg , dev - > regs + S5P_CISCPREDST ) ;
}
void fimc_hw_set_scaler ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_scaler * sc = & ctx - > scaler ;
struct fimc_frame * src_frame = & ctx - > s_frame ;
struct fimc_frame * dst_frame = & ctx - > d_frame ;
u32 cfg = 0 ;
2010-10-08 12:01:14 +04:00
fimc_hw_set_prescaler ( ctx ) ;
2010-08-03 16:50:29 +04:00
if ( ! ( ctx - > flags & FIMC_COLOR_RANGE_NARROW ) )
cfg | = ( S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE ) ;
if ( ! sc - > enabled )
cfg | = S5P_CISCCTRL_SCALERBYPASS ;
if ( sc - > scaleup_h )
cfg | = S5P_CISCCTRL_SCALEUP_H ;
if ( sc - > scaleup_v )
cfg | = S5P_CISCCTRL_SCALEUP_V ;
if ( sc - > copy_mode )
cfg | = S5P_CISCCTRL_ONE2ONE ;
if ( ctx - > in_path = = FIMC_DMA ) {
if ( src_frame - > fmt - > color = = S5P_FIMC_RGB565 )
cfg | = S5P_CISCCTRL_INRGB_FMT_RGB565 ;
else if ( src_frame - > fmt - > color = = S5P_FIMC_RGB666 )
cfg | = S5P_CISCCTRL_INRGB_FMT_RGB666 ;
else if ( src_frame - > fmt - > color = = S5P_FIMC_RGB888 )
cfg | = S5P_CISCCTRL_INRGB_FMT_RGB888 ;
}
if ( ctx - > out_path = = FIMC_DMA ) {
if ( dst_frame - > fmt - > color = = S5P_FIMC_RGB565 )
cfg | = S5P_CISCCTRL_OUTRGB_FMT_RGB565 ;
else if ( dst_frame - > fmt - > color = = S5P_FIMC_RGB666 )
cfg | = S5P_CISCCTRL_OUTRGB_FMT_RGB666 ;
else if ( dst_frame - > fmt - > color = = S5P_FIMC_RGB888 )
cfg | = S5P_CISCCTRL_OUTRGB_FMT_RGB888 ;
} else {
cfg | = S5P_CISCCTRL_OUTRGB_FMT_RGB888 ;
if ( ctx - > flags & FIMC_SCAN_MODE_INTERLACED )
cfg | = S5P_CISCCTRL_INTERLACE ;
}
dbg ( " main_hratio= 0x%X main_vratio= 0x%X " ,
sc - > main_hratio , sc - > main_vratio ) ;
cfg | = S5P_CISCCTRL_SC_HORRATIO ( sc - > main_hratio ) ;
cfg | = S5P_CISCCTRL_SC_VERRATIO ( sc - > main_vratio ) ;
writel ( cfg , dev - > regs + S5P_CISCCTRL ) ;
}
void fimc_hw_en_capture ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
2010-10-07 17:06:16 +04:00
u32 cfg = readl ( dev - > regs + S5P_CIIMGCPT ) ;
if ( ctx - > out_path = = FIMC_DMA ) {
/* one shot mode */
cfg | = S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN ;
} else {
/* Continous frame capture mode (freerun). */
cfg & = ~ ( S5P_CIIMGCPT_CPT_FREN_ENABLE |
S5P_CIIMGCPT_CPT_FRMOD_CNT ) ;
cfg | = S5P_CIIMGCPT_IMGCPTEN ;
}
2010-08-03 16:50:29 +04:00
if ( ctx - > scaler . enabled )
cfg | = S5P_CIIMGCPT_IMGCPTEN_SC ;
writel ( cfg | S5P_CIIMGCPT_IMGCPTEN , dev - > regs + S5P_CIIMGCPT ) ;
}
void fimc_hw_set_effect ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_effect * effect = & ctx - > effect ;
u32 cfg = ( S5P_CIIMGEFF_IE_ENABLE | S5P_CIIMGEFF_IE_SC_AFTER ) ;
cfg | = effect - > type ;
if ( effect - > type = = S5P_FIMC_EFFECT_ARBITRARY ) {
cfg | = S5P_CIIMGEFF_PAT_CB ( effect - > pat_cb ) ;
cfg | = S5P_CIIMGEFF_PAT_CR ( effect - > pat_cr ) ;
}
writel ( cfg , dev - > regs + S5P_CIIMGEFF ) ;
}
static void fimc_hw_set_in_dma_size ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_frame * frame = & ctx - > s_frame ;
u32 cfg_o = 0 ;
u32 cfg_r = 0 ;
if ( FIMC_LCDFIFO = = ctx - > out_path )
2010-10-08 12:01:14 +04:00
cfg_r | = S5P_CIREAL_ISIZE_AUTOLOAD_EN ;
2010-08-03 16:50:29 +04:00
cfg_o | = S5P_ORIG_SIZE_HOR ( frame - > f_width ) ;
cfg_o | = S5P_ORIG_SIZE_VER ( frame - > f_height ) ;
cfg_r | = S5P_CIREAL_ISIZE_WIDTH ( frame - > width ) ;
cfg_r | = S5P_CIREAL_ISIZE_HEIGHT ( frame - > height ) ;
writel ( cfg_o , dev - > regs + S5P_ORGISIZE ) ;
writel ( cfg_r , dev - > regs + S5P_CIREAL_ISIZE ) ;
}
void fimc_hw_set_in_dma ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_frame * frame = & ctx - > s_frame ;
struct fimc_dma_offset * offset = & frame - > dma_offset ;
2010-10-08 12:01:14 +04:00
u32 cfg ;
2010-08-03 16:50:29 +04:00
/* Set the pixel offsets. */
2010-10-08 12:01:14 +04:00
cfg = S5P_CIO_OFFS_HOR ( offset - > y_h ) ;
2010-08-03 16:50:29 +04:00
cfg | = S5P_CIO_OFFS_VER ( offset - > y_v ) ;
writel ( cfg , dev - > regs + S5P_CIIYOFF ) ;
2010-10-08 12:01:14 +04:00
cfg = S5P_CIO_OFFS_HOR ( offset - > cb_h ) ;
2010-08-03 16:50:29 +04:00
cfg | = S5P_CIO_OFFS_VER ( offset - > cb_v ) ;
writel ( cfg , dev - > regs + S5P_CIICBOFF ) ;
2010-10-08 12:01:14 +04:00
cfg = S5P_CIO_OFFS_HOR ( offset - > cr_h ) ;
2010-08-03 16:50:29 +04:00
cfg | = S5P_CIO_OFFS_VER ( offset - > cr_v ) ;
writel ( cfg , dev - > regs + S5P_CIICROFF ) ;
/* Input original and real size. */
fimc_hw_set_in_dma_size ( ctx ) ;
2010-10-08 12:01:14 +04:00
/* Use DMA autoload only in FIFO mode. */
2010-08-03 16:50:29 +04:00
fimc_hw_en_autoload ( dev , ctx - > out_path = = FIMC_LCDFIFO ) ;
/* Set the input DMA to process single frame only. */
cfg = readl ( dev - > regs + S5P_MSCTRL ) ;
cfg & = ~ ( S5P_MSCTRL_FLIP_MASK
| S5P_MSCTRL_INFORMAT_MASK
| S5P_MSCTRL_IN_BURST_COUNT_MASK
| S5P_MSCTRL_INPUT_MASK
| S5P_MSCTRL_C_INT_IN_MASK
| S5P_MSCTRL_2P_IN_ORDER_MASK ) ;
2010-12-08 18:48:23 +03:00
cfg | = S5P_MSCTRL_IN_BURST_COUNT ( 4 ) | S5P_MSCTRL_INPUT_MEMORY ;
2010-08-03 16:50:29 +04:00
switch ( frame - > fmt - > color ) {
2010-12-08 18:48:23 +03:00
case S5P_FIMC_RGB565 . . . S5P_FIMC_RGB888 :
2010-08-03 16:50:29 +04:00
cfg | = S5P_MSCTRL_INFORMAT_RGB ;
break ;
case S5P_FIMC_YCBCR420 :
cfg | = S5P_MSCTRL_INFORMAT_YCBCR420 ;
2010-12-08 20:05:08 +03:00
if ( frame - > fmt - > colplanes = = 2 )
2010-08-03 16:50:29 +04:00
cfg | = ctx - > in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE ;
else
cfg | = S5P_MSCTRL_C_INT_IN_3PLANE ;
break ;
2010-12-08 18:48:23 +03:00
case S5P_FIMC_YCBYCR422 . . . S5P_FIMC_CRYCBY422 :
2010-12-08 20:05:08 +03:00
if ( frame - > fmt - > colplanes = = 1 ) {
2010-08-03 16:50:29 +04:00
cfg | = ctx - > in_order_1p
| S5P_MSCTRL_INFORMAT_YCBCR422_1P ;
} else {
cfg | = S5P_MSCTRL_INFORMAT_YCBCR422 ;
2010-12-08 20:05:08 +03:00
if ( frame - > fmt - > colplanes = = 2 )
2010-08-03 16:50:29 +04:00
cfg | = ctx - > in_order_2p
| S5P_MSCTRL_C_INT_IN_2PLANE ;
else
cfg | = S5P_MSCTRL_C_INT_IN_3PLANE ;
}
break ;
default :
break ;
}
/*
* Input DMA flip mode ( and rotation ) .
* Do not allow simultaneous rotation and flipping .
*/
if ( ! ctx - > rotation & & ctx - > out_path = = FIMC_LCDFIFO )
cfg | = fimc_hw_get_in_flip ( ctx - > flip ) ;
writel ( cfg , dev - > regs + S5P_MSCTRL ) ;
/* Input/output DMA linear/tiled mode. */
cfg = readl ( dev - > regs + S5P_CIDMAPARAM ) ;
cfg & = ~ S5P_CIDMAPARAM_TILE_MASK ;
if ( tiled_fmt ( ctx - > s_frame . fmt ) )
cfg | = S5P_CIDMAPARAM_R_64X32 ;
if ( tiled_fmt ( ctx - > d_frame . fmt ) )
cfg | = S5P_CIDMAPARAM_W_64X32 ;
writel ( cfg , dev - > regs + S5P_CIDMAPARAM ) ;
}
void fimc_hw_set_input_path ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
u32 cfg = readl ( dev - > regs + S5P_MSCTRL ) ;
cfg & = ~ S5P_MSCTRL_INPUT_MASK ;
if ( ctx - > in_path = = FIMC_DMA )
cfg | = S5P_MSCTRL_INPUT_MEMORY ;
else
cfg | = S5P_MSCTRL_INPUT_EXTCAM ;
writel ( cfg , dev - > regs + S5P_MSCTRL ) ;
}
void fimc_hw_set_output_path ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
u32 cfg = readl ( dev - > regs + S5P_CISCCTRL ) ;
cfg & = ~ S5P_CISCCTRL_LCDPATHEN_FIFO ;
if ( ctx - > out_path = = FIMC_LCDFIFO )
cfg | = S5P_CISCCTRL_LCDPATHEN_FIFO ;
writel ( cfg , dev - > regs + S5P_CISCCTRL ) ;
}
void fimc_hw_set_input_addr ( struct fimc_dev * dev , struct fimc_addr * paddr )
{
2010-10-08 12:01:14 +04:00
u32 cfg = readl ( dev - > regs + S5P_CIREAL_ISIZE ) ;
2010-08-03 16:50:29 +04:00
cfg | = S5P_CIREAL_ISIZE_ADDR_CH_DIS ;
writel ( cfg , dev - > regs + S5P_CIREAL_ISIZE ) ;
2010-09-28 12:49:11 +04:00
writel ( paddr - > y , dev - > regs + S5P_CIIYSA ( 0 ) ) ;
writel ( paddr - > cb , dev - > regs + S5P_CIICBSA ( 0 ) ) ;
writel ( paddr - > cr , dev - > regs + S5P_CIICRSA ( 0 ) ) ;
2010-08-03 16:50:29 +04:00
cfg & = ~ S5P_CIREAL_ISIZE_ADDR_CH_DIS ;
writel ( cfg , dev - > regs + S5P_CIREAL_ISIZE ) ;
}
2010-10-08 12:01:14 +04:00
void fimc_hw_set_output_addr ( struct fimc_dev * dev ,
struct fimc_addr * paddr , int index )
2010-08-03 16:50:29 +04:00
{
2010-10-08 12:01:14 +04:00
int i = ( index = = - 1 ) ? 0 : index ;
do {
2010-08-03 16:50:29 +04:00
writel ( paddr - > y , dev - > regs + S5P_CIOYSA ( i ) ) ;
writel ( paddr - > cb , dev - > regs + S5P_CIOCBSA ( i ) ) ;
writel ( paddr - > cr , dev - > regs + S5P_CIOCRSA ( i ) ) ;
2010-10-08 12:01:14 +04:00
dbg ( " dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X " ,
i , paddr - > y , paddr - > cb , paddr - > cr ) ;
} while ( index = = - 1 & & + + i < FIMC_MAX_OUT_BUFS ) ;
2010-08-03 16:50:29 +04:00
}
2010-10-07 17:06:16 +04:00
int fimc_hw_set_camera_polarity ( struct fimc_dev * fimc ,
2010-12-27 20:42:15 +03:00
struct s5p_fimc_isp_info * cam )
2010-10-07 17:06:16 +04:00
{
u32 cfg = readl ( fimc - > regs + S5P_CIGCTRL ) ;
cfg & = ~ ( S5P_CIGCTRL_INVPOLPCLK | S5P_CIGCTRL_INVPOLVSYNC |
S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC ) ;
if ( cam - > flags & FIMC_CLK_INV_PCLK )
cfg | = S5P_CIGCTRL_INVPOLPCLK ;
if ( cam - > flags & FIMC_CLK_INV_VSYNC )
cfg | = S5P_CIGCTRL_INVPOLVSYNC ;
if ( cam - > flags & FIMC_CLK_INV_HREF )
cfg | = S5P_CIGCTRL_INVPOLHREF ;
if ( cam - > flags & FIMC_CLK_INV_HSYNC )
cfg | = S5P_CIGCTRL_INVPOLHSYNC ;
writel ( cfg , fimc - > regs + S5P_CIGCTRL ) ;
return 0 ;
}
int fimc_hw_set_camera_source ( struct fimc_dev * fimc ,
2010-12-27 20:42:15 +03:00
struct s5p_fimc_isp_info * cam )
2010-10-07 17:06:16 +04:00
{
struct fimc_frame * f = & fimc - > vid_cap . ctx - > s_frame ;
u32 cfg = 0 ;
2010-12-27 21:02:16 +03:00
u32 bus_width ;
int i ;
static const struct {
u32 pixelcode ;
u32 cisrcfmt ;
u16 bus_width ;
} pix_desc [ ] = {
{ V4L2_MBUS_FMT_YUYV8_2X8 , S5P_CISRCFMT_ORDER422_YCBYCR , 8 } ,
{ V4L2_MBUS_FMT_YVYU8_2X8 , S5P_CISRCFMT_ORDER422_YCRYCB , 8 } ,
{ V4L2_MBUS_FMT_VYUY8_2X8 , S5P_CISRCFMT_ORDER422_CRYCBY , 8 } ,
{ V4L2_MBUS_FMT_UYVY8_2X8 , S5P_CISRCFMT_ORDER422_CBYCRY , 8 } ,
/* TODO: Add pixel codes for 16-bit bus width */
} ;
2010-10-07 17:06:16 +04:00
if ( cam - > bus_type = = FIMC_ITU_601 | | cam - > bus_type = = FIMC_ITU_656 ) {
2010-12-27 21:02:16 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( pix_desc ) ; i + + ) {
if ( fimc - > vid_cap . fmt . code = = pix_desc [ i ] . pixelcode ) {
cfg = pix_desc [ i ] . cisrcfmt ;
bus_width = pix_desc [ i ] . bus_width ;
break ;
}
}
2010-10-07 17:06:16 +04:00
2010-12-27 21:02:16 +03:00
if ( i = = ARRAY_SIZE ( pix_desc ) ) {
v4l2_err ( & fimc - > vid_cap . v4l2_dev ,
" Camera color format not supported: %d \n " ,
fimc - > vid_cap . fmt . code ) ;
2010-10-07 17:06:16 +04:00
return - EINVAL ;
}
if ( cam - > bus_type = = FIMC_ITU_601 ) {
2010-12-27 21:02:16 +03:00
if ( bus_width = = 8 )
2010-10-07 17:06:16 +04:00
cfg | = S5P_CISRCFMT_ITU601_8BIT ;
2010-12-27 21:02:16 +03:00
else if ( bus_width = = 16 )
2010-10-07 17:06:16 +04:00
cfg | = S5P_CISRCFMT_ITU601_16BIT ;
} /* else defaults to ITU-R BT.656 8-bit */
}
cfg | = S5P_CISRCFMT_HSIZE ( f - > o_width ) | S5P_CISRCFMT_VSIZE ( f - > o_height ) ;
writel ( cfg , fimc - > regs + S5P_CISRCFMT ) ;
return 0 ;
}
int fimc_hw_set_camera_offset ( struct fimc_dev * fimc , struct fimc_frame * f )
{
u32 hoff2 , voff2 ;
u32 cfg = readl ( fimc - > regs + S5P_CIWDOFST ) ;
cfg & = ~ ( S5P_CIWDOFST_HOROFF_MASK | S5P_CIWDOFST_VEROFF_MASK ) ;
cfg | = S5P_CIWDOFST_OFF_EN |
S5P_CIWDOFST_HOROFF ( f - > offs_h ) |
S5P_CIWDOFST_VEROFF ( f - > offs_v ) ;
writel ( cfg , fimc - > regs + S5P_CIWDOFST ) ;
/* See CIWDOFSTn register description in the datasheet for details. */
hoff2 = f - > o_width - f - > width - f - > offs_h ;
voff2 = f - > o_height - f - > height - f - > offs_v ;
cfg = S5P_CIWDOFST2_HOROFF ( hoff2 ) | S5P_CIWDOFST2_VEROFF ( voff2 ) ;
writel ( cfg , fimc - > regs + S5P_CIWDOFST2 ) ;
return 0 ;
}
int fimc_hw_set_camera_type ( struct fimc_dev * fimc ,
2010-12-27 20:42:15 +03:00
struct s5p_fimc_isp_info * cam )
2010-10-07 17:06:16 +04:00
{
u32 cfg , tmp ;
struct fimc_vid_cap * vid_cap = & fimc - > vid_cap ;
cfg = readl ( fimc - > regs + S5P_CIGCTRL ) ;
/* Select ITU B interface, disable Writeback path and test pattern. */
cfg & = ~ ( S5P_CIGCTRL_TESTPAT_MASK | S5P_CIGCTRL_SELCAM_ITU_A |
S5P_CIGCTRL_SELCAM_MIPI | S5P_CIGCTRL_CAMIF_SELWB |
S5P_CIGCTRL_SELCAM_MIPI_A ) ;
if ( cam - > bus_type = = FIMC_MIPI_CSI2 ) {
cfg | = S5P_CIGCTRL_SELCAM_MIPI ;
if ( cam - > mux_id = = 0 )
cfg | = S5P_CIGCTRL_SELCAM_MIPI_A ;
/* TODO: add remaining supported formats. */
if ( vid_cap - > fmt . code = = V4L2_MBUS_FMT_VYUY8_2X8 ) {
tmp = S5P_CSIIMGFMT_YCBCR422_8BIT ;
} else {
err ( " camera image format not supported: %d " ,
vid_cap - > fmt . code ) ;
return - EINVAL ;
}
writel ( tmp | ( 0x1 < < 8 ) , fimc - > regs + S5P_CSIIMGFMT ) ;
} else if ( cam - > bus_type = = FIMC_ITU_601 | |
cam - > bus_type = = FIMC_ITU_656 ) {
if ( cam - > mux_id = = 0 ) /* ITU-A, ITU-B: 0, 1 */
cfg | = S5P_CIGCTRL_SELCAM_ITU_A ;
} else if ( cam - > bus_type = = FIMC_LCD_WB ) {
cfg | = S5P_CIGCTRL_CAMIF_SELWB ;
} else {
err ( " invalid camera bus type selected \n " ) ;
return - EINVAL ;
}
writel ( cfg , fimc - > regs + S5P_CIGCTRL ) ;
return 0 ;
}