?? tw2834.c
字號:
/* extdrv/peripheral/vad/tw2834.c
*
* Copyright (c) 2006 Hisilicon Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
* History:
* 10-April-2006 create this file
* 2006-04-29 add record path half d1 mod
* 2006-05-13 set the playpath default output mod to full
* 2006-05-24 add record mod 2cif
* 2006-06-15 support mod changing between every record mod
* 2006-08-12 change the filters when record mod change
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/system.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/list.h>
#include <asm/semaphore.h>
#include <asm/delay.h>
#include "tw2834.h"
#include "tw2834_def.h"
/*use the tw2834 serial interface*/
#define _USE_SERIAL_INTERFACE
/*#define _USE_PARALLEL_INTERFACE*/
/*
* insmod parameter:
* mchannel = 0 , videosize = 0, 1 cif
* mchannel = 0 , videosize = 1, 1 d1
* mchannel = 1 , videosize = 0, 4 cif
* mchannel = 1 , videosize = 1, 2 half d1
* mchannel = 1 , videosize = 2, 4 d1
* mchannel = 1 , videosize = 3, 4 half cif(normal quad)
* mchannel = 1 , videosize = 4, 2 cif
* norm_mode = 0, PAL mode
* norm_mode = 1, NTSC mode
*/
static int mchannel = 0;
static int videosize = 0;
static int norm_mode = VIDEO_NORM_PAL;
#ifdef _USE_SERIAL_INTERFACE
#include "hi_i2c.h"
/* tw2834 i2c slaver address micro-definition. */
#define TW2834_I2C_ADDR 0x44
/*
* initialize gpio control routine
* do nothing
*/
static void init_gpio_control(void)
{
return;
}
/*
* release gpio control routine
* do nothing
*/
static void release_gpio_control(void)
{
return;
}
/*
* tw2834 write byte routine via I2C.
* @param addr: address include page number and register address
* @param data: the data write to the register
* @return value:0--success; -1--write over time.
*/
static int do_2834_write_byte(int addr, unsigned char data)
{
return hi_i2c_writespecial(TW2834_I2C_ADDR,((0x300&addr)>>8),(addr&0xff),data&0xff);
}
/*
* tw2834 read byte routine via I2C.
* @param addr: address include page number and register address
* @return value:the content of the register.
*/
static unsigned char do_2834_read_byte(int addr)
{
return hi_i2c_readspecial(TW2834_I2C_ADDR,((addr&0x300)>>8),(addr&0xff));
}
/*
* tw2834 write register routine .
* @param page: page number
* @param addr: register address
* @param value: the data write to the register
* @return value:nothing.
*/
static void tw2834_write_byte(int page, int addr, int value)
{
if(do_2834_write_byte(((page<<8)|addr), value))
{
printk("\tTW2834_ERROR: write failed....\n");
return;
}
}
/*
* tw2834 read register routine .
* @param page: page number
* @param addr: register address
* @return value:the data read from the register.
*/
static unsigned char tw2834_read_byte(int page, int addr)
{
unsigned char data;
data = do_2834_read_byte((page<<8)|addr);
return data;
}
/*
* tw2834 write a group of register routine .
* @param page: page number
* @param addr: start register address
* @param tbl_ptr: the first data pointer
* @param tbl_cnt: the number of data
* @return value:nothing.
*/
static void tw2834_write_table(int page,int addr,unsigned char *tbl_ptr,int tbl_cnt)
{
int i;
unsigned int value;
int temp;
for ( i=0;i<tbl_cnt;i++)
{
value = *tbl_ptr;
temp = addr+i;
if(do_2834_write_byte(((page<<8)|temp), value))
{
printk("\tTW2834_ERROR: write failed....\n");
return;
}
tbl_ptr++;
}
}
#else /* _USE_PARALLEL_INTERFACE */
/*parallel interface is not available now.*/
#endif
/************************** video input control *******************************/
/*
* Scaling Function of horizontal for video input of display path and record path.
* @param path: TW2834_PATH_X display path; TW2834_PATH_Y record path
* @param ch: channel number
* @param ratio_x: scaleing ratio
* @return value: null.
*/
static void tw2834_setvin_scale_ratiox(unsigned char path,unsigned char ch,unsigned short ratio_x)
{
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x1c, (ratio_x & 0xff00) >> 8);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x1d, (ratio_x & 0xff));
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x1e, (ratio_x & 0xff00) >> 8);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x1f, (ratio_x & 0xff));
}
}
/*
* Scaling Function of vertical for video input of display path and record path.
* @param path: TW2834_PATH_X display path; TW2834_PATH_Y record path
* @param ch: channel number
* @param ratio_y: scaleing ratio
* @return value: null.
*/
static void tw2834_setvin_scale_ratioy(unsigned char path,unsigned char ch,unsigned short ratio_y)
{
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x18, (ratio_y & 0xff00) >> 8);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x19, (ratio_y & 0xff));
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x1a, (ratio_y & 0xff00) >> 8);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x1b, (ratio_y & 0xff));
}
}
/*
* Scaling Function of vertical and horizontal for video input of display path and record path.
* @param path: TW2834_PATH_X display path; TW2834_PATH_Y record path
* @param ch: channel number
* @param ratio_y: scaleing ratio of vertical
* @param ratio_x: scaleing ratio of horizontal
* @return value: null.
*/
static void tw2834_setvin_scale_ratio(unsigned char path,unsigned char ch,
unsigned short ratio_x,unsigned short ratio_y)
{
if (ch > 3)
{
printk("\tTW2834_ERROR: Channel number input error\n");
return;
}
tw2834_setvin_scale_ratiox(path, ch, ratio_x);
tw2834_setvin_scale_ratioy(path, ch, ratio_y);
if ((0xffff == ratio_x) && (0xffff == ratio_y))
{
if (VIDEO_NORM_PAL == norm_mode)
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0x00);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x0f);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x0f);
}
}
else
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0x00);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x07);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x07);
}
}
}
if ((0x7fff == ratio_x) && (0xffff == ratio_y))
{
if (VIDEO_NORM_PAL == norm_mode)
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0x05);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0x10);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0x10);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x0f);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x0f);
}
}
else
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0x05);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0x10);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0x10);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x07);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x07);
}
}
}
if ((0xffff == ratio_x) && (0x7fff == ratio_y))
{
if (VIDEO_NORM_PAL == norm_mode)
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0xa0);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0x00);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x07);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x07);
}
}
else
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0xa0);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0x00);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x07);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x07);
}
}
}
if ((0x7fff == ratio_x) && (0x7fff == ratio_y))
{
if (VIDEO_NORM_PAL == norm_mode)
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0xa5);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0x00);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0x00);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x07);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x07);
}
}
else
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x14, 0x50);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x15, 0xa0);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x16, 0xc0);
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x17, 0xc0);
if(CHKBIT_SET(path, TW2834_PATH_X))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x20, 0x07);
}
if(CHKBIT_SET(path, TW2834_PATH_Y))
{
tw2834_write_byte(PAGE0, (0x40 * ch) + 0x21, 0x07);
}
}
}
}
/*************************record path control**********************************/
/*
* Set the mode of the record path.
* @param frame: frame mode or not (0,normal mod; 1,frame mod)
* @param dis_mode: DVR mod or not (0,normal mod; 1,DVR mod)
* @return value: null.
*/
static void tw2834_set_record_mod(unsigned char frame_op, unsigned char dis_mode)
{
unsigned char byte_tmp;
byte_tmp = tw2834_read_byte(PAGE1, REG_RECORD_MOD);
CLEAR_BIT(byte_tmp, 0x40);
SET_BIT(byte_tmp, ((frame_op & 0x01) << 6));
CLEAR_BIT(byte_tmp, 0x10);
SET_BIT(byte_tmp, ((dis_mode & 0x01) << 4));
tw2834_write_byte(PAGE1, REG_RECORD_MOD, byte_tmp);
}
/*
* Set the position of the channel for record path.
* @param ch: channel number
* @param pos: the position of the channel (can be 0 1 2 3)
* @return value: null.
*/
static void tw2834_set_record_pic_pos(unsigned char ch, unsigned char pos)
{
unsigned char byte_tmp;
if(ch > 3 || pos > 3)
{
printk("\tTW2834_ERROR: Channel number or position input error\n");
return;
}
byte_tmp = tw2834_read_byte(PAGE1, REG_PIC_POS);
CLEAR_BIT(byte_tmp, (3 << (ch << 1)));
SET_BIT(byte_tmp, (pos << (ch << 1)));
tw2834_write_byte(PAGE1, REG_PIC_POS, byte_tmp);
}
/*
* Set the pic size of each channel for the record path.
* @param ch: channel number
* @param pos: the size of the channel (can be 0 1 2 3)
* @return value: null.
*/
static void tw2834_set_record_pic_size(unsigned char ch, unsigned char size)
{
unsigned char byte_tmp;
if(ch > 3 || size > 3)
{
printk("\tTW2834_ERROR: Channel number or size input error\n");
return;
}
byte_tmp = tw2834_read_byte(PAGE1, REG_PIC_SIZE);
CLEAR_BIT(byte_tmp, (3 << (ch << 1)));
SET_BIT(byte_tmp, (size << (ch << 1)));
tw2834_write_byte(PAGE1, REG_PIC_SIZE, byte_tmp);
}
/*
* Set the operation mode of each channel for the record path.
* @param op_mod: operation mode (can be FUNC_MODE_LIVE/STROBE/SWITCH )
* @return value: null.
*/
static void tw2834_set_op_mode(unsigned char op_mod)
{
unsigned char byte_tmp;
unsigned char byte_op_mod;
byte_op_mod = op_mod << 4;
/*set switch mod for record path channel 0*/
byte_tmp = tw2834_read_byte(PAGE1, 0x60);
CLEAR_BIT(byte_tmp, 0x30);
SET_BIT(byte_tmp, byte_op_mod);
tw2834_write_byte(PAGE1, 0x60, byte_tmp);
/*set switch mod for record path channel 1*/
byte_tmp = tw2834_read_byte(PAGE1, 0x63);
CLEAR_BIT(byte_tmp, 0x30);
SET_BIT(byte_tmp, byte_op_mod);
tw2834_write_byte(PAGE1, 0x63, byte_tmp);
/*set switch mod for record path channel 2*/
byte_tmp = tw2834_read_byte(PAGE1, 0x66);
CLEAR_BIT(byte_tmp, 0x30);
SET_BIT(byte_tmp, byte_op_mod);
tw2834_write_byte(PAGE1, 0x66, byte_tmp);
/*set switch mod for record path channel 3*/
byte_tmp = tw2834_read_byte(PAGE1, 0x69);
CLEAR_BIT(byte_tmp, 0x30);
SET_BIT(byte_tmp, byte_op_mod);
tw2834_write_byte(PAGE1, 0x69, byte_tmp);
}
/******************************************************************************/
/*
* Set the record path to frame quad mod.
* @return value: null.
*/
static void set_record_frame_quad(void)
{
/*set vin scaling*/
tw2834_setvin_scale_ratio(TW2834_PATH_Y, 0, 0x7fff, 0xffff);
tw2834_setvin_scale_ratio(TW2834_PATH_Y, 1, 0x7fff, 0xffff);
tw2834_setvin_scale_ratio(TW2834_PATH_Y, 2, 0x7fff, 0xffff);
tw2834_setvin_scale_ratio(TW2834_PATH_Y, 3, 0x7fff, 0xffff);
/*set live mod for record path */
tw2834_set_op_mode(FUNC_MODE_LIVE);
/*set record mod frame*/
tw2834_set_record_mod(1, 0);
/*set pic_size for each channel*/
tw2834_set_record_pic_size(0, 0);
tw2834_set_record_pic_size(1, 0);
tw2834_set_record_pic_size(2, 0);
tw2834_set_record_pic_size(3, 0);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -