2014-07-11 12:19:42 -03:00
/* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h
*
* Copyright ( c ) 2014 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com
*
* Author : Jacek Anaszewski < j . anaszewski @ 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/videodev2.h>
# include <linux/delay.h>
# include "jpeg-core.h"
# include "jpeg-regs.h"
# include "jpeg-hw-exynos3250.h"
void exynos3250_jpeg_reset ( void __iomem * regs )
{
2015-02-25 08:53:49 -03:00
u32 reg = 1 ;
2014-07-11 12:19:42 -03:00
int count = 1000 ;
writel ( 1 , regs + EXYNOS3250_SW_RESET ) ;
/* no other way but polling for when JPEG IP becomes operational */
while ( reg ! = 0 & & - - count > 0 ) {
udelay ( 1 ) ;
cpu_relax ( ) ;
reg = readl ( regs + EXYNOS3250_SW_RESET ) ;
}
reg = 0 ;
count = 1000 ;
while ( reg ! = 1 & & - - count > 0 ) {
writel ( 1 , regs + EXYNOS3250_JPGDRI ) ;
udelay ( 1 ) ;
cpu_relax ( ) ;
reg = readl ( regs + EXYNOS3250_JPGDRI ) ;
}
writel ( 0 , regs + EXYNOS3250_JPGDRI ) ;
}
void exynos3250_jpeg_poweron ( void __iomem * regs )
{
writel ( EXYNOS3250_POWER_ON , regs + EXYNOS3250_JPGCLKCON ) ;
}
void exynos3250_jpeg_set_dma_num ( void __iomem * regs )
{
writel ( ( ( EXYNOS3250_DMA_MO_COUNT < < EXYNOS3250_WDMA_ISSUE_NUM_SHIFT ) &
EXYNOS3250_WDMA_ISSUE_NUM_MASK ) |
( ( EXYNOS3250_DMA_MO_COUNT < < EXYNOS3250_RDMA_ISSUE_NUM_SHIFT ) &
EXYNOS3250_RDMA_ISSUE_NUM_MASK ) |
( ( EXYNOS3250_DMA_MO_COUNT < < EXYNOS3250_ISSUE_GATHER_NUM_SHIFT ) &
EXYNOS3250_ISSUE_GATHER_NUM_MASK ) ,
regs + EXYNOS3250_DMA_ISSUE_NUM ) ;
}
void exynos3250_jpeg_clk_set ( void __iomem * base )
{
u32 reg ;
reg = readl ( base + EXYNOS3250_JPGCMOD ) & ~ EXYNOS3250_HALF_EN_MASK ;
writel ( reg | EXYNOS3250_HALF_EN , base + EXYNOS3250_JPGCMOD ) ;
}
void exynos3250_jpeg_input_raw_fmt ( void __iomem * regs , unsigned int fmt )
{
u32 reg ;
reg = readl ( regs + EXYNOS3250_JPGCMOD ) &
EXYNOS3250_MODE_Y16_MASK ;
switch ( fmt ) {
case V4L2_PIX_FMT_RGB32 :
reg | = EXYNOS3250_MODE_SEL_ARGB8888 ;
break ;
case V4L2_PIX_FMT_BGR32 :
reg | = EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB ;
break ;
case V4L2_PIX_FMT_RGB565 :
reg | = EXYNOS3250_MODE_SEL_RGB565 ;
break ;
case V4L2_PIX_FMT_RGB565X :
reg | = EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB ;
break ;
case V4L2_PIX_FMT_YUYV :
reg | = EXYNOS3250_MODE_SEL_422_1P_LUM_CHR ;
break ;
case V4L2_PIX_FMT_YVYU :
reg | = EXYNOS3250_MODE_SEL_422_1P_LUM_CHR |
EXYNOS3250_SRC_SWAP_UV ;
break ;
case V4L2_PIX_FMT_UYVY :
reg | = EXYNOS3250_MODE_SEL_422_1P_CHR_LUM ;
break ;
case V4L2_PIX_FMT_VYUY :
reg | = EXYNOS3250_MODE_SEL_422_1P_CHR_LUM |
EXYNOS3250_SRC_SWAP_UV ;
break ;
case V4L2_PIX_FMT_NV12 :
reg | = EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12 ;
break ;
case V4L2_PIX_FMT_NV21 :
reg | = EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21 ;
break ;
case V4L2_PIX_FMT_YUV420 :
reg | = EXYNOS3250_MODE_SEL_420_3P ;
break ;
default :
break ;
}
writel ( reg , regs + EXYNOS3250_JPGCMOD ) ;
}
void exynos3250_jpeg_set_y16 ( void __iomem * regs , bool y16 )
{
u32 reg ;
reg = readl ( regs + EXYNOS3250_JPGCMOD ) ;
if ( y16 )
reg | = EXYNOS3250_MODE_Y16 ;
else
reg & = ~ EXYNOS3250_MODE_Y16_MASK ;
writel ( reg , regs + EXYNOS3250_JPGCMOD ) ;
}
void exynos3250_jpeg_proc_mode ( void __iomem * regs , unsigned int mode )
{
u32 reg , m ;
if ( mode = = S5P_JPEG_ENCODE )
m = EXYNOS3250_PROC_MODE_COMPR ;
else
m = EXYNOS3250_PROC_MODE_DECOMPR ;
reg = readl ( regs + EXYNOS3250_JPGMOD ) ;
reg & = ~ EXYNOS3250_PROC_MODE_MASK ;
reg | = m ;
writel ( reg , regs + EXYNOS3250_JPGMOD ) ;
}
void exynos3250_jpeg_subsampling_mode ( void __iomem * regs , unsigned int mode )
{
u32 reg , m = 0 ;
switch ( mode ) {
case V4L2_JPEG_CHROMA_SUBSAMPLING_444 :
m = EXYNOS3250_SUBSAMPLING_MODE_444 ;
break ;
case V4L2_JPEG_CHROMA_SUBSAMPLING_422 :
m = EXYNOS3250_SUBSAMPLING_MODE_422 ;
break ;
case V4L2_JPEG_CHROMA_SUBSAMPLING_420 :
m = EXYNOS3250_SUBSAMPLING_MODE_420 ;
break ;
}
reg = readl ( regs + EXYNOS3250_JPGMOD ) ;
reg & = ~ EXYNOS3250_SUBSAMPLING_MODE_MASK ;
reg | = m ;
writel ( reg , regs + EXYNOS3250_JPGMOD ) ;
}
unsigned int exynos3250_jpeg_get_subsampling_mode ( void __iomem * regs )
{
return readl ( regs + EXYNOS3250_JPGMOD ) &
EXYNOS3250_SUBSAMPLING_MODE_MASK ;
}
void exynos3250_jpeg_dri ( void __iomem * regs , unsigned int dri )
{
u32 reg ;
reg = dri & EXYNOS3250_JPGDRI_MASK ;
writel ( reg , regs + EXYNOS3250_JPGDRI ) ;
}
void exynos3250_jpeg_qtbl ( void __iomem * regs , unsigned int t , unsigned int n )
{
unsigned long reg ;
reg = readl ( regs + EXYNOS3250_QHTBL ) ;
reg & = ~ EXYNOS3250_QT_NUM_MASK ( t ) ;
reg | = ( n < < EXYNOS3250_QT_NUM_SHIFT ( t ) ) &
EXYNOS3250_QT_NUM_MASK ( t ) ;
writel ( reg , regs + EXYNOS3250_QHTBL ) ;
}
void exynos3250_jpeg_htbl_ac ( void __iomem * regs , unsigned int t )
{
unsigned long reg ;
reg = readl ( regs + EXYNOS3250_QHTBL ) ;
reg & = ~ EXYNOS3250_HT_NUM_AC_MASK ( t ) ;
/* this driver uses table 0 for all color components */
reg | = ( 0 < < EXYNOS3250_HT_NUM_AC_SHIFT ( t ) ) &
EXYNOS3250_HT_NUM_AC_MASK ( t ) ;
writel ( reg , regs + EXYNOS3250_QHTBL ) ;
}
void exynos3250_jpeg_htbl_dc ( void __iomem * regs , unsigned int t )
{
unsigned long reg ;
reg = readl ( regs + EXYNOS3250_QHTBL ) ;
reg & = ~ EXYNOS3250_HT_NUM_DC_MASK ( t ) ;
/* this driver uses table 0 for all color components */
reg | = ( 0 < < EXYNOS3250_HT_NUM_DC_SHIFT ( t ) ) &
EXYNOS3250_HT_NUM_DC_MASK ( t ) ;
writel ( reg , regs + EXYNOS3250_QHTBL ) ;
}
void exynos3250_jpeg_set_y ( void __iomem * regs , unsigned int y )
{
u32 reg ;
reg = y & EXYNOS3250_JPGY_MASK ;
writel ( reg , regs + EXYNOS3250_JPGY ) ;
}
void exynos3250_jpeg_set_x ( void __iomem * regs , unsigned int x )
{
u32 reg ;
reg = x & EXYNOS3250_JPGX_MASK ;
writel ( reg , regs + EXYNOS3250_JPGX ) ;
}
2014-08-26 10:50:23 -03:00
#if 0 /* Currently unused */
2014-07-11 12:19:42 -03:00
unsigned int exynos3250_jpeg_get_y ( void __iomem * regs )
{
return readl ( regs + EXYNOS3250_JPGY ) ;
}
unsigned int exynos3250_jpeg_get_x ( void __iomem * regs )
{
return readl ( regs + EXYNOS3250_JPGX ) ;
}
2014-08-26 10:50:23 -03:00
# endif
2014-07-11 12:19:42 -03:00
void exynos3250_jpeg_interrupts_enable ( void __iomem * regs )
{
u32 reg ;
reg = readl ( regs + EXYNOS3250_JPGINTSE ) ;
reg | = ( EXYNOS3250_JPEG_DONE_EN |
EXYNOS3250_WDMA_DONE_EN |
EXYNOS3250_RDMA_DONE_EN |
EXYNOS3250_ENC_STREAM_INT_EN |
EXYNOS3250_CORE_DONE_EN |
EXYNOS3250_ERR_INT_EN |
EXYNOS3250_HEAD_INT_EN ) ;
writel ( reg , regs + EXYNOS3250_JPGINTSE ) ;
}
void exynos3250_jpeg_enc_stream_bound ( void __iomem * regs , unsigned int size )
{
u32 reg ;
reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK ;
writel ( reg , regs + EXYNOS3250_ENC_STREAM_BOUND ) ;
}
void exynos3250_jpeg_output_raw_fmt ( void __iomem * regs , unsigned int fmt )
{
u32 reg ;
switch ( fmt ) {
case V4L2_PIX_FMT_RGB32 :
reg = EXYNOS3250_OUT_FMT_ARGB8888 ;
break ;
case V4L2_PIX_FMT_BGR32 :
reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB ;
break ;
case V4L2_PIX_FMT_RGB565 :
reg = EXYNOS3250_OUT_FMT_RGB565 ;
break ;
case V4L2_PIX_FMT_RGB565X :
reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB ;
break ;
case V4L2_PIX_FMT_YUYV :
reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR ;
break ;
case V4L2_PIX_FMT_YVYU :
reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR |
EXYNOS3250_OUT_SWAP_UV ;
break ;
case V4L2_PIX_FMT_UYVY :
reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM ;
break ;
case V4L2_PIX_FMT_VYUY :
reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM |
EXYNOS3250_OUT_SWAP_UV ;
break ;
case V4L2_PIX_FMT_NV12 :
reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12 ;
break ;
case V4L2_PIX_FMT_NV21 :
reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21 ;
break ;
case V4L2_PIX_FMT_YUV420 :
reg = EXYNOS3250_OUT_FMT_420_3P ;
break ;
default :
reg = 0 ;
break ;
}
writel ( reg , regs + EXYNOS3250_OUTFORM ) ;
}
void exynos3250_jpeg_jpgadr ( void __iomem * regs , unsigned int addr )
{
writel ( addr , regs + EXYNOS3250_JPG_JPGADR ) ;
}
void exynos3250_jpeg_imgadr ( void __iomem * regs , struct s5p_jpeg_addr * img_addr )
{
writel ( img_addr - > y , regs + EXYNOS3250_LUMA_BASE ) ;
writel ( img_addr - > cb , regs + EXYNOS3250_CHROMA_BASE ) ;
writel ( img_addr - > cr , regs + EXYNOS3250_CHROMA_CR_BASE ) ;
}
void exynos3250_jpeg_stride ( void __iomem * regs , unsigned int img_fmt ,
unsigned int width )
{
u32 reg_luma = 0 , reg_cr = 0 , reg_cb = 0 ;
switch ( img_fmt ) {
case V4L2_PIX_FMT_RGB32 :
reg_luma = 4 * width ;
break ;
case V4L2_PIX_FMT_RGB565 :
case V4L2_PIX_FMT_RGB565X :
case V4L2_PIX_FMT_YUYV :
case V4L2_PIX_FMT_YVYU :
case V4L2_PIX_FMT_UYVY :
case V4L2_PIX_FMT_VYUY :
reg_luma = 2 * width ;
break ;
case V4L2_PIX_FMT_NV12 :
case V4L2_PIX_FMT_NV21 :
reg_luma = width ;
reg_cb = reg_luma ;
break ;
case V4L2_PIX_FMT_YUV420 :
reg_luma = width ;
reg_cb = reg_cr = reg_luma / 2 ;
break ;
default :
break ;
}
writel ( reg_luma , regs + EXYNOS3250_LUMA_STRIDE ) ;
writel ( reg_cb , regs + EXYNOS3250_CHROMA_STRIDE ) ;
writel ( reg_cr , regs + EXYNOS3250_CHROMA_CR_STRIDE ) ;
}
void exynos3250_jpeg_offset ( void __iomem * regs , unsigned int x_offset ,
unsigned int y_offset )
{
u32 reg ;
reg = ( y_offset < < EXYNOS3250_LUMA_YY_OFFSET_SHIFT ) &
EXYNOS3250_LUMA_YY_OFFSET_MASK ;
reg | = ( x_offset < < EXYNOS3250_LUMA_YX_OFFSET_SHIFT ) &
EXYNOS3250_LUMA_YX_OFFSET_MASK ;
writel ( reg , regs + EXYNOS3250_LUMA_XY_OFFSET ) ;
reg = ( y_offset < < EXYNOS3250_CHROMA_YY_OFFSET_SHIFT ) &
EXYNOS3250_CHROMA_YY_OFFSET_MASK ;
reg | = ( x_offset < < EXYNOS3250_CHROMA_YX_OFFSET_SHIFT ) &
EXYNOS3250_CHROMA_YX_OFFSET_MASK ;
writel ( reg , regs + EXYNOS3250_CHROMA_XY_OFFSET ) ;
reg = ( y_offset < < EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT ) &
EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK ;
reg | = ( x_offset < < EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT ) &
EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK ;
writel ( reg , regs + EXYNOS3250_CHROMA_CR_XY_OFFSET ) ;
}
void exynos3250_jpeg_coef ( void __iomem * base , unsigned int mode )
{
if ( mode = = S5P_JPEG_ENCODE ) {
writel ( EXYNOS3250_JPEG_ENC_COEF1 ,
base + EXYNOS3250_JPG_COEF ( 1 ) ) ;
writel ( EXYNOS3250_JPEG_ENC_COEF2 ,
base + EXYNOS3250_JPG_COEF ( 2 ) ) ;
writel ( EXYNOS3250_JPEG_ENC_COEF3 ,
base + EXYNOS3250_JPG_COEF ( 3 ) ) ;
} else {
writel ( EXYNOS3250_JPEG_DEC_COEF1 ,
base + EXYNOS3250_JPG_COEF ( 1 ) ) ;
writel ( EXYNOS3250_JPEG_DEC_COEF2 ,
base + EXYNOS3250_JPG_COEF ( 2 ) ) ;
writel ( EXYNOS3250_JPEG_DEC_COEF3 ,
base + EXYNOS3250_JPG_COEF ( 3 ) ) ;
}
}
void exynos3250_jpeg_start ( void __iomem * regs )
{
writel ( 1 , regs + EXYNOS3250_JSTART ) ;
}
void exynos3250_jpeg_rstart ( void __iomem * regs )
{
writel ( 1 , regs + EXYNOS3250_JRSTART ) ;
}
unsigned int exynos3250_jpeg_get_int_status ( void __iomem * regs )
{
return readl ( regs + EXYNOS3250_JPGINTST ) ;
}
void exynos3250_jpeg_clear_int_status ( void __iomem * regs ,
unsigned int value )
{
return writel ( value , regs + EXYNOS3250_JPGINTST ) ;
}
unsigned int exynos3250_jpeg_operating ( void __iomem * regs )
{
return readl ( regs + S5P_JPGOPR ) & EXYNOS3250_JPGOPR_MASK ;
}
unsigned int exynos3250_jpeg_compressed_size ( void __iomem * regs )
{
return readl ( regs + EXYNOS3250_JPGCNT ) & EXYNOS3250_JPGCNT_MASK ;
}
void exynos3250_jpeg_dec_stream_size ( void __iomem * regs ,
unsigned int size )
{
writel ( size & EXYNOS3250_DEC_STREAM_MASK ,
regs + EXYNOS3250_DEC_STREAM_SIZE ) ;
}
void exynos3250_jpeg_dec_scaling_ratio ( void __iomem * regs ,
unsigned int sratio )
{
switch ( sratio ) {
case 1 :
default :
sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8 ;
break ;
case 2 :
sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8 ;
break ;
case 4 :
sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8 ;
break ;
case 8 :
sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8 ;
break ;
}
writel ( sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK ,
regs + EXYNOS3250_DEC_SCALING_RATIO ) ;
}
void exynos3250_jpeg_set_timer ( void __iomem * regs , unsigned int time_value )
{
time_value & = EXYNOS3250_TIMER_INIT_MASK ;
writel ( EXYNOS3250_TIMER_INT_STAT | time_value ,
regs + EXYNOS3250_TIMER_SE ) ;
}
unsigned int exynos3250_jpeg_get_timer_status ( void __iomem * regs )
{
return readl ( regs + EXYNOS3250_TIMER_ST ) ;
}
void exynos3250_jpeg_clear_timer_status ( void __iomem * regs )
{
writel ( EXYNOS3250_TIMER_INT_STAT , regs + EXYNOS3250_TIMER_ST ) ;
}