📄 tvp5150.c
字号:
/**** MX27 TVIN/TVP5150AM1 Driver**/#include <linux/kernel.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/blkpg.h>#include <linux/i2c.h>#include <linux/i2c-algo-bit.h>#include <linux/i2c-id.h>#include <linux/i2c-dev.h>#include <linux/mm.h>#include <linux/miscdevice.h>#include <linux/proc_fs.h>#include <linux/device.h>#include <linux/list.h>#include <linux/smp_lock.h>#include <asm/arch/mxc_i2c.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/arch/mx27.h>#include <asm/arch/ipu.h>#include <asm/arch/mxc_v4l2.h>#include <asm/arch/clock.h>#include <media/v4l2-dev.h>#include "mxc_v4l2_capture.h"#include "mx27_csi.h"#include "mx27_prp.h"static sensor_interface *interface_param = NULL;static int reset_frame_rate = 30;#define PTA_BASE_ADDR IO_ADDRESS(GPIO_BASE_ADDR+0x300)#define PTD_DR (*(volatile unsigned long *)(PTA_BASE_ADDR+0x1C) ) typedef struct{ int video_type; /**< PAL or NTSC. Please refer to Define_Video_Type. */ int width; /**< The width of the output image. */ int f1height; /**< The height of the field 1 image. */ int f2height; /**< The height of the field 2 image. */ int color_format; /**< RGB or YUV. Please refer to Define_Color_Format. */ int fps; /**< The frame rate (should be constant). */ int video_source; /**< Composite or s-video. Please refer to Define_Video_Source. */} TVP5150_CFG;/** * @name Define_Color_Format * The color format of output data. The values are used by TVP5150_CFG.color_format. *//** @def RGB The RGB output *//** @def YUV The YUV output *//**@{*/#ifndef RGB #define RGB 0#endif#ifndef YUV #define YUV 1#endif/**@}*//** * @name Define_Video_Source * The vidoe source input to TVP5150 processor. The values are used by TVP5150.video_source. *//** @def CVBS The video source is from composite port *//** @def SVIDEO The video source is from s-video port *//**@{*/#ifndef CVBS #define CVBS 0#endif#ifndef SVIDEO #define SVIDEO 1#endif/**@}*//** * @name Define_Video_Type * The video type input to TVP5150 processor. The values are used by TVP5150.video_type. *//** @def PAL The video type is PAL *//** @def NTSC The video type is NTSC *//**@{*/#define VT_UNKNOWN 0#ifndef PAL #define PAL 50 //val is chose to be field freq#endif#ifndef NTSC #define NTSC 60#endif#ifndef SECAM #define SECAM 70#endif/**@}*//** * @name Define_ioctl_Operation * Define the ioctl operations for TV-in driver. *//**@{*//** @def TVP5150_IOC_CONFIG ioctl operation for configuring TVP5150 processor. *//** @def TVP5150_IOC_I2C_TEST ioctl operation for testing TVP5150 using I2C. */#define TVP5150_IOC_CONFIG 10#define TVP5150_IOC_I2C_TEST 11#define TVP5150_IOC_READ_CONFIG 12//global staticstatic TVP5150_CFG g_tvp5150_cfg = {0, 0, 0, 0, 0, 0, -1};//#define TVP5150_PM#ifdef TVP5150_PM#include <linux/pm.h>#define TVP5150_PMST_SUSPEND 0#define TVP5150_PMST_RESUME 1static unsigned int g_tvp5150_pm_status = TVP5150_PMST_RESUME;struct pm_dev *g_tvp5150_pm = 0;#endif//static devfs_handle_t devfs_handle;static int gMajor = 0;//functions and interfacestatic int tvp5150_open(struct inode *inode, struct file *filp);static int tvp5150_release(struct inode *inode, struct file *filp);static ssize_t tvp5150_read(struct file *filp, char *buf, size_t size, loff_t *l);static ssize_t tvp5150_write(struct file *filp, const char *buf, size_t size, loff_t *l);static int tvp5150_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);//localstatic void tvp5150_reset(void);static void tvp5150_normal_mode(void);static void tvp5150_power_down(void);static int tvp5150_i2c_test(void);static int tvp5150_init(int type);/************************************************************************************************* i2c related*************************************************************************************************/#define I2C_DRIVERID_TVIN 0xF000#define EMBEDDED_REGISTER 0x01#define I2C_M_READ 0x01//0x02#define I2C_M_WT 0x04#define I2C_NEED_STOP 0x0200#define TVP5150_I2C_ADDR 0x5C//0xBA //tvp5150 i2c addrstatic int i2c_tvin_attach_adapter (struct i2c_adapter * adap);static struct i2c_driver i2c_tvin_driver ={ .driver = { .owner = THIS_MODULE, .name = "tvp5150 driver", }, .attach_adapter = &i2c_tvin_attach_adapter, .detach_client = NULL, .detach_client = NULL,};static struct i2c_client i2c_tvin_client ={ .name = "tvp5150 client", .addr = TVP5150_I2C_ADDR, .driver = &i2c_tvin_driver, .flags = 0,};static int i2c_tvin_attach_adapter (struct i2c_adapter * adap){ printk("i2c_tvin_attach_adapter start\n"); if (memcmp(adap->name, "MXC I2C Adapter", 15) != 0 ) { printk("memcmp adapter name failed\n"); return -ENODEV; } i2c_tvin_client.adapter = adap; if (i2c_attach_client(&i2c_tvin_client)) { printk("tvp5150: i2c_attach_client() failed.\n"); //i2c_del_driver(&i2c_tvin_client); return -1; } interface_param = (sensor_interface *) kmalloc(sizeof(sensor_interface), GFP_KERNEL); if (!interface_param) { printk(KERN_ERR "tvp5150_attach: kmalloc failed \n"); return -1; } printk("i2c_tvin_attach_adapter end\n"); return 0;}static void i2c_tvin_init(void){ /* * set the address of the TVP5150 to the client */ //i2c_tvin_client.addr = TVP5150_I2C_ADDR; /* * call the i2c_add_driver() to register the driver * to the Linux I2C system */ if (i2c_add_driver( &i2c_tvin_driver ) != 0) { printk("I2C addr driver failed\n"); } printk("I2C addr driver successful\n"); return;}static void i2c_tvin_cleanup(void){ //i2c_tvin_client.adapter->dec_use(i2c_tvin_client.adapter); i2c_detach_client(&i2c_tvin_client ); i2c_del_driver(&i2c_tvin_driver);}/** * @brief Write one byte to TVP5150 register * * @param reg TVP5150 register address * @param data Data to be written to the register */static int i2c_tvin_write(unsigned int reg, unsigned char data){ struct i2c_msg msg; char buf[2]; int ret; /* * store the register value to the first address of the buffer * the adapter/algorithm driver will regard the first byte * as the register value */ buf[0] = (char)reg; buf[1] = data; /* * initialize the message structure */ msg.addr = i2c_tvin_client.addr; msg.flags = I2C_M_WT | I2C_NEED_STOP; msg.len = 2; msg.buf = buf; //ret = i2c_transfer( i2c_tvin_client.adapter, &msg, 1 ); ret = i2c_master_send(&i2c_tvin_client, buf, 2); return ret;}/** * @brief Read one byte from TVP5150 register * * @param reg TVP5150 register address * @param data Data buffer to receive the register value */static int i2c_tvin_read(unsigned int reg, unsigned char *data){ struct i2c_msg msg; char buf[2]; int ret = 0; /* * store the register value to the first address of the buffer * the adapter/algorithm driver will regard the first byte * as the register value */ buf[0] = (char)reg; /* * initialize the message structure */ msg.addr = i2c_tvin_client.addr; msg.flags = I2C_M_WT | I2C_NEED_STOP; msg.len = 1; msg.buf = (char *)buf; //ret =i2c_transfer(i2c_tvin_client.adapter, &msg, 1); ret = i2c_master_send(&i2c_tvin_client,buf,1); ret =0; //Maybe tvp5150 doesn't like repeat start, need to send a separate message msg.addr = i2c_tvin_client.addr; msg.flags = I2C_M_READ | I2C_NEED_STOP; msg.len = 1; msg.buf = (char *)data; //*data = buf[0]; //ret = i2c_transfer(i2c_tvin_client.adapter, &msg, 1); ret = i2c_master_recv(&i2c_tvin_client, data, 1); //printk("i2c_tvin_read I2C slave addr = %x reg = %x buf = %x...\n",i2c_tvin_client.addr,reg,*data); return ret;}/************************************************************************************************* tvp5150 api*************************************************************************************************/static void tvp5150_reset(void){ //PTD_DR &= ~0x00100000; //RESETB = 0 //PTD_DR |= 0x00080000; //PDN = 1. return;}static void tvp5150_normal_mode(void){ //RESETB = 1, PDN = 1. //PTD_DR |= 0x00180000; return;}static void tvp5150_power_down(void){ //PTD_DR |= 0x00100000; //RESETB = 1 //PTD_DR &= ~0x00080000; //PDN = 0. return;}/*** Test on I2C channel* Read / write one of the register* compare and verify if the data is correct*/static int tvp5150_i2c_test(void){ unsigned char chip_ver; //silicon ID printk("TVP5150 I2C Test...\n"); //read device ID i2c_tvin_read(0x80, &chip_ver); printk("MSB of device ID (0x51): 0x%02X\n", chip_ver); i2c_tvin_read(0x81, &chip_ver); printk("LSB of device ID (0x50): 0x%02X \n", chip_ver); return 0; }/*** TVP5150 Basic Init
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -