⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tw2834.c

📁 tw2834 linux下的2834驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 + -