2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-08-03 16:50:29 +04:00
/*
* Register interface file for Samsung Camera Interface ( FIMC ) driver
*
2013-03-20 17:44:39 +04:00
* Copyright ( C ) 2010 - 2013 Samsung Electronics Co . , Ltd .
* Sylwester Nawrocki < s . nawrocki @ samsung . com >
2010-08-03 16:50:29 +04:00
*/
# include <linux/delay.h>
2013-03-20 17:44:39 +04:00
# include <linux/io.h>
# include <linux/regmap.h>
2015-11-14 00:40:07 +03:00
# include <media/drv-intf/exynos-fimc.h>
2013-03-24 19:54:25 +04:00
# include "media-dev.h"
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
# include "fimc-reg.h"
2010-08-03 16:50:29 +04:00
# include "fimc-core.h"
void fimc_hw_reset ( struct fimc_dev * dev )
{
u32 cfg ;
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CISRCFMT ) ;
cfg | = FIMC_REG_CISRCFMT_ITU601_8BIT ;
writel ( cfg , dev - > regs + FIMC_REG_CISRCFMT ) ;
2010-08-03 16:50:29 +04:00
/* Software reset. */
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIGCTRL ) ;
cfg | = ( FIMC_REG_CIGCTRL_SWRST | FIMC_REG_CIGCTRL_IRQ_LEVEL ) ;
writel ( cfg , dev - > regs + FIMC_REG_CIGCTRL ) ;
2011-09-02 13:25:32 +04:00
udelay ( 10 ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIGCTRL ) ;
cfg & = ~ FIMC_REG_CIGCTRL_SWRST ;
writel ( cfg , dev - > regs + FIMC_REG_CIGCTRL ) ;
2011-10-05 21:20:45 +04:00
2013-03-26 15:22:21 +04:00
if ( dev - > drv_data - > out_buf_count > 4 )
2011-10-05 21:20:45 +04:00
fimc_hw_set_dma_seq ( dev , 0xF ) ;
2010-08-03 16:50:29 +04:00
}
2010-12-27 20:47:32 +03:00
static u32 fimc_hw_get_in_flip ( struct fimc_ctx * ctx )
2010-08-03 16:50:29 +04:00
{
2012-05-02 13:14:49 +04:00
u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL ;
2010-08-03 16:50:29 +04:00
2011-08-25 02:25:10 +04:00
if ( ctx - > hflip )
2012-05-02 13:14:49 +04:00
flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR ;
2012-11-26 18:08:26 +04:00
if ( ctx - > vflip )
flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR ;
2011-08-25 02:25:10 +04:00
2010-12-27 20:47:32 +03:00
if ( ctx - > rotation < = 90 )
return flip ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
return ( flip ^ FIMC_REG_MSCTRL_FLIP_180 ) & FIMC_REG_MSCTRL_FLIP_180 ;
2010-08-03 16:50:29 +04:00
}
2010-12-27 20:47:32 +03:00
static u32 fimc_hw_get_target_flip ( struct fimc_ctx * ctx )
2010-08-03 16:50:29 +04:00
{
2012-05-02 13:14:49 +04:00
u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL ;
2010-08-03 16:50:29 +04:00
2011-08-25 02:25:10 +04:00
if ( ctx - > hflip )
2012-05-02 13:14:49 +04:00
flip | = FIMC_REG_CITRGFMT_FLIP_Y_MIRROR ;
2012-11-26 18:08:26 +04:00
if ( ctx - > vflip )
flip | = FIMC_REG_CITRGFMT_FLIP_X_MIRROR ;
2011-08-25 02:25:10 +04:00
2010-12-27 20:47:32 +03:00
if ( ctx - > rotation < = 90 )
return flip ;
2012-05-02 13:14:49 +04:00
return ( flip ^ FIMC_REG_CITRGFMT_FLIP_180 ) & FIMC_REG_CITRGFMT_FLIP_180 ;
2010-08-03 16:50:29 +04:00
}
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 ;
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CITRGFMT ) ;
cfg & = ~ ( FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 |
FIMC_REG_CITRGFMT_FLIP_180 ) ;
2010-10-08 12:01:22 +04:00
/*
* 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 ) {
2012-04-26 13:26:29 +04:00
if ( ctx - > out_path = = FIMC_IO_LCDFIFO )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CITRGFMT_INROT90 ;
2010-10-08 12:01:22 +04:00
else
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CITRGFMT_OUTROT90 ;
2010-10-08 12:01:22 +04:00
}
2012-04-26 13:26:29 +04:00
if ( ctx - > out_path = = FIMC_IO_DMA ) {
2010-12-27 20:47:32 +03:00
cfg | = fimc_hw_get_target_flip ( ctx ) ;
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CITRGFMT ) ;
2010-12-27 20:47:32 +03:00
} else {
/* LCD FIFO path */
2012-05-02 13:14:49 +04:00
flip = readl ( dev - > regs + FIMC_REG_MSCTRL ) ;
flip & = ~ FIMC_REG_MSCTRL_FLIP_MASK ;
2010-12-27 20:47:32 +03:00
flip | = fimc_hw_get_in_flip ( ctx ) ;
2012-05-02 13:14:49 +04:00
writel ( flip , dev - > regs + FIMC_REG_MSCTRL ) ;
2010-12-27 20:47:32 +03:00
}
2010-10-08 12:01:22 +04:00
}
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 ,
2012-05-02 13:14:49 +04:00
frame - > height , frame - > fmt - > color ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CITRGFMT ) ;
cfg & = ~ ( FIMC_REG_CITRGFMT_FMT_MASK | FIMC_REG_CITRGFMT_HSIZE_MASK |
FIMC_REG_CITRGFMT_VSIZE_MASK ) ;
2010-08-03 16:50:29 +04:00
switch ( frame - > fmt - > color ) {
2012-04-26 13:26:29 +04:00
case FIMC_FMT_RGB444 . . . FIMC_FMT_RGB888 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CITRGFMT_RGB ;
2010-08-03 16:50:29 +04:00
break ;
2012-04-26 13:26:29 +04:00
case FIMC_FMT_YCBCR420 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CITRGFMT_YCBCR420 ;
2010-08-03 16:50:29 +04:00
break ;
2012-04-26 13:26:29 +04:00
case FIMC_FMT_YCBYCR422 . . . FIMC_FMT_CRYCBY422 :
2010-12-08 20:05:08 +03:00
if ( frame - > fmt - > colplanes = = 1 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CITRGFMT_YCBCR422_1P ;
2010-08-03 16:50:29 +04:00
else
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CITRGFMT_YCBCR422 ;
2010-08-03 16:50:29 +04:00
break ;
default :
break ;
}
2012-05-02 13:14:49 +04:00
if ( ctx - > rotation = = 90 | | ctx - > rotation = = 270 )
cfg | = ( frame - > height < < 16 ) | frame - > width ;
else
cfg | = ( frame - > width < < 16 ) | frame - > height ;
2010-10-08 12:01:22 +04:00
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CITRGFMT ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CITAREA ) ;
cfg & = ~ FIMC_REG_CITAREA_MASK ;
2010-08-03 16:50:29 +04:00
cfg | = ( frame - > width * frame - > height ) ;
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CITAREA ) ;
2010-08-03 16:50:29 +04:00
}
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
2012-05-02 13:14:49 +04:00
cfg = ( frame - > f_height < < 16 ) | frame - > f_width ;
writel ( cfg , dev - > regs + FIMC_REG_ORGOSIZE ) ;
2010-10-07 17:06:16 +04:00
/* Select color space conversion equation (HD/SD size).*/
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIGCTRL ) ;
2010-10-07 17:06:16 +04:00
if ( frame - > f_width > = 1280 ) /* HD */
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_CSC_ITU601_709 ;
2010-10-07 17:06:16 +04:00
else /* SD */
2012-05-02 13:14:49 +04:00
cfg & = ~ FIMC_REG_CIGCTRL_CSC_ITU601_709 ;
writel ( cfg , dev - > regs + FIMC_REG_CIGCTRL ) ;
2010-10-07 17:06:16 +04:00
2010-08-03 16:50:29 +04:00
}
void fimc_hw_set_out_dma ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_frame * frame = & ctx - > d_frame ;
struct fimc_dma_offset * offset = & frame - > dma_offset ;
2011-12-01 21:02:24 +04:00
struct fimc_fmt * fmt = frame - > fmt ;
2012-05-02 13:14:49 +04:00
u32 cfg ;
2010-08-03 16:50:29 +04:00
/* Set the input dma offsets. */
2012-05-02 13:14:49 +04:00
cfg = ( offset - > y_v < < 16 ) | offset - > y_h ;
writel ( cfg , dev - > regs + FIMC_REG_CIOYOFF ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = ( offset - > cb_v < < 16 ) | offset - > cb_h ;
writel ( cfg , dev - > regs + FIMC_REG_CIOCBOFF ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = ( offset - > cr_v < < 16 ) | offset - > cr_h ;
writel ( cfg , dev - > regs + FIMC_REG_CIOCROFF ) ;
2010-08-03 16:50:29 +04:00
fimc_hw_set_out_dma_size ( ctx ) ;
/* Configure chroma components order. */
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIOCTRL ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg & = ~ ( FIMC_REG_CIOCTRL_ORDER2P_MASK |
FIMC_REG_CIOCTRL_ORDER422_MASK |
FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK |
FIMC_REG_CIOCTRL_RGB16FMT_MASK ) ;
2010-08-03 16:50:29 +04:00
2011-12-01 21:02:24 +04:00
if ( fmt - > colplanes = = 1 )
2010-08-03 16:50:29 +04:00
cfg | = ctx - > out_order_1p ;
2011-12-01 21:02:24 +04:00
else if ( fmt - > colplanes = = 2 )
2012-05-02 13:14:49 +04:00
cfg | = ctx - > out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE ;
2011-12-01 21:02:24 +04:00
else if ( fmt - > colplanes = = 3 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIOCTRL_YCBCR_3PLANE ;
2010-08-03 16:50:29 +04:00
2012-04-26 13:26:29 +04:00
if ( fmt - > color = = FIMC_FMT_RGB565 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIOCTRL_RGB565 ;
2012-04-26 13:26:29 +04:00
else if ( fmt - > color = = FIMC_FMT_RGB555 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIOCTRL_ARGB1555 ;
2012-04-26 13:26:29 +04:00
else if ( fmt - > color = = FIMC_FMT_RGB444 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIOCTRL_ARGB4444 ;
2011-12-01 21:02:24 +04:00
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CIOCTRL ) ;
2010-08-03 16:50:29 +04:00
}
static void fimc_hw_en_autoload ( struct fimc_dev * dev , int enable )
{
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( dev - > regs + FIMC_REG_ORGISIZE ) ;
2010-08-03 16:50:29 +04:00
if ( enable )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN ;
2010-08-03 16:50:29 +04:00
else
2012-05-02 13:14:49 +04:00
cfg & = ~ FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN ;
writel ( cfg , dev - > regs + FIMC_REG_ORGISIZE ) ;
2010-08-03 16:50:29 +04:00
}
void fimc_hw_en_lastirq ( struct fimc_dev * dev , int enable )
{
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( dev - > regs + FIMC_REG_CIOCTRL ) ;
2010-08-03 16:50:29 +04:00
if ( enable )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIOCTRL_LASTIRQ_ENABLE ;
2010-08-03 16:50:29 +04:00
else
2012-05-02 13:14:49 +04:00
cfg & = ~ FIMC_REG_CIOCTRL_LASTIRQ_ENABLE ;
writel ( cfg , dev - > regs + FIMC_REG_CIOCTRL ) ;
2010-08-03 16:50:29 +04:00
}
2010-12-28 17:27:13 +03:00
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 ) ;
2012-05-02 13:14:49 +04:00
cfg = shfactor < < 28 ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg | = ( sc - > pre_hratio < < 16 ) | sc - > pre_vratio ;
writel ( cfg , dev - > regs + FIMC_REG_CISCPRERATIO ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = ( sc - > pre_dst_width < < 16 ) | sc - > pre_dst_height ;
writel ( cfg , dev - > regs + FIMC_REG_CISCPREDST ) ;
2010-08-03 16:50:29 +04:00
}
2010-12-28 17:27:13 +03:00
static void fimc_hw_set_scaler ( 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 ;
struct fimc_frame * src_frame = & ctx - > s_frame ;
struct fimc_frame * dst_frame = & ctx - > d_frame ;
2011-10-05 21:20:45 +04:00
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( dev - > regs + FIMC_REG_CISCCTRL ) ;
2011-10-05 21:20:45 +04:00
2012-05-02 13:14:49 +04:00
cfg & = ~ ( FIMC_REG_CISCCTRL_CSCR2Y_WIDE | FIMC_REG_CISCCTRL_CSCY2R_WIDE |
FIMC_REG_CISCCTRL_SCALEUP_H | FIMC_REG_CISCCTRL_SCALEUP_V |
FIMC_REG_CISCCTRL_SCALERBYPASS | FIMC_REG_CISCCTRL_ONE2ONE |
FIMC_REG_CISCCTRL_INRGB_FMT_MASK | FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK |
FIMC_REG_CISCCTRL_INTERLACE | FIMC_REG_CISCCTRL_RGB_EXT ) ;
2010-08-03 16:50:29 +04:00
if ( ! ( ctx - > flags & FIMC_COLOR_RANGE_NARROW ) )
2012-05-02 13:14:49 +04:00
cfg | = ( FIMC_REG_CISCCTRL_CSCR2Y_WIDE |
FIMC_REG_CISCCTRL_CSCY2R_WIDE ) ;
2010-08-03 16:50:29 +04:00
if ( ! sc - > enabled )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_SCALERBYPASS ;
2010-08-03 16:50:29 +04:00
if ( sc - > scaleup_h )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_SCALEUP_H ;
2010-08-03 16:50:29 +04:00
if ( sc - > scaleup_v )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_SCALEUP_V ;
2010-08-03 16:50:29 +04:00
if ( sc - > copy_mode )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_ONE2ONE ;
2010-08-03 16:50:29 +04:00
2012-04-26 13:26:29 +04:00
if ( ctx - > in_path = = FIMC_IO_DMA ) {
2011-12-01 21:02:24 +04:00
switch ( src_frame - > fmt - > color ) {
2012-04-26 13:26:29 +04:00
case FIMC_FMT_RGB565 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_INRGB_FMT_RGB565 ;
2011-12-01 21:02:24 +04:00
break ;
2012-04-26 13:26:29 +04:00
case FIMC_FMT_RGB666 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_INRGB_FMT_RGB666 ;
2011-12-01 21:02:24 +04:00
break ;
2012-04-26 13:26:29 +04:00
case FIMC_FMT_RGB888 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_INRGB_FMT_RGB888 ;
2011-12-01 21:02:24 +04:00
break ;
}
2010-08-03 16:50:29 +04:00
}
2012-04-26 13:26:29 +04:00
if ( ctx - > out_path = = FIMC_IO_DMA ) {
2011-12-01 21:02:24 +04:00
u32 color = dst_frame - > fmt - > color ;
2012-04-26 13:26:29 +04:00
if ( color > = FIMC_FMT_RGB444 & & color < = FIMC_FMT_RGB565 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565 ;
2012-04-26 13:26:29 +04:00
else if ( color = = FIMC_FMT_RGB666 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666 ;
2012-04-26 13:26:29 +04:00
else if ( color = = FIMC_FMT_RGB888 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888 ;
2010-08-03 16:50:29 +04:00
} else {
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888 ;
2010-08-03 16:50:29 +04:00
if ( ctx - > flags & FIMC_SCAN_MODE_INTERLACED )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_INTERLACE ;
2010-08-03 16:50:29 +04:00
}
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CISCCTRL ) ;
2010-12-28 17:27:13 +03:00
}
void fimc_hw_set_mainscaler ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
2012-08-02 17:27:46 +04:00
const struct fimc_variant * variant = dev - > variant ;
2010-12-28 17:27:13 +03:00
struct fimc_scaler * sc = & ctx - > scaler ;
u32 cfg ;
dbg ( " main_hratio= 0x%X main_vratio= 0x%X " ,
2012-05-02 13:14:49 +04:00
sc - > main_hratio , sc - > main_vratio ) ;
2010-12-28 17:27:13 +03:00
fimc_hw_set_scaler ( ctx ) ;
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CISCCTRL ) ;
cfg & = ~ ( FIMC_REG_CISCCTRL_MHRATIO_MASK |
FIMC_REG_CISCCTRL_MVRATIO_MASK ) ;
2010-12-28 17:27:13 +03:00
2010-12-28 17:37:55 +03:00
if ( variant - > has_mainscaler_ext ) {
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_MHRATIO_EXT ( sc - > main_hratio ) ;
cfg | = FIMC_REG_CISCCTRL_MVRATIO_EXT ( sc - > main_vratio ) ;
writel ( cfg , dev - > regs + FIMC_REG_CISCCTRL ) ;
2010-12-28 17:27:13 +03:00
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIEXTEN ) ;
2010-12-28 17:27:13 +03:00
2012-05-02 13:14:49 +04:00
cfg & = ~ ( FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK |
FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK ) ;
cfg | = FIMC_REG_CIEXTEN_MHRATIO_EXT ( sc - > main_hratio ) ;
cfg | = FIMC_REG_CIEXTEN_MVRATIO_EXT ( sc - > main_vratio ) ;
writel ( cfg , dev - > regs + FIMC_REG_CIEXTEN ) ;
2010-12-28 17:37:55 +03:00
} else {
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_MHRATIO ( sc - > main_hratio ) ;
cfg | = FIMC_REG_CISCCTRL_MVRATIO ( sc - > main_vratio ) ;
writel ( cfg , dev - > regs + FIMC_REG_CISCCTRL ) ;
2010-12-28 17:37:55 +03:00
}
2010-08-03 16:50:29 +04:00
}
2012-11-22 21:01:39 +04:00
void fimc_hw_enable_capture ( struct fimc_ctx * ctx )
2010-08-03 16:50:29 +04:00
{
struct fimc_dev * dev = ctx - > fimc_dev ;
2012-11-22 21:01:39 +04:00
u32 cfg ;
2010-08-03 16:50:29 +04:00
2012-11-22 21:01:39 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIIMGCPT ) ;
cfg | = FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE ;
2010-08-03 16:50:29 +04:00
if ( ctx - > scaler . enabled )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIIMGCPT_IMGCPTEN_SC ;
2012-11-22 21:01:39 +04:00
else
cfg & = FIMC_REG_CIIMGCPT_IMGCPTEN_SC ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIIMGCPT_IMGCPTEN ;
writel ( cfg , dev - > regs + FIMC_REG_CIIMGCPT ) ;
2010-08-03 16:50:29 +04:00
}
2012-11-22 21:01:39 +04:00
void fimc_hw_disable_capture ( struct fimc_dev * dev )
{
u32 cfg = readl ( dev - > regs + FIMC_REG_CIIMGCPT ) ;
cfg & = ~ ( FIMC_REG_CIIMGCPT_IMGCPTEN |
FIMC_REG_CIIMGCPT_IMGCPTEN_SC ) ;
writel ( cfg , dev - > regs + FIMC_REG_CIIMGCPT ) ;
}
2012-04-02 13:41:22 +04:00
void fimc_hw_set_effect ( struct fimc_ctx * ctx )
2010-08-03 16:50:29 +04:00
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_effect * effect = & ctx - > effect ;
2011-08-26 21:57:06 +04:00
u32 cfg = 0 ;
2010-08-03 16:50:29 +04:00
2012-04-02 13:41:22 +04:00
if ( effect - > type ! = FIMC_REG_CIIMGEFF_FIN_BYPASS ) {
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIIMGEFF_IE_SC_AFTER |
FIMC_REG_CIIMGEFF_IE_ENABLE ;
2011-08-26 21:57:06 +04:00
cfg | = effect - > type ;
2012-05-02 13:14:49 +04:00
if ( effect - > type = = FIMC_REG_CIIMGEFF_FIN_ARBITRARY )
cfg | = ( effect - > pat_cb < < 13 ) | effect - > pat_cr ;
2010-08-03 16:50:29 +04:00
}
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CIIMGEFF ) ;
2010-08-03 16:50:29 +04:00
}
2011-12-01 21:02:24 +04:00
void fimc_hw_set_rgb_alpha ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
struct fimc_frame * frame = & ctx - > d_frame ;
u32 cfg ;
if ( ! ( frame - > fmt - > flags & FMT_HAS_ALPHA ) )
return ;
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIOCTRL ) ;
cfg & = ~ FIMC_REG_CIOCTRL_ALPHA_OUT_MASK ;
2011-12-01 21:02:24 +04:00
cfg | = ( frame - > alpha < < 4 ) ;
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CIOCTRL ) ;
2011-12-01 21:02:24 +04:00
}
2010-08-03 16:50:29 +04:00
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 ;
2012-04-26 13:26:29 +04:00
if ( FIMC_IO_LCDFIFO = = ctx - > out_path )
2012-05-02 13:14:49 +04:00
cfg_r | = FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg_o | = ( frame - > f_height < < 16 ) | frame - > f_width ;
cfg_r | = ( frame - > height < < 16 ) | frame - > width ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
writel ( cfg_o , dev - > regs + FIMC_REG_ORGISIZE ) ;
writel ( cfg_r , dev - > regs + FIMC_REG_CIREAL_ISIZE ) ;
2010-08-03 16:50:29 +04:00
}
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. */
2012-05-02 13:14:49 +04:00
cfg = ( offset - > y_v < < 16 ) | offset - > y_h ;
writel ( cfg , dev - > regs + FIMC_REG_CIIYOFF ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = ( offset - > cb_v < < 16 ) | offset - > cb_h ;
writel ( cfg , dev - > regs + FIMC_REG_CIICBOFF ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg = ( offset - > cr_v < < 16 ) | offset - > cr_h ;
writel ( cfg , dev - > regs + FIMC_REG_CIICROFF ) ;
2010-08-03 16:50:29 +04:00
/* 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. */
2012-04-26 13:26:29 +04:00
fimc_hw_en_autoload ( dev , ctx - > out_path = = FIMC_IO_LCDFIFO ) ;
2010-08-03 16:50:29 +04:00
/* Set the input DMA to process single frame only. */
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_MSCTRL ) ;
cfg & = ~ ( FIMC_REG_MSCTRL_INFORMAT_MASK
| FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK
| FIMC_REG_MSCTRL_INPUT_MASK
| FIMC_REG_MSCTRL_C_INT_IN_MASK
2013-03-21 21:22:34 +04:00
| FIMC_REG_MSCTRL_2P_IN_ORDER_MASK
| FIMC_REG_MSCTRL_ORDER422_MASK ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg | = ( FIMC_REG_MSCTRL_IN_BURST_COUNT ( 4 )
| FIMC_REG_MSCTRL_INPUT_MEMORY
| FIMC_REG_MSCTRL_FIFO_CTRL_FULL ) ;
2010-08-03 16:50:29 +04:00
switch ( frame - > fmt - > color ) {
2012-04-26 13:26:29 +04:00
case FIMC_FMT_RGB565 . . . FIMC_FMT_RGB888 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_MSCTRL_INFORMAT_RGB ;
2010-08-03 16:50:29 +04:00
break ;
2012-04-26 13:26:29 +04:00
case FIMC_FMT_YCBCR420 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_MSCTRL_INFORMAT_YCBCR420 ;
2010-08-03 16:50:29 +04:00
2010-12-08 20:05:08 +03:00
if ( frame - > fmt - > colplanes = = 2 )
2012-05-02 13:14:49 +04:00
cfg | = ctx - > in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE ;
2010-08-03 16:50:29 +04:00
else
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_MSCTRL_C_INT_IN_3PLANE ;
2010-08-03 16:50:29 +04:00
break ;
2012-04-26 13:26:29 +04:00
case FIMC_FMT_YCBYCR422 . . . FIMC_FMT_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
2012-05-02 13:14:49 +04:00
| FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P ;
2010-08-03 16:50:29 +04:00
} else {
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_MSCTRL_INFORMAT_YCBCR422 ;
2010-08-03 16:50:29 +04:00
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
2012-05-02 13:14:49 +04:00
| FIMC_REG_MSCTRL_C_INT_IN_2PLANE ;
2010-08-03 16:50:29 +04:00
else
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_MSCTRL_C_INT_IN_3PLANE ;
2010-08-03 16:50:29 +04:00
}
break ;
default :
break ;
}
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_MSCTRL ) ;
2010-08-03 16:50:29 +04:00
/* Input/output DMA linear/tiled mode. */
2012-05-02 13:14:49 +04:00
cfg = readl ( dev - > regs + FIMC_REG_CIDMAPARAM ) ;
cfg & = ~ FIMC_REG_CIDMAPARAM_TILE_MASK ;
2010-08-03 16:50:29 +04:00
if ( tiled_fmt ( ctx - > s_frame . fmt ) )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIDMAPARAM_R_64X32 ;
2010-08-03 16:50:29 +04:00
if ( tiled_fmt ( ctx - > d_frame . fmt ) )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIDMAPARAM_W_64X32 ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_CIDMAPARAM ) ;
2010-08-03 16:50:29 +04:00
}
void fimc_hw_set_input_path ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( dev - > regs + FIMC_REG_MSCTRL ) ;
cfg & = ~ FIMC_REG_MSCTRL_INPUT_MASK ;
2010-08-03 16:50:29 +04:00
2012-04-26 13:26:29 +04:00
if ( ctx - > in_path = = FIMC_IO_DMA )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_MSCTRL_INPUT_MEMORY ;
2010-08-03 16:50:29 +04:00
else
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_MSCTRL_INPUT_EXTCAM ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
writel ( cfg , dev - > regs + FIMC_REG_MSCTRL ) ;
2010-08-03 16:50:29 +04:00
}
void fimc_hw_set_output_path ( struct fimc_ctx * ctx )
{
struct fimc_dev * dev = ctx - > fimc_dev ;
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( dev - > regs + FIMC_REG_CISCCTRL ) ;
cfg & = ~ FIMC_REG_CISCCTRL_LCDPATHEN_FIFO ;
2012-04-26 13:26:29 +04:00
if ( ctx - > out_path = = FIMC_IO_LCDFIFO )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISCCTRL_LCDPATHEN_FIFO ;
writel ( cfg , dev - > regs + FIMC_REG_CISCCTRL ) ;
2010-08-03 16:50:29 +04:00
}
void fimc_hw_set_input_addr ( struct fimc_dev * dev , struct fimc_addr * paddr )
{
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( dev - > regs + FIMC_REG_CIREAL_ISIZE ) ;
cfg | = FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS ;
writel ( cfg , dev - > regs + FIMC_REG_CIREAL_ISIZE ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
writel ( paddr - > y , dev - > regs + FIMC_REG_CIIYSA ( 0 ) ) ;
writel ( paddr - > cb , dev - > regs + FIMC_REG_CIICBSA ( 0 ) ) ;
writel ( paddr - > cr , dev - > regs + FIMC_REG_CIICRSA ( 0 ) ) ;
2010-08-03 16:50:29 +04:00
2012-05-02 13:14:49 +04:00
cfg & = ~ FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS ;
writel ( cfg , dev - > regs + FIMC_REG_CIREAL_ISIZE ) ;
2010-08-03 16:50:29 +04:00
}
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 {
2012-05-02 13:14:49 +04:00
writel ( paddr - > y , dev - > regs + FIMC_REG_CIOYSA ( i ) ) ;
writel ( paddr - > cb , dev - > regs + FIMC_REG_CIOCBSA ( i ) ) ;
writel ( paddr - > cr , dev - > regs + FIMC_REG_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 ,
2013-02-01 22:00:40 +04:00
struct fimc_source_info * cam )
2010-10-07 17:06:16 +04:00
{
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( fimc - > regs + FIMC_REG_CIGCTRL ) ;
2010-10-07 17:06:16 +04:00
2012-05-02 13:14:49 +04:00
cfg & = ~ ( FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC |
FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC |
FIMC_REG_CIGCTRL_INVPOLFIELD ) ;
2010-10-07 17:06:16 +04:00
2011-09-19 19:38:35 +04:00
if ( cam - > flags & V4L2_MBUS_PCLK_SAMPLE_FALLING )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_INVPOLPCLK ;
2010-10-07 17:06:16 +04:00
2011-09-19 19:38:35 +04:00
if ( cam - > flags & V4L2_MBUS_VSYNC_ACTIVE_LOW )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_INVPOLVSYNC ;
2010-10-07 17:06:16 +04:00
2011-09-19 19:38:35 +04:00
if ( cam - > flags & V4L2_MBUS_HSYNC_ACTIVE_LOW )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_INVPOLHREF ;
2010-10-07 17:06:16 +04:00
2011-09-19 19:38:35 +04:00
if ( cam - > flags & V4L2_MBUS_HSYNC_ACTIVE_LOW )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_INVPOLHSYNC ;
2010-10-07 17:06:16 +04:00
2011-09-19 19:38:35 +04:00
if ( cam - > flags & V4L2_MBUS_FIELD_EVEN_LOW )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_INVPOLFIELD ;
2011-09-19 19:38:35 +04:00
2012-05-02 13:14:49 +04:00
writel ( cfg , fimc - > regs + FIMC_REG_CIGCTRL ) ;
2010-10-07 17:06:16 +04:00
return 0 ;
}
2012-05-02 13:14:49 +04:00
struct mbus_pixfmt_desc {
u32 pixelcode ;
u32 cisrcfmt ;
u16 bus_width ;
} ;
static const struct mbus_pixfmt_desc pix_desc [ ] = {
2014-11-10 20:28:31 +03:00
{ MEDIA_BUS_FMT_YUYV8_2X8 , FIMC_REG_CISRCFMT_ORDER422_YCBYCR , 8 } ,
{ MEDIA_BUS_FMT_YVYU8_2X8 , FIMC_REG_CISRCFMT_ORDER422_YCRYCB , 8 } ,
{ MEDIA_BUS_FMT_VYUY8_2X8 , FIMC_REG_CISRCFMT_ORDER422_CRYCBY , 8 } ,
{ MEDIA_BUS_FMT_UYVY8_2X8 , FIMC_REG_CISRCFMT_ORDER422_CBYCRY , 8 } ,
2012-05-02 13:14:49 +04:00
} ;
2010-10-07 17:06:16 +04:00
int fimc_hw_set_camera_source ( struct fimc_dev * fimc ,
2013-02-01 22:00:40 +04:00
struct fimc_source_info * source )
2010-10-07 17:06:16 +04:00
{
2013-03-20 17:44:39 +04:00
struct fimc_vid_cap * vc = & fimc - > vid_cap ;
struct fimc_frame * f = & vc - > ctx - > s_frame ;
2013-02-01 22:00:40 +04:00
u32 bus_width , cfg = 0 ;
2010-12-27 21:02:16 +03:00
int i ;
2013-02-01 22:00:40 +04:00
switch ( source - > fimc_bus_type ) {
case FIMC_BUS_TYPE_ITU_601 :
case FIMC_BUS_TYPE_ITU_656 :
2020-07-31 02:01:08 +03:00
if ( fimc_fmt_is_user_defined ( f - > fmt - > color ) ) {
cfg | = FIMC_REG_CISRCFMT_ITU601_8BIT ;
break ;
}
2010-12-27 21:02:16 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( pix_desc ) ; i + + ) {
2013-03-20 17:44:39 +04:00
if ( vc - > ci_fmt . code = = pix_desc [ i ] . pixelcode ) {
2010-12-27 21:02:16 +03:00
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 ) ) {
2013-05-31 18:37:18 +04:00
v4l2_err ( & vc - > ve . vdev ,
2010-12-27 21:02:16 +03:00
" Camera color format not supported: %d \n " ,
2013-03-20 17:44:39 +04:00
vc - > ci_fmt . code ) ;
2010-10-07 17:06:16 +04:00
return - EINVAL ;
}
2013-02-01 22:00:40 +04:00
if ( source - > fimc_bus_type = = FIMC_BUS_TYPE_ITU_601 ) {
2010-12-27 21:02:16 +03:00
if ( bus_width = = 8 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISRCFMT_ITU601_8BIT ;
2010-12-27 21:02:16 +03:00
else if ( bus_width = = 16 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISRCFMT_ITU601_16BIT ;
2010-10-07 17:06:16 +04:00
} /* else defaults to ITU-R BT.656 8-bit */
2013-02-01 22:00:40 +04:00
break ;
case FIMC_BUS_TYPE_MIPI_CSI2 :
2012-09-24 18:08:45 +04:00
if ( fimc_fmt_is_user_defined ( f - > fmt - > color ) )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CISRCFMT_ITU601_8BIT ;
2013-02-01 22:00:40 +04:00
break ;
2013-03-20 17:44:39 +04:00
default :
case FIMC_BUS_TYPE_ISP_WRITEBACK :
/* Anything to do here ? */
break ;
2010-10-07 17:06:16 +04:00
}
2012-05-02 13:14:49 +04:00
cfg | = ( f - > o_width < < 16 ) | f - > o_height ;
writel ( cfg , fimc - > regs + FIMC_REG_CISRCFMT ) ;
2010-10-07 17:06:16 +04:00
return 0 ;
}
2012-05-02 13:14:49 +04:00
void fimc_hw_set_camera_offset ( struct fimc_dev * fimc , struct fimc_frame * f )
2010-10-07 17:06:16 +04:00
{
u32 hoff2 , voff2 ;
2012-05-02 13:14:49 +04:00
u32 cfg = readl ( fimc - > regs + FIMC_REG_CIWDOFST ) ;
2010-10-07 17:06:16 +04:00
2012-05-02 13:14:49 +04:00
cfg & = ~ ( FIMC_REG_CIWDOFST_HOROFF_MASK | FIMC_REG_CIWDOFST_VEROFF_MASK ) ;
cfg | = FIMC_REG_CIWDOFST_OFF_EN |
( f - > offs_h < < 16 ) | f - > offs_v ;
2010-10-07 17:06:16 +04:00
2012-05-02 13:14:49 +04:00
writel ( cfg , fimc - > regs + FIMC_REG_CIWDOFST ) ;
2010-10-07 17:06:16 +04:00
/* 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 ;
2012-05-02 13:14:49 +04:00
cfg = ( hoff2 < < 16 ) | voff2 ;
writel ( cfg , fimc - > regs + FIMC_REG_CIWDOFST2 ) ;
2010-10-07 17:06:16 +04:00
}
int fimc_hw_set_camera_type ( struct fimc_dev * fimc ,
2013-02-01 22:00:40 +04:00
struct fimc_source_info * source )
2010-10-07 17:06:16 +04:00
{
struct fimc_vid_cap * vid_cap = & fimc - > vid_cap ;
2012-03-21 13:21:30 +04:00
u32 csis_data_alignment = 32 ;
2013-03-20 17:44:39 +04:00
u32 cfg , tmp ;
2010-10-07 17:06:16 +04:00
2012-05-02 13:14:49 +04:00
cfg = readl ( fimc - > regs + FIMC_REG_CIGCTRL ) ;
2010-10-07 17:06:16 +04:00
/* Select ITU B interface, disable Writeback path and test pattern. */
2012-05-02 13:14:49 +04:00
cfg & = ~ ( FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A |
FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB |
2013-03-20 17:44:39 +04:00
FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG |
FIMC_REG_CIGCTRL_SELWB_A ) ;
2010-10-07 17:06:16 +04:00
2013-02-01 22:00:40 +04:00
switch ( source - > fimc_bus_type ) {
case FIMC_BUS_TYPE_MIPI_CSI2 :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_SELCAM_MIPI ;
2010-10-07 17:06:16 +04:00
2013-02-01 22:00:40 +04:00
if ( source - > mux_id = = 0 )
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_SELCAM_MIPI_A ;
2010-10-07 17:06:16 +04:00
/* TODO: add remaining supported formats. */
2013-03-20 17:44:39 +04:00
switch ( vid_cap - > ci_fmt . code ) {
2014-11-10 20:28:31 +03:00
case MEDIA_BUS_FMT_VYUY8_2X8 :
2012-05-02 13:14:49 +04:00
tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT ;
2011-08-26 21:57:06 +04:00
break ;
2014-11-10 20:28:31 +03:00
case MEDIA_BUS_FMT_JPEG_1X8 :
case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8 :
2012-05-02 13:14:49 +04:00
tmp = FIMC_REG_CSIIMGFMT_USER ( 1 ) ;
cfg | = FIMC_REG_CIGCTRL_CAM_JPEG ;
2011-08-26 21:57:06 +04:00
break ;
default :
2013-05-31 18:37:18 +04:00
v4l2_err ( & vid_cap - > ve . vdev ,
2012-06-12 10:12:26 +04:00
" Not supported camera pixel format: %#x \n " ,
2013-03-20 17:44:39 +04:00
vid_cap - > ci_fmt . code ) ;
2010-10-07 17:06:16 +04:00
return - EINVAL ;
}
2012-03-21 13:21:30 +04:00
tmp | = ( csis_data_alignment = = 32 ) < < 8 ;
2011-02-21 18:09:01 +03:00
2012-05-02 13:14:49 +04:00
writel ( tmp , fimc - > regs + FIMC_REG_CSIIMGFMT ) ;
2012-07-24 19:06:26 +04:00
break ;
2013-02-01 22:00:40 +04:00
case FIMC_BUS_TYPE_ITU_601 . . . FIMC_BUS_TYPE_ITU_656 :
if ( source - > mux_id = = 0 ) /* ITU-A, ITU-B: 0, 1 */
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_SELCAM_ITU_A ;
2020-07-31 02:01:08 +03:00
if ( vid_cap - > ci_fmt . code = = MEDIA_BUS_FMT_JPEG_1X8 )
cfg | = FIMC_REG_CIGCTRL_CAM_JPEG ;
2012-07-24 19:06:26 +04:00
break ;
2013-02-01 22:00:40 +04:00
case FIMC_BUS_TYPE_LCD_WRITEBACK_A :
2012-05-02 13:14:49 +04:00
cfg | = FIMC_REG_CIGCTRL_CAMIF_SELWB ;
2020-07-25 01:10:14 +03:00
fallthrough ;
2013-03-20 17:44:39 +04:00
case FIMC_BUS_TYPE_ISP_WRITEBACK :
if ( fimc - > variant - > has_isp_wb )
cfg | = FIMC_REG_CIGCTRL_CAMIF_SELWB ;
else
WARN_ONCE ( 1 , " ISP Writeback input is not supported \n " ) ;
2012-07-24 19:06:26 +04:00
break ;
default :
2013-05-31 18:37:18 +04:00
v4l2_err ( & vid_cap - > ve . vdev ,
" Invalid FIMC bus type selected: %d \n " ,
2013-02-01 22:00:40 +04:00
source - > fimc_bus_type ) ;
2010-10-07 17:06:16 +04:00
return - EINVAL ;
}
2012-05-02 13:14:49 +04:00
writel ( cfg , fimc - > regs + FIMC_REG_CIGCTRL ) ;
2010-10-07 17:06:16 +04:00
return 0 ;
}
2012-05-02 13:14:49 +04:00
void fimc_hw_clear_irq ( struct fimc_dev * dev )
{
u32 cfg = readl ( dev - > regs + FIMC_REG_CIGCTRL ) ;
cfg | = FIMC_REG_CIGCTRL_IRQ_CLR ;
writel ( cfg , dev - > regs + FIMC_REG_CIGCTRL ) ;
}
void fimc_hw_enable_scaler ( struct fimc_dev * dev , bool on )
{
u32 cfg = readl ( dev - > regs + FIMC_REG_CISCCTRL ) ;
if ( on )
cfg | = FIMC_REG_CISCCTRL_SCALERSTART ;
else
cfg & = ~ FIMC_REG_CISCCTRL_SCALERSTART ;
writel ( cfg , dev - > regs + FIMC_REG_CISCCTRL ) ;
}
void fimc_hw_activate_input_dma ( struct fimc_dev * dev , bool on )
{
u32 cfg = readl ( dev - > regs + FIMC_REG_MSCTRL ) ;
if ( on )
cfg | = FIMC_REG_MSCTRL_ENVID ;
else
cfg & = ~ FIMC_REG_MSCTRL_ENVID ;
writel ( cfg , dev - > regs + FIMC_REG_MSCTRL ) ;
}
/* Return an index to the buffer actually being written. */
2012-09-24 18:08:45 +04:00
s32 fimc_hw_get_frame_index ( struct fimc_dev * dev )
2012-05-02 13:14:49 +04:00
{
2012-09-24 18:08:45 +04:00
s32 reg ;
2012-05-02 13:14:49 +04:00
2013-03-26 15:22:21 +04:00
if ( dev - > drv_data - > cistatus2 ) {
2012-09-24 18:08:45 +04:00
reg = readl ( dev - > regs + FIMC_REG_CISTATUS2 ) & 0x3f ;
return reg - 1 ;
2012-05-02 13:14:49 +04:00
}
reg = readl ( dev - > regs + FIMC_REG_CISTATUS ) ;
return ( reg & FIMC_REG_CISTATUS_FRAMECNT_MASK ) > >
FIMC_REG_CISTATUS_FRAMECNT_SHIFT ;
}
2012-09-24 18:08:45 +04:00
/* Return an index to the buffer being written previously. */
s32 fimc_hw_get_prev_frame_index ( struct fimc_dev * dev )
{
s32 reg ;
2013-03-26 15:22:21 +04:00
if ( ! dev - > drv_data - > cistatus2 )
2012-09-24 18:08:45 +04:00
return - 1 ;
reg = readl ( dev - > regs + FIMC_REG_CISTATUS2 ) ;
return ( ( reg > > 7 ) & 0x3f ) - 1 ;
}
2012-05-02 13:14:49 +04:00
/* Locking: the caller holds fimc->slock */
void fimc_activate_capture ( struct fimc_ctx * ctx )
{
fimc_hw_enable_scaler ( ctx - > fimc_dev , ctx - > scaler . enabled ) ;
2012-11-22 21:01:39 +04:00
fimc_hw_enable_capture ( ctx ) ;
2012-05-02 13:14:49 +04:00
}
void fimc_deactivate_capture ( struct fimc_dev * fimc )
{
fimc_hw_en_lastirq ( fimc , true ) ;
2012-11-22 21:01:39 +04:00
fimc_hw_disable_capture ( fimc ) ;
2012-05-02 13:14:49 +04:00
fimc_hw_enable_scaler ( fimc , false ) ;
fimc_hw_en_lastirq ( fimc , false ) ;
}
2013-03-20 17:44:39 +04:00
int fimc_hw_camblk_cfg_writeback ( struct fimc_dev * fimc )
{
struct regmap * map = fimc - > sysreg ;
unsigned int mask , val , camblk_cfg ;
int ret ;
2013-04-01 03:31:02 +04:00
if ( map = = NULL )
return 0 ;
2013-03-20 17:44:39 +04:00
ret = regmap_read ( map , SYSREG_CAMBLK , & camblk_cfg ) ;
if ( ret < 0 | | ( ( camblk_cfg & 0x00700000 ) > > 20 ! = 0x3 ) )
return ret ;
if ( ! WARN ( fimc - > id > = 3 , " not supported id: %d \n " , fimc - > id ) )
val = 0x1 < < ( fimc - > id + 20 ) ;
else
val = 0 ;
mask = SYSREG_CAMBLK_FIFORST_ISP | SYSREG_CAMBLK_ISPWB_FULL_EN ;
ret = regmap_update_bits ( map , SYSREG_CAMBLK , mask , val ) ;
if ( ret < 0 )
return ret ;
usleep_range ( 1000 , 2000 ) ;
val | = SYSREG_CAMBLK_FIFORST_ISP ;
ret = regmap_update_bits ( map , SYSREG_CAMBLK , mask , val ) ;
if ( ret < 0 )
return ret ;
mask = SYSREG_ISPBLK_FIFORST_CAM_BLK ;
ret = regmap_update_bits ( map , SYSREG_ISPBLK , mask , ~ mask ) ;
if ( ret < 0 )
return ret ;
usleep_range ( 1000 , 2000 ) ;
return regmap_update_bits ( map , SYSREG_ISPBLK , mask , mask ) ;
}