?? tvp5150.c
字號:
/* * Copyright 2007 Morninghan Electronics, Inc. All Rights Reserved. *//* * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html *//*! * @file tvp5150.c * * @brief TVP5150 TVin driver functions * * @ingroup Camera */#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/ctype.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/i2c.h>#include <linux/clk.h>#include <asm/arch/mxc_i2c.h>#include "mxc_v4l2_capture.h"#define TVP5150_I2C_ADDRESS 0x5D#define TVP5150_CHIP_VERSION 0x04static sensor_interface *interface_param = NULL;extern cam_data *g_cam;static int tvp5150_attach(struct i2c_adapter *adapter);static int tvp5150_detach(struct i2c_client *client);static struct i2c_driver tvp5150_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = "TVP5150 Client", }, .attach_adapter = tvp5150_attach, .detach_client = tvp5150_detach,};static struct i2c_client tvp5150_i2c_client = { .name = "TVP5150 I2C dev", .addr = TVP5150_I2C_ADDRESS, .driver = &tvp5150_i2c_driver,};/* * Function definitions */static int tvp5150_i2c_client_xfer(unsigned int addr, u8 reg, char *buf, int num, int tran_flag){ struct i2c_msg msg[2]; int ret; msg[0].addr = addr; msg[0].len = 1; msg[0].buf = ® msg[0].flags = tran_flag; msg[0].flags &= ~I2C_M_RD; msg[1].addr = addr; msg[1].len = num; msg[1].buf = buf; msg[1].flags = tran_flag; if (tran_flag & MXC_I2C_FLAG_READ) { msg[1].flags |= I2C_M_RD; } else { msg[1].flags &= ~I2C_M_RD; } ret = i2c_transfer(tvp5150_i2c_client.adapter, msg, 2); if (ret >= 0) return 0; return ret;}static int tvp5150_read_reg(u8 reg, u8 * val){ return tvp5150_i2c_client_xfer(TVP5150_I2C_ADDRESS, reg, val, 1, MXC_I2C_FLAG_READ);}static int tvp5150_write_reg(u8 reg, u8 val){ return tvp5150_i2c_client_xfer(TVP5150_I2C_ADDRESS, reg, &val, 1, 0);}/*! * tvp5150 sensor interface Initialization * @param param sensor_interface * * @param width u32 * @param height u32 * @return None */static void tvp5150_interface(sensor_interface * param, u32 width, u32 height){ param->Vsync_pol = 0x0; param->clk_mode = 0x0; //gated param->pixclk_pol = 0x0; param->data_width = 0x1; param->data_pol = 0x0; param->ext_vsync = 0x1; param->Vsync_pol = 0x0; param->Hsync_pol = 0x0; param->width = width - 1; param->height = height - 1; param->pixel_fmt = IPU_PIX_FMT_UYVY; param->mclk = 27000000; /* setup cropping */ g_cam->crop_bounds.left = 0; g_cam->crop_bounds.width = width; g_cam->crop_bounds.top = 0; g_cam->crop_bounds.height = height; g_cam->crop_defrect = g_cam->crop_bounds; if ((g_cam->crop_current.width > g_cam->crop_bounds.width) || (g_cam->crop_current.height > g_cam->crop_bounds.height)) g_cam->crop_current = g_cam->crop_bounds; g_cam->streamparm.parm.capture.capturemode = 0; g_cam->standard.index = 0; g_cam->standard.id = (height == 576) ? V4L2_STD_PAL : V4L2_STD_NTSC; g_cam->standard.frameperiod.denominator = (height == 576) ? 50 : 60; g_cam->standard.frameperiod.numerator = 1; g_cam->standard.framelines = height;}/*! * tvp5150 sensor configuration * * @param frame_rate int * * @param high_quality int * @return sensor_interface * */sensor_interface *tvp5150_config(int *frame_rate, int high_quality){ u32 out_width, out_height; u8 status, status2; out_width = 720; out_height = 576; set_mclk_rate(&interface_param->mclk); /* CVBS input */ tvp5150_write_reg(0x03, 0x09); /* Miscellaneous controls register address, */ /* enables YCbCr output and the clock output */ tvp5150_write_reg(0x04, 0xC0); /* Autoswitch mask register */#if 0 /* S-Video input */ tvp5150_write_reg(0x00, 0x01); /* Analog input control 1 (S-video in) */ tvp5150_write_reg(0x03, 0x0D); /* Miscellaneous cnotrols register address, Enables the YCbCr */ /* output data, HSYNC, VSYNC/PALI, AVID, and FID/GLCO */ tvp5150_write_reg(0x04, 0xC0); /* Autoswitch mask register */ tvp5150_write_reg(0x0D, 0x40); /* Outputs and data rates select register */#endif /* read out status */ tvp5150_read_reg(0x8C, &status); tvp5150_read_reg(0x88, &status2); if (!((status2 & 0x0E) && (status & 0x01))) printk(KERN_ERR"No video source detected.\n"); else { switch ((status >> 1) & 0x07) { case 0x0: case 0x4: /* 60Hz => NTSC */ printk(KERN_INFO"NTSC video source.\n"); out_width = 720; out_height = 487; break; case 0x1: case 0x2: case 0x3: /* 50Hz => PAL */ printk(KERN_INFO"PAL video source.\n"); break; case 0x5: printk(KERN_INFO"SECAM video source.\n"); break; default: printk(KERN_ERR"Unknown video source.\n"); break; } } tvp5150_interface(interface_param, out_width, out_height); return interface_param;}/*! * tvp5150 sensor set color configuration * * @param bright int * @param saturation int * @param red int * @param green int * @param blue int * @return None */static voidtvp5150_set_color(int bright, int saturation, int red, int green, int blue){}/*! * tvp5150 sensor get color configuration * * @param bright int * * @param saturation int * * @param red int * * @param green int * * @param blue int * * @return None */static voidtvp5150_get_color(int *bright, int *saturation, int *red, int *green, int *blue){}/*! * tvp5150 sensor set AE measurement window mode configuration * * @param ae_mode int * @return None */static void tvp5150_set_ae_mode(int ae_mode){}/*! * tvp5150 sensor get AE measurement window mode configuration * * @param ae_mode int * * @return None */static void tvp5150_get_ae_mode(int *ae_mode){}/*! * tvp5150 sensor enable/disable AE * * @param active int * @return None */static void tvp5150_set_ae(int active){}/*! * tvp5150 sensor enable/disable auto white balance * * @param active int * @return None */static void tvp5150_set_awb(int active){}/*! * tvp5150 sensor set the flicker control * * @param control int * @return None */static void tvp5150_flicker_control(int control){}/*! * tvp5150 Get mode&flicker control parameters * * @return None */static void tvp5150_get_control_params(int *ae, int *awb, int *flicker){}/*! * tvp5150 Reset function * * @return None */static sensor_interface *tvp5150_reset(void){ return tvp5150_config(0, 0);}/*! * tvp5150 get_status function, detect whether the device is present * * @return Zero on success, others on failure */static int tvp5150_get_status(void){ int retval = 0; u8 data = 0; if (!interface_param) return -ENODEV; retval = tvp5150_read_reg(0x82, &data); printk(KERN_INFO"TVP5150 Chip version = 0x%02X\n", data); if ((retval < 0) || (data != TVP5150_CHIP_VERSION)) return -ENODEV; else return 0;}struct camera_sensor camera_sensor_if = { .set_color = tvp5150_set_color, .get_color = tvp5150_get_color, .set_ae_mode = tvp5150_set_ae_mode, .get_ae_mode = tvp5150_get_ae_mode, .set_ae = tvp5150_set_ae, .set_awb = tvp5150_set_awb, .flicker_control = tvp5150_flicker_control, .get_control_params = tvp5150_get_control_params, .config = tvp5150_config, .reset = tvp5150_reset, .get_status = tvp5150_get_status,};/*! * tvp5150 I2C detect_client function * * @param adapter struct i2c_adapter * * @param address int * @param kind int * * @return Error code indicating success or failure */static int tvp5150_detect_client(struct i2c_adapter *adapter, int address, int kind){ tvp5150_i2c_client.adapter = adapter; if (i2c_attach_client(&tvp5150_i2c_client)) { tvp5150_i2c_client.adapter = NULL; printk(KERN_ERR "tvp5150_detect_client: i2c_attach_client failed\n"); return -1; } interface_param = (sensor_interface *) kmalloc(sizeof(sensor_interface), GFP_KERNEL); if (!interface_param) { printk(KERN_ERR "tvp5150_detect_client: kmalloc failed \n"); return -1; } interface_param->mclk = 27000000; printk(KERN_INFO "TVP5150 Detected\n"); return 0;}static unsigned short normal_i2c[] = { TVP5150_I2C_ADDRESS, I2C_CLIENT_END };/* Magic definition of all other variables and things */I2C_CLIENT_INSMOD;/*! * tvp5150 I2C attach function * * @param adapter struct i2c_adapter * * @return Error code indicating success or failure */static int tvp5150_attach(struct i2c_adapter *adap){ uint32_t mclk = 27000000; struct clk *clk; int err; clk = clk_get(NULL, "csi_clk"); clk_enable(clk); set_mclk_rate(&mclk); err = i2c_probe(adap, &addr_data, &tvp5150_detect_client); clk_disable(clk); clk_put(clk); return err;}/*! * tvp5150 I2C detach function * * @param client struct i2c_client * * @return Error code indicating success or failure */static int tvp5150_detach(struct i2c_client *client){ int err; if (!tvp5150_i2c_client.adapter) return -1; err = i2c_detach_client(&tvp5150_i2c_client); tvp5150_i2c_client.adapter = NULL; if (interface_param) kfree(interface_param); interface_param = NULL; return err;}extern void gpio_tvp5150_active(void);/*! * tvp5150 init function * * @return Error code indicating success or failure */static __init int tvp5150_init(void){ u8 err; gpio_tvp5150_active(); err = i2c_add_driver(&tvp5150_i2c_driver); return err;}extern void gpio_tvp5150_inactive(void);/*! * tvp5150 cleanup function * * @return Error code indicating success or failure */static void __exit tvp5150_clean(void){ i2c_del_driver(&tvp5150_i2c_driver); gpio_tvp5150_inactive();}module_init(tvp5150_init);module_exit(tvp5150_clean);/* Exported symbols for modules. */EXPORT_SYMBOL(camera_sensor_if);MODULE_AUTHOR("Morninghan electronics, Inc.");MODULE_DESCRIPTION("TVP5150 TVin Driver");MODULE_LICENSE("GPL");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -