📄 s3c_pp_6400.c
字号:
/* * linux/drivers/video/s3c_pp_6400.c * * Revision 1.0 * * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * * S3C PostProcessor driver * */#include <linux/init.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/types.h>#include <linux/timer.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/platform_device.h>#include <linux/interrupt.h>#include <linux/clk.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <linux/errno.h> /* error codes */#include <asm/div64.h>#include <linux/mm.h>#include <linux/tty.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/uaccess.h>#include <asm/arch/map.h>#include <linux/miscdevice.h>#include <linux/poll.h>#include <linux/mutex.h>#include <linux/init.h>#include <linux/version.h>#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)#include <linux/config.h>#include <asm/arch/registers.h>#include <asm/arch-s3c64xx/reserved_mem.h>#else#include <asm/arch/regs-pp.h>#include <asm/arch/regs-lcd.h>#include <asm/arch-s3c2410/regs-s3c6400-clock.h>#include <asm/arch-s3c2410/reserved_mem.h>#include <linux/pm.h>#include <asm/plat-s3c24xx/pm.h>#endif#include "s3c_pp_common.h"#define PFX "s3c_pp"#define NO_PIP_MODE 1 // Currently, Do not support PIP mode// if you want to modify src/dst buffer size, modify below defined size #define SYSTEM_RAM 0x07000000 // 128mb#define RESERVE_POST_MEM 8*1024*1024 // 8mb#define PRE_BUFF_SIZE 4*1024*1024 //4 // 4mb#define POST_BUFF_SIZE ( RESERVE_POST_MEM - PRE_BUFF_SIZE )#define POST_BUFF_BASE_ADDR POST_RESERVED_MEM_START#define USE_DEDICATED_MEM 1static struct resource *s3c_pp_mem;static void __iomem *s3c_pp_base;static int s3c_pp_irq = NO_IRQ;static struct clk *pp_clock;static struct clk *h_clk;static struct mutex *h_mutex;static wait_queue_head_t waitq;void set_scaler_register(scaler_info_t * scaler_info, pp_params *pParams){ __raw_writel((scaler_info->pre_v_ratio<<7)|(scaler_info->pre_h_ratio<<0), s3c_pp_base + S3C_VPP_PRESCALE_RATIO); __raw_writel((scaler_info->pre_dst_height<<12)|(scaler_info->pre_dst_width<<0), s3c_pp_base + S3C_VPP_PRESCALEIMGSIZE); __raw_writel(scaler_info->sh_factor, s3c_pp_base + S3C_VPP_PRESCALE_SHFACTOR); __raw_writel(scaler_info->dx, s3c_pp_base + S3C_VPP_MAINSCALE_H_RATIO); __raw_writel(scaler_info->dy, s3c_pp_base + S3C_VPP_MAINSCALE_V_RATIO); __raw_writel((pParams->SrcHeight<<12)|(pParams->SrcWidth), s3c_pp_base + S3C_VPP_SRCIMGSIZE); __raw_writel((pParams->DstHeight<<12)|(pParams->DstWidth), s3c_pp_base + S3C_VPP_DSTIMGSIZE);}void set_buf_addr_register(buf_addr_t *buf_addr, pp_params *pParams){ __raw_writel(buf_addr->src_start_y, s3c_pp_base + S3C_VPP_ADDRSTART_Y); __raw_writel(buf_addr->offset_y, s3c_pp_base + S3C_VPP_OFFSET_Y); __raw_writel(buf_addr->src_end_y, s3c_pp_base + S3C_VPP_ADDREND_Y); if(pParams->SrcCSpace == YC420) { __raw_writel(buf_addr->src_start_cb, s3c_pp_base + S3C_VPP_ADDRSTART_CB); __raw_writel(buf_addr->offset_cr, s3c_pp_base + S3C_VPP_OFFSET_CB); __raw_writel(buf_addr->src_end_cb, s3c_pp_base + S3C_VPP_ADDREND_CB); __raw_writel(buf_addr->src_start_cr, s3c_pp_base + S3C_VPP_ADDRSTART_CR); __raw_writel(buf_addr->offset_cb, s3c_pp_base + S3C_VPP_OFFSET_CR); __raw_writel(buf_addr->src_end_cr, s3c_pp_base + S3C_VPP_ADDREND_CR); } if(pParams->OutPath == POST_DMA) { __raw_writel(buf_addr->dst_start_rgb, s3c_pp_base + S3C_VPP_ADDRSTART_RGB); __raw_writel(buf_addr->offset_rgb, s3c_pp_base + S3C_VPP_OFFSET_RGB); __raw_writel(buf_addr->dst_end_rgb, s3c_pp_base + S3C_VPP_ADDREND_RGB); if(pParams->DstCSpace == YC420) { __raw_writel(buf_addr->out_src_start_cb, s3c_pp_base + S3C_VPP_ADDRSTART_OCB); __raw_writel(buf_addr->out_offset_cb, s3c_pp_base + S3C_VPP_OFFSET_OCB); __raw_writel(buf_addr->out_src_end_cb, s3c_pp_base + S3C_VPP_ADDREND_OCB); __raw_writel(buf_addr->out_src_start_cr, s3c_pp_base + S3C_VPP_ADDRSTART_OCR); __raw_writel(buf_addr->out_offset_cr, s3c_pp_base + S3C_VPP_OFFSET_OCR); __raw_writel(buf_addr->out_src_end_cr, s3c_pp_base + S3C_VPP_ADDREND_OCR); } }}void set_data_format_register(pp_params *pParams){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); tmp |= (0x1<<16); tmp |= (0x2<<10); // set the source color space switch(pParams->SrcCSpace) { case YC420: tmp &=~((0x1<<3)|(0x1<<2)); tmp |= (0x1<<8)|(0x1<<1); break; case YCBYCR: tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3)|(0x1<<0)); tmp |= (0x1<<2)|(0x1<<1); break; case YCRYCB: tmp &= ~((0x1<<8)|(0x1<<3)|(0x1<<0)); tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1); break; case CBYCRY: tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3)); tmp |= (0x1<<2)|(0x1<<1)|(0x1<<0); break; case CRYCBY: tmp &= ~((0x1<<8)|(0x1<<3)); tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1)|(0x1<<0); break; case RGB24: tmp &= ~(0x1<<8); tmp |= (0x1<<3)|(0x1<<2)|(0x1<<1); break; case RGB16: tmp &= ~((0x1<<8)|(0x1<<1)); tmp |= (0x1<<3)|(0x1<<2); break; default: break; } // set the destination color space if(pParams->OutPath == POST_DMA) { switch(pParams->DstCSpace) { case YC420: tmp &= ~(0x1<<18); tmp |= (0x1<<17); break; case YCBYCR: tmp &= ~((0x1<<20)|(0x1<<19)|(0x1<<18)|(0x1<<17)); break; case YCRYCB: tmp &= ~((0x1<<19)|(0x1<<18)|(0x1<<17)); tmp |= (0x1<<20); break; case CBYCRY: tmp &= ~((0x1<<20)|(0x1<<18)|(0x1<<17)); tmp |= (0x1<<19); break; case CRYCBY: tmp &= ~((0x1<<18)|(0x1<<17)); tmp |= (0x1<<20)|(0x1<<19); break; case RGB24: tmp |= (0x1<<18)|(0x1<<4); break; case RGB16: tmp &= ~(0x1<<4); tmp |= (0x1<<18); break; default: break; } } else if(pParams->OutPath == POST_FIFO) { if(pParams->DstCSpace == RGB30) { tmp |= (0x1<<18)|(0x1<<13); } else if(pParams->DstCSpace == YUV444) { tmp |= (0x1<<13); tmp &= ~(0x1<<18)|(0x1<<17); } } __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}static void set_clock_src(pp_clk_src_t clk_src){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); if(clk_src == HCLK) { if((unsigned int)h_clk > 66000000) { tmp &= ~(0x7f<<23); tmp |= (1<<24); tmp |= (1<<23); } else { tmp &=~ (0x7f<<23); } } else if(clk_src == PLL_EXT) { } else { tmp &=~(0x7f<<23); } tmp = (tmp &~ (0x3<<21)) | (clk_src<<21); __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}static void set_data_path(pp_params *pParams){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); tmp &=~(0x1<<12); // 0: progressive mode, 1: interlace mode tmp &=~(0x1<<31); if(pParams->OutPath == POST_FIFO) { s3c_fb_enable_local_post(0); tmp |= (0x1<<13); } else if(pParams->OutPath == POST_DMA) { tmp &=~(0x1<<13); } __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}static void set_interlace_mode(u32 on_off){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); if(on_off == 1) tmp |=(1<<12); else tmp &=~(1<<12); __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}static void set_auto_load(pp_params *pParams){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); if(pParams->Mode == FREE_RUN) { tmp |= (1<<14); } else if(pParams->Mode == ONE_SHOT) { tmp &=~(1<<14); } __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}static void post_int_enable(u32 int_type){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); if(int_type == 0) { //Edge triggering tmp &= ~(S3C_MODE_IRQ_LEVEL); } else if(int_type == 1) { //level triggering tmp |= S3C_MODE_IRQ_LEVEL; } tmp |= S3C_MODE_POST_INT_ENABLE; __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}static void post_int_disable(void){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); tmp &=~ S3C_MODE_POST_INT_ENABLE; __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}static void start_processing(void){ __raw_writel(0x1<<31, s3c_pp_base + S3C_VPP_POSTENVID);}static void stop_processing_free_run(void){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_MODE); tmp &=~(1<<14); __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE);}s3c_pp_state_t post_get_processing_state(void){ s3c_pp_state_t state; u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_POSTENVID); if (tmp & S3C_VPP_POSTENVID) { state = POST_BUSY; } else { state = POST_IDLE; } printk("Post processing state = %d\n", state); return state;}static void config_pp(pp_params *pParams){ u32 tmp; tmp = __raw_readl(s3c_pp_base + S3C_VPP_POSTENVID); tmp &= ~S3C_POSTENVID_ENABLE; __raw_writel(tmp, s3c_pp_base + S3C_VPP_POSTENVID); tmp = S3C_MODE2_ADDR_CHANGE_DISABLE |S3C_MODE2_CHANGE_AT_FRAME_END |S3C_MODE2_SOFTWARE_TRIGGER; __raw_writel(tmp, s3c_pp_base + S3C_VPP_MODE_2);#ifdef NO_PIP_MODE pParams->SrcStartX = pParams->SrcStartY = 0; pParams->DstStartX = pParams->DstStartY = 0; pParams->SrcWidth = pParams->SrcFullWidth; pParams->SrcHeight = pParams->SrcFullHeight; pParams->DstWidth = pParams->DstFullWidth; pParams->DstHeight = pParams->DstFullHeight;#endif set_clock_src(HCLK); // setting the output data path (DMA or FIFO) set_data_path(pParams); // setting the src/dst color space set_data_format(pParams); // setting the src/dst size set_scaler(pParams); // setting the src/dst buffer address set_buf_addr(pParams); set_auto_load(pParams);}irqreturn_t s3c_pp_isr(int irq, void *dev_id, struct pt_regs *regs){ u32 mode; mode = __raw_readl(s3c_pp_base + S3C_VPP_MODE); mode &= ~(1 << 6); /* Clear Source in POST Processor */ __raw_writel(mode, s3c_pp_base + S3C_VPP_MODE); wake_up_interruptible(&waitq); return IRQ_HANDLED;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -