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

📄 camera_misoc0343.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
字号:
/* *  drivers/media/video/mx2ads/camera_misoc0343.c * *  driver for Motorola MX2ADS on-board CMOS Image Sensor * *  Author: MontaVista Software, Inc. <source@mvista.com> * * 2004 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/config.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/videodev.h>#include <asm/uaccess.h>#include <asm/hardware.h>#define MODULE_NAME "misoc0343"#include <asm/hardware/misoc0343.h>#include "common.h"#include "camif.h"#define DEF_BLUE        (0)#define DEF_RED         (0)#define DEF_AWB         (1)#define DEF_HFLIP       (0)#define DEF_VFLIP       (0)static struct camera * this;extern const struct image_size mx2ads_image_size[]; extern const int mx2ads_pixfmt_depth[];#define V4L2_CID_LAST_PRIV  V4L2_CID_PRIVATE_BASE+0enum regdomain {IC, IFP};/*  Video controls  */static struct vcontrol {	struct v4l2_queryctrl qc;	int current_value;        enum regdomain domain;	u16 reg;	u16 mask;	u8 start_bit;} control[] = {        { { V4L2_CID_RED_BALANCE, "Red Balance", 0, 255, 1, DEF_RED,            V4L2_CTRL_TYPE_INTEGER },          0, IFP, MISOC0343_R33, 0xff00, 8 },        { { V4L2_CID_BLUE_BALANCE, "Blue Balance", 0, 255, 1, DEF_BLUE,            V4L2_CTRL_TYPE_INTEGER },          0, IFP, MISOC0343_R33, 0xff, 0 },        { { V4L2_CID_AUTO_WHITE_BALANCE, "Auto White Balance", 0,1,0, DEF_AWB,            V4L2_CTRL_TYPE_BOOLEAN },          0, IFP, MISOC0343_R6, 0x02, 1 },        { { V4L2_CID_HFLIP, "Horizontal Flip", 0, 1, 0, DEF_HFLIP,            V4L2_CTRL_TYPE_BOOLEAN },          0, IC, MISOC0343_IC_RDMODE, 0x4000, 14 },        { { V4L2_CID_VFLIP, "Vertical Flip", 0, 1, 0, DEF_VFLIP,            V4L2_CTRL_TYPE_BOOLEAN },          0, IC, MISOC0343_IC_RDMODE, 0x8000, 15 },};#define NUM_CONTROLS (sizeof(control)/sizeof(control[0]))#define MISOC0343_WRITE16(_sw, _reg, _val)                             \    do {                                                               \	    struct camera_serial_bus * sbus = this->camif->sbus;       \            u8 sw[2] = {(u8)(((MISOC0343_##_sw) >> 8) & 0xFF),         \                         (u8)(MISOC0343_##_sw & 0xFF)};                \            u8 data[2] = {(u8)(((_val) >> 8) & 0xFF),                  \                         (u8)((_val) & 0xFF)};                         \	    sbus->write(MISOC0343_R1, sw, 2);                          \	    sbus->write((_reg), data, 2);                              \    } while(0)#define MISOC0343_READ16(_sw, _reg, _val)                              \    do {                                                               \	    struct camera_serial_bus * sbus = this->camif->sbus;       \            u8 sw[2] = {(u8)(((MISOC0343_##_sw) >> 8) & 0xFF),         \                         (u8)(MISOC0343_##_sw & 0xFF)};                \	    sbus->write(MISOC0343_R1, sw, 2);                          \	    sbus->read((_reg), (uint8_t*)&(_val), 2);                  \    } while(0)#define MISOC0343_IFP_WRITE16(_reg, _val) \    MISOC0343_WRITE16(IFP, (_reg), (_val))#define MISOC0343_IC_WRITE16(_reg, _val) \    MISOC0343_WRITE16(IC, (_reg), (_val))#define MISOC0343_IFP_READ16(_reg, _val) \    MISOC0343_READ16(IFP, (_reg), (_val))#define MISOC0343_IC_READ16(_reg, _val) \    MISOC0343_READ16(IC, (_reg), (_val))static int misoc0343_close(void);static int misoc0343_set_control(struct v4l2_control *vc);/* * Initialise board-specfic settings to init Micron camera */static intmisoc0343_init(void){	struct v4l2_control vc;	int i;        /*	 * Reset Image core	 */	MISOC0343_IC_WRITE16(MISOC0343_IC_RESET, 0x01);	MISOC0343_IC_WRITE16(MISOC0343_IC_RESET, 0x00);	/*	 * Reset Image Flow	 */	MISOC0343_IFP_WRITE16(MISOC0343_IFP_RESET, 0x01);	MISOC0343_IFP_WRITE16(MISOC0343_IFP_RESET, 0x00);	MISOC0343_IFP_READ16(MISOC0343_R33, i);		MISOC0343_IC_WRITE16(MISOC0343_IC_RDMODE,			     (MISOC0343_RDMODE_BOOSTRST |			      MISOC0343_RDMODE_ALLFRAMES));	MISOC0343_IFP_WRITE16(MISOC0343_IFP_SHWIDTH, MISOC0343_SHWIDTH_DEFAULT);	for (i = 0; i < NUM_CONTROLS; i++) {		vc.id = control[i].qc.id;		vc.value = control[i].qc.default_value;		misoc0343_set_control(&vc);	}	misoc0343_close();	return 0;}static int misoc0343_set_fp(int fp, int xclk, int test){        dbg("Not implemented yet\n");        return -1;}static int misoc0343_get_fp(void){        dbg("Not implemented yet\n");	return -1;}static int misoc0343_write_control(struct vcontrol * lvc, u16 value){	u16 oldval, newval;	u16 reg = lvc->reg;	u16 mask = lvc->mask;		value <<= lvc->start_bit;        if (lvc->domain == IC) {            MISOC0343_IC_READ16(reg, oldval);        } else { /*IFP */            MISOC0343_IFP_READ16(reg, oldval);        }        oldval &= ~mask;        value &= mask;                /* Enforce mask on value */        newval = oldval | value;      /* Set the desired bits */        if (lvc->domain == IC) {            MISOC0343_IC_WRITE16(reg, newval);            MISOC0343_IC_READ16(reg, newval);        } else { /*IFP */            MISOC0343_IFP_WRITE16(reg, newval);            MISOC0343_IFP_READ16(reg, newval);        }	return (newval & mask) >> lvc->start_bit;}static int misoc0343_read_control(struct vcontrol * lvc){	u16 val;	u16 reg = lvc->reg;	u16 mask = lvc->mask;	        if (lvc->domain == IC) {            MISOC0343_IC_READ16(reg, val);        } else { /*IFP */            MISOC0343_IFP_READ16(reg, val);        }	return (val & mask) >> lvc->start_bit;}static intfind_vctrl(int id){	int i;	if (id < V4L2_CID_BASE || id > V4L2_CID_LAST_PRIV)		return -EDOM;	for (i = NUM_CONTROLS - 1; i >= 0; i--)		if (control[i].qc.id == id)			break;	if (i < 0)		i = -EINVAL;	return i;}static intmisoc0343_control(struct v4l2_control *vc, int write){	int i, val;	struct vcontrol * lvc;		i = find_vctrl(vc->id);	if (i < 0)		return -EINVAL;	lvc = &control[i];		if (write)		val = misoc0343_write_control(lvc, vc->value);	else		val = misoc0343_read_control(lvc);		if (val >= 0) {		vc->value = lvc->current_value = val;		return 0;	} else		return val;}static intmisoc0343_set_control(struct v4l2_control *vc){	return misoc0343_control(vc, 1);}static intmisoc0343_get_control(struct v4l2_control *vc){	return misoc0343_control(vc, 0);}static intmisoc0343_querymenu(struct v4l2_querymenu *qm){	/* No menu controls have been defined */	return -EINVAL;}static intmisoc0343_query_control(struct v4l2_queryctrl *qc){	int i;	i = find_vctrl(qc->id);	if (i == -EINVAL) {		qc->flags = V4L2_CTRL_FLAG_DISABLED;		return 0;	}	if (i < 0)		return -EINVAL;	/*  V4L2 filled in category and group, preserve them */	control[i].qc.category = qc->category;	memcpy(control[i].qc.group, qc->group, sizeof(qc->group));	*qc = control[i].qc;	return 0;}static intmisoc0343_find_size(struct v4l2_pix_format *fmt){        int isize;        for (isize = QQVGA; isize < VGA; isize++) {                if ((mx2ads_image_size[isize].height >= fmt->height) &&		    (mx2ads_image_size[isize].width >= fmt->width)) {			fmt->width = mx2ads_image_size[isize].width;			fmt->height = mx2ads_image_size[isize].height;                        return isize;                }        }        fmt->width = mx2ads_image_size[VGA].width;        fmt->height = mx2ads_image_size[VGA].height;        return VGA;}intmisoc0343_find_format(struct v4l2_pix_format* fmt){	switch (fmt->pixelformat) {            case V4L2_PIX_FMT_YUYV:		return YUV;            case V4L2_PIX_FMT_RGB565:            case V4L2_PIX_FMT_BGR24: /* will have to convert to BGR24 */		return RGB565;	}	return -1;}static intmisoc0343_set_format(struct v4l2_pix_format *fmt){	enum pixel_format pixfmt;	uint16_t reg_val;                this->imgfmt = misoc0343_find_size(fmt);         switch(this->imgfmt) {            case QQVGA:		reg_val = MISOC0343_DECIMATION_QQVGA;                break;            case QCIF:		reg_val = MISOC0343_DECIMATION_QCIF;                break;            case QVGA:		reg_val = MISOC0343_DECIMATION_QVGA;                break;            case CIF:		reg_val = MISOC0343_DECIMATION_CIF;                break;            case VGA:		reg_val = MISOC0343_DECIMATION_VGA;                break;            default:                return -EINVAL;        }	MISOC0343_IFP_WRITE16(MISOC0343_IFP_DECIMATION, reg_val);        /*         * turn camera into approprative mode         */	MISOC0343_IFP_READ16(MISOC0343_IFP_FORMAT, reg_val);	if ((pixfmt = misoc0343_find_format(fmt)) < 0)		return -EINVAL;        switch(pixfmt) {                case YUV:                    reg_val = MISOC0343_FORMAT_FLCKDTC |                        MISOC0343_FORMAT_YUV422 |                        MISOC0343_FORMAT_LENSSHADE;                    break;                case RGB565:	            reg_val |= MISOC0343_FORMAT_565RGB;                    break;                default:		    return -EINVAL;        }	MISOC0343_IFP_WRITE16(MISOC0343_IFP_FORMAT, reg_val);	return 0;}/*  * Open - open device */static int misoc0343_open(void){	uint16_t reg_val;        /*         * Make standby low (disable standby)         */	CSI_REG_READ(EXP_IO, reg_val);	reg_val &= ~EXP_IO_CSI_CTL0;	CSI_REG_WRITE(EXP_IO, reg_val);	udelay(20);	return 0;}/*  * Close - close the device */static int misoc0343_close(void){	uint16_t reg_val;        /*         * Make standby high (enable standby)         */	CSI_REG_READ(EXP_IO, reg_val);	reg_val |= EXP_IO_CSI_CTL0;	CSI_REG_WRITE(EXP_IO, reg_val);	udelay(20);	return 0;}static void misoc0343_cleanup(void){	misoc0343_close();	this->camif->sbus->cleanup();}/* * Check - whether Micron compatible camera present */static intmisoc0343_detect(void){	uint16_t reg_val;	struct camera_serial_bus * sbus;	int ret;	this = &camera_misoc0343;	sbus = this->camif->sbus;	sbus->set_devid(CAMERA_MISOC0343_DEV_ID);	CSI_REG_READ(EXP_IO, reg_val);	/*	 * Make standby low (disable standby)	 */	reg_val &= ~EXP_IO_CSI_CTL0;	CSI_REG_WRITE(EXP_IO, reg_val);        	udelay(20);	/*	 * Make reset low (reset sensor)	 */	reg_val &= ~EXP_IO_CSI_CTL1;	CSI_REG_WRITE(EXP_IO, reg_val);	udelay(200);	/*	 * Make reset high	 */	reg_val |= EXP_IO_CSI_CTL1;	CSI_REG_WRITE(EXP_IO, reg_val);	udelay(200);	if ((ret = sbus->init()) < 0) {		misoc0343_cleanup();		return ret;	}	MISOC0343_IC_READ16(MISOC0343_IC_VERSION, reg_val);	if (reg_val != MISOC0343_CORE_VERSION) {		misoc0343_cleanup();		return -ENODEV;	}	MISOC0343_IFP_READ16(MISOC0343_IFP_VERSION, reg_val);	if (reg_val != MISOC0343_IMAGE_VERSION) {		misoc0343_cleanup();		return -ENODEV;	}	return 0;}struct camera camera_misoc0343 = {	.imgfmt             = QVGA,	.pixfmt             = RGB565,		.detect             = misoc0343_detect,	.init               = misoc0343_init,	.cleanup            = misoc0343_cleanup,	.open               = misoc0343_open,	.close              = misoc0343_close,	.set_format         = misoc0343_set_format,	.set_frame_period   = misoc0343_set_fp,	.get_frame_period   = misoc0343_get_fp,		.query_control      = misoc0343_query_control,	.get_control        = misoc0343_get_control,	.set_control        = misoc0343_set_control,	.query_menu         = misoc0343_querymenu,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -