📄 saa7121.c
字号:
/* * linux/drivers/video/saa7121.c * *//* History * 1 */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/device.h>#include <linux/errno.h>#include <linux/fs.h>#include <asm/io.h>#include <linux/types.h>#include <linux/string.h>#include <linux/major.h>#include <linux/miscdevice.h>#include <asm/uaccess.h>#include <linux/i2c.h>#include <linux/i2c-dev.h>#include <linux/videodev.h>#include <linux/video_encoder.h>#include "saa7121.h"#define I2C_NAME(s) (s)->name#define MODULE_NAME "SAA7121 DRIVER"#define VER_NO 0.0.1#define DEBUG 1#define MMIO_BASE 0x1be00000#define QVCP5L_BASE 0x10e000#define QVCP5L_OUT_CTRL_OFFSET 0x3c#define QVCP5L_ONSH_CTRL_OFFSET 0x70#define QVCP5L_OUT_CTRL MMIO_BASE + QVCP5L_BASE + QVCP5L_OUT_CTRL_OFFSET#define QVCP5L_ONSH_CTRL MMIO_BASE + QVCP5L_BASE + QVCP5L_ONSH_CTRL_OFFSET#define QVCP5L_OUT_CTRL_MSK 0xfffc9888#define QVCP5L_OUT_CTRL_SET 0x00003644#define ENCODER_SET_REG _IOW('e', 10, int)#define ENCODER_GET_REG _IOW('e', 11, int)#define ENCODER_SET_LEFT_RIGHT _IOW('e', 12, int)#define ENCODER_SET_TOP_BOTTOM _IOW('e', 13, int)static ulong out_ctrl_value;static int debug = 8;#define dprintk(num, format, args...) \ do { \ if (debug >= num) \ printk(format, ##args); \ } while (0)/* ----------------------------------------------------------------------- *//* Initialization Sequence */ static char *mode_option = "pal";module_param(mode_option,charp,0);struct saa7121 { unsigned char reg[128]; int norm; //PAL or NTSC int enable; int bright; int contrast; int hue; int sat;};static struct i2c_client *saa7121_client;#define DEVNAME "saa7121"#define I2C_SAA7121 0x8cstatic inline int saa7121_read (struct i2c_client *client,u8 reg);static int saa7121_write (struct i2c_client *client, u8 reg, u8 value);static int saa7121_command (struct i2c_client *client, unsigned int cmd, void *arg);static int saa7121_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static const unsigned char init_common[] = { 0x26, 0x00, 0x27, 0x00,};/*PAL 输出模式配置*/static const unsigned char init_pal[] = { 0x26, 0x0, 0x27, 0x0, 0x28, 0x21, 0x29, 0x1d, 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, 0x3a, 0x13, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, 0x5a, 0x3f, 0x5b, 0xa0, 0x5c, 0xd8, 0x5d, 0x30, 0x5e, 0x3b, 0x5f, 0x75, 0x60, 0x0, 0x61, 0x06, 0x62, 0x40, 0x63, 0xcb, 0x64, 0x8a, 0x65, 0x09, 0x66, 0x2a, 0x67, 0x0, 0x68, 0x0, 0x69, 0x0, 0x6a, 0x0, 0x6b, 0x20, 0x6c, 0x01, 0x6d, 0x30, 0x6e, 0xa0, 0x6f, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x0, 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, 0x78, 0x0, 0x79, 0x0, 0x7a, 0x00, 0x7b, 0x00, 0x7c, 0x00, 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0};/*NTSC 输出模式配置*/static const unsigned char init_ntsc[] = { 0x26, 0x0, 0x27, 0x0, 0x28, 0x19, 0x29, 0x1d, 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, 0x3a, 0x13, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, 0x5a, 0x67, 0x5b, 0x76, 0x5c, 0xa5, 0x5d, 0x2a, 0x5e, 0x2e, 0x5f, 0x6e, 0x60, 0x0, 0x61, 0x15, 0x62, 0x3f, 0x63, 0x1f, 0x64, 0x7c, 0x65, 0xf0, 0x66, 0x21, 0x67, 0x0, 0x68, 0x0, 0x69, 0x0, 0x6a, 0x80, 0x6b, 0x20, 0x6c, 0x01, 0x6d, 0x31, 0x6e, 0x80, 0x6f, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x0, 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, 0x78, 0x0, 0x79, 0x0, 0x7a, 0x00, 0x7b, 0x00, 0x7c, 0x00, 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0};static int saa7121_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ u8 reg; u8 value; ulong setting; int readval=0; struct saa7121 *encoder = i2c_get_clientdata(saa7121_client); switch (cmd) { /*写寄存器的值*/ case ENCODER_SET_LEFT_RIGHT: /* 0x6c from 0x01 to 0xf1,not low four bits */ if( get_user(setting, (ulong *)arg) == 0) { reg =0x6c; value =(u8) (setting & 0x000f); value =(value<<4)|0x01; //printk("set register 0x%02x = 0x%02x\n",reg, value); if (saa7121_write(saa7121_client, reg, value)<0) /* set register */ return -EINVAL; } break; case ENCODER_SET_TOP_BOTTOM: /* 0x6d,from 0x20 to 0x3f */ if( get_user(setting, (ulong *)arg) == 0) { reg =0x6d; value =(u8) (setting & 0x001f); value =value|0x20; //printk("set register 0x%02x = 0x%02x\n",reg, value); if (saa7121_write(saa7121_client, reg, value)<0) /* set register */ return -EINVAL; } break; case ENCODER_SET_REG: if( get_user(setting, (ulong *)arg) == 0) { reg =(u8) ((setting & 0xff00) >> 8); value =(u8) (setting & 0x00ff); printk("set register 0x%02x = 0x%02x\n",reg, value); if (saa7121_write(saa7121_client, reg, value)<0) /* set register */ return -EINVAL; } break; /*读取寄存器的值(全返回第一个寄存器的值,saa7121只有第一寄存器可读)*/ case ENCODER_GET_REG: if( get_user(setting, (ulong *)arg) == 0){ reg = (u8)(setting & 0x00ff); if ((readval = saa7121_read(saa7121_client, reg))<0) /* get register */ return -EINVAL; printk("Read register 0x%02x, value = 0x%x\n",reg,readval); put_user(readval, (ulong *)arg ); } break; /*获取encorder 的能力*/ case ENCODER_GET_CAPABILITIES: { struct video_encoder_capability cap; cap.flags = VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC; cap.inputs = 1; cap.outputs = 1; if (copy_to_user((struct video_encoder_capability*)arg, &cap, sizeof(struct video_encoder_capability)) ) return -EINVAL; } break; /*设置输出格式*/ case ENCODER_SET_NORM: { ulong iarg ; if( get_user(iarg, (ulong *)arg) == 0){ saa7121_write_block(saa7121_client, init_common, sizeof(init_common)); switch (iarg) { case VIDEO_MODE_NTSC: saa7121_write_block(saa7121_client, init_ntsc, sizeof(init_ntsc)); printk("saa7121 set output mode : NTSC\n"); break; case VIDEO_MODE_PAL: saa7121_write_block(saa7121_client, init_pal, sizeof(init_pal)); printk("saa7121 set output mode : PAL\n"); break; default: return -EINVAL; } } encoder->norm = iarg; } break; /*使能输出*/ case ENCODER_ENABLE_OUTPUT: { ulong iarg ; if( get_user(iarg, (ulong *)arg) == 0){ encoder->enable = !!iarg; saa7121_write(saa7121_client, 0x61, (encoder->reg[0x61] & 0xbf) | (encoder->enable ? 0x00 : 0x40)); printk("saa7121 enable output : %c\n", encoder->enable ? 'Y':'N'); } } break; default: return -EINVAL; } return 0;}/* ----------------------------------------------------------------------- */static struct file_operations saa7121_fops = { .owner = THIS_MODULE, .read = NULL, .open = NULL, .release = NULL, .ioctl = saa7121_ioctl,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -