Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- */
- /*
- * 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; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- #define DEBUG 8
- #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/clk.h>
- #include <linux/of_device.h>
- #include <linux/i2c.h>
- #include <linux/of_gpio.h>
- #include <linux/pinctrl/consumer.h>
- #include <linux/regulator/consumer.h>
- #include <linux/fsl_devices.h>
- #include <media/v4l2-chip-ident.h>
- #include <media/v4l2-int-device.h>
- #include "mxc_v4l2_capture.h"
- //#define USE_BT656
- //#define USE_RAW
- #define OV7740_VOLTAGE_ANALOG 2800000
- #define OV7740_VOLTAGE_DIGITAL_CORE 1500000
- #define OV7740_VOLTAGE_DIGITAL_IO 1800000
- #define MIN_FPS 30
- #define MAX_FPS 60
- #define DEFAULT_FPS 30
- #define OV7740_XCLK_MIN 6000000
- #define OV7740_XCLK_MAX 27000000
- #define OV7740_CHIP_ID_HIGH_BYTE 0x1C
- #define OV7740_CHIP_ID_HIGH_BYTE_READ 0x7F
- #define OV7740_CHIP_ID_LOW_BYTE 0x1D
- #define OV7740_CHIP_ID_LOW_BYTE_READ 0xA2
- enum ov7740_mode {
- ov7740_mode_MIN = 0,
- ov7740_mode_VGA_640_480 = 0,
- ov7740_mode_QVGA_320_240 = 1,
- ov7740_mode_MAX = 1
- };
- enum ov7740_frame_rate {
- ov7740_15_fps,
- ov7740_30_fps
- };
- static int ov7740_framerates[] = {
- [ov7740_15_fps] = 15,
- [ov7740_30_fps] = 30,
- };
- struct reg_value {
- u16 u16RegAddr;
- u8 u8Val;
- u8 u8Mask;
- u32 u32Delay_ms;
- };
- struct ov7740_mode_info {
- enum ov7740_mode mode;
- u32 width;
- u32 height;
- struct reg_value *init_data_ptr;
- u32 init_data_size;
- };
- const char *stringize_mode(u32 mode){
- switch(mode)
- {
- case ov7740_mode_VGA_640_480 :
- return "ov7740_mode_VGA_640_480";
- break;
- case ov7740_mode_QVGA_320_240 :
- return "ov7740_mode_QVGA_320_240";
- break;
- }
- return "Unknown mode";
- }
- const char *stringize_pixelformat(u32 palette){
- switch(palette)
- {
- case V4L2_PIX_FMT_RGB565 :
- return "V4L2_PIX_FMT_RGB565";
- break;
- case V4L2_PIX_FMT_YUYV :
- return "V4L2_PIX_FMT_YUYV";
- break;
- case V4L2_PIX_FMT_YVU420 :
- return "V4L2_PIX_FMT_YVU420";
- break;
- case V4L2_PIX_FMT_YUV420 :
- return "V4L2_PIX_FMT_YUV420";
- break;
- case V4L2_PIX_FMT_YUV422P :
- return "V4L2_PIX_FMT_YUV422P";
- break;
- }
- return "Unknown pixelformat";
- }
- /*!
- * Maintains the information on the current state of the sesor.
- */
- static struct sensor_data ov7740_data;
- //static int pwn_gpio, rst_gpio;
- static struct reg_value ov7740_setting_15fps_QVGA_320_240[] = {
- {0x12,0x80, 0 , 10},
- {0x13,0x00, 0 , 0},
- {0x11,0x03, 0 , 0},
- #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
- {0x12,0x20, 0 , 0},
- #else
- #ifdef USE_RAW
- {0x12,0x01, 0 , 0},
- #else
- {0x12,0x00, 0 , 0}, /* YUYV */
- #endif /* USE_RAW */
- #endif /* USE_BT656 */
- {0xd5,0x10, 0 , 0},
- {0x0c,0x12, 0 , 0}, /* swap to YUYV */
- {0x0d,0x34, 0 , 0},
- {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
- {0x17,0x25, 0 , 0},
- {0x18,0xa0, 0 , 0},
- {0x19,0x03, 0 , 0},
- {0x1a,0xf0, 0 , 0},
- {0x1b,0x89, 0 , 0},
- {0x1e,0x13, 0 , 0},
- {0x22,0x03, 0 , 0},
- {0x29,0x17, 0 , 0},
- {0x2b,0xf8, 0 , 0},
- {0x2c,0x01, 0 , 0},
- {0x31,0x50, 0 , 0},
- {0x32,0x78, 0 , 0},
- {0x33,0xc4, 0 , 0},
- {0x3a,0xb4, 0 , 0},
- {0x36,0x3f, 0 , 0},
- {0x04,0x60, 0 , 0},
- {0x27,0x80, 0 , 0},
- {0x3d,0x0f, 0 , 0},
- {0x3e,0x82, 0 , 0},
- {0x3f,0x40, 0 , 0},
- {0x40,0x7f, 0 , 0},
- {0x41,0x6a, 0 , 0},
- {0x42,0x29, 0 , 0},
- {0x44,0xe5, 0 , 0},
- {0x45,0x41, 0 , 0},
- {0x47,0x42, 0 , 0},
- {0x48,0x00, 0 , 0},
- {0x49,0x61, 0 , 0},
- {0x4a,0xa1, 0 , 0},
- {0x4b,0x46, 0 , 0},
- {0x4c,0x18, 0 , 0},
- {0x4d,0x50, 0 , 0},
- {0x4e,0x13, 0 , 0},
- {0x64,0x00, 0 , 0},
- {0x67,0x88, 0 , 0},
- {0x68,0x1a, 0 , 0},
- {0x14,0x38, 0 , 0},
- {0x24,0x3c, 0 , 0},
- {0x25,0x30, 0 , 0},
- {0x26,0x72, 0 , 0},
- {0x50,0x4c, 0 , 0},
- {0x51,0x3f, 0 , 0},
- {0x52,0x00, 0 , 0},
- {0x53,0x00, 0 , 0},
- {0x20,0x00, 0 , 0},
- {0x21,0x57, 0 , 0},
- {0x38,0x14, 0 , 0},
- {0xe9,0x00, 0 , 0},
- {0x56,0x55, 0 , 0},
- {0x57,0xff, 0 , 0},
- {0x58,0xff, 0 , 0},
- {0x59,0xff, 0 , 0},
- {0x5f,0x04, 0 , 0},
- {0x13,0xff, 0 , 0},
- {0x80,0x7d, 0 , 0},
- {0x81,0x3f, 0 , 0},/* YUV422 enabled */
- {0x82,0x3f, 0 , 0},
- {0x83,0x03, 0 , 0},
- {0x38,0x11, 0 , 0},
- {0x84,0x70, 0 , 0},
- {0x85,0x00, 0 , 0},
- {0x86,0x03, 0 , 0},
- {0x87,0x01, 0 , 0},
- {0x88,0x05, 0 , 0},
- {0x89,0x30, 0 , 0},
- {0x8d,0x30, 0 , 0},
- {0x8f,0x85, 0 , 0},
- {0x93,0x30, 0 , 0},
- {0x95,0x85, 0 , 0},
- {0x99,0x30, 0 , 0},
- {0x9b,0x85, 0 , 0},
- {0x9c,0x08, 0 , 0},
- {0x9d,0x12, 0 , 0},
- {0x9e,0x23, 0 , 0},
- {0x9f,0x45, 0 , 0},
- {0xa0,0x55, 0 , 0},
- {0xa1,0x64, 0 , 0},
- {0xa2,0x72, 0 , 0},
- {0xa3,0x7f, 0 , 0},
- {0xa4,0x8b, 0 , 0},
- {0xa5,0x95, 0 , 0},
- {0xa6,0xa7, 0 , 0},
- {0xa7,0xb5, 0 , 0},
- {0xa8,0xcb, 0 , 0},
- {0xa9,0xdd, 0 , 0},
- {0xaa,0xec, 0 , 0},
- {0xab,0x1a, 0 , 0},
- {0xce,0x78, 0 , 0},
- {0xcf,0x6e, 0 , 0},
- {0xd0,0x0a, 0 , 0},
- {0xd1,0x0c, 0 , 0},
- {0xd2,0x84, 0 , 0},
- {0xd3,0x90, 0 , 0},
- {0xd4,0x1e, 0 , 0},
- {0x5a,0x24, 0 , 0},
- {0x5b,0x1f, 0 , 0},
- {0x5c,0x88, 0 , 0},
- {0x5d,0x60, 0 , 0},
- {0xac,0x6e, 0 , 0},
- {0xbe,0xff, 0 , 0},
- {0xbf,0x00, 0 , 0},
- {0xe5,0x8c, 0 , 0},
- {0x70,0x00, 0 , 0},
- {0x71,0x34, 0 , 0},
- {0x74,0x28, 0 , 0},
- {0x75,0x98, 0 , 0},
- {0x76,0x00, 0 , 0},
- {0x77,0x08, 0 , 0},
- {0x78,0x01, 0 , 0},
- {0x79,0xc2, 0 , 0},
- {0x7d,0x02, 0 , 0},
- {0x7a,0x9c, 0 , 0},
- {0x7b,0x40, 0 , 0},
- {0xec,0x02, 0 , 0},
- {0x7c,0x0c, 0 , 0},
- };
- static struct reg_value ov7740_setting_30fps_QVGA_320_240[] = {
- {0x12,0x80, 0 , 10},
- {0x13,0x00, 0 , 0},
- {0x11,0x01, 0 , 0},
- #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
- {0x12,0x20, 0 , 0},
- #else
- #ifdef USE_RAW
- {0x12,0x01, 0 , 0},
- #else
- {0x12,0x00, 0 , 0}, /* YUYV */
- #endif /* USE_RAW */
- #endif /* USE_BT656 */
- {0xd5,0x10, 0 , 0},
- {0x0c,0x12, 0 , 0}, /* swap to YUYV */
- {0x0d,0x34, 0 , 0},
- {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
- {0x17,0x25, 0 , 0},
- {0x18,0xa0, 0 , 0},
- {0x19,0x03, 0 , 0},
- {0x1a,0xf0, 0 , 0},
- {0x1b,0x89, 0 , 0},
- {0x1e,0x13, 0 , 0},
- {0x22,0x03, 0 , 0},
- {0x29,0x17, 0 , 0},
- {0x2b,0xf8, 0 , 0},
- {0x2c,0x01, 0 , 0},
- {0x31,0x50, 0 , 0},
- {0x32,0x78, 0 , 0},
- {0x33,0xc4, 0 , 0},
- {0x3a,0xb4, 0 , 0},
- {0x36,0x3f, 0 , 0},
- {0x04,0x60, 0 , 0},
- {0x27,0x80, 0 , 0},
- {0x3d,0x0f, 0 , 0},
- {0x3e,0x82, 0 , 0},
- {0x3f,0x40, 0 , 0},
- {0x40,0x7f, 0 , 0},
- {0x41,0x6a, 0 , 0},
- {0x42,0x29, 0 , 0},
- {0x44,0xe5, 0 , 0},
- {0x45,0x41, 0 , 0},
- {0x47,0x42, 0 , 0},
- {0x48,0x00, 0 , 0},
- {0x49,0x61, 0 , 0},
- {0x4a,0xa1, 0 , 0},
- {0x4b,0x46, 0 , 0},
- {0x4c,0x18, 0 , 0},
- {0x4d,0x50, 0 , 0},
- {0x4e,0x13, 0 , 0},
- {0x64,0x00, 0 , 0},
- {0x67,0x88, 0 , 0},
- {0x68,0x1a, 0 , 0},
- {0x14,0x38, 0 , 0},
- {0x24,0x3c, 0 , 0},
- {0x25,0x30, 0 , 0},
- {0x26,0x72, 0 , 0},
- {0x50,0x97, 0 , 0},
- {0x51,0x7e, 0 , 0},
- {0x52,0x00, 0 , 0},
- {0x53,0x00, 0 , 0},
- {0x20,0x00, 0 , 0},
- {0x21,0x23, 0 , 0},
- {0x38,0x14, 0 , 0},
- {0xe9,0x00, 0 , 0},
- {0x56,0x55, 0 , 0},
- {0x57,0xff, 0 , 0},
- {0x58,0xff, 0 , 0},
- {0x59,0xff, 0 , 0},
- {0x5f,0x04, 0 , 0},
- {0x13,0xff, 0 , 0},
- {0x80,0x7d, 0 , 0},
- {0x81,0x3f, 0 , 0},/* YUV422 enabled */
- {0x82,0x3f, 0 , 0},
- {0x83,0x03, 0 , 0},
- {0x38,0x11, 0 , 0},
- {0x84,0x70, 0 , 0},
- {0x85,0x00, 0 , 0},
- {0x86,0x03, 0 , 0},
- {0x87,0x01, 0 , 0},
- {0x88,0x05, 0 , 0},
- {0x89,0x30, 0 , 0},
- {0x8d,0x30, 0 , 0},
- {0x8f,0x85, 0 , 0},
- {0x93,0x30, 0 , 0},
- {0x95,0x85, 0 , 0},
- {0x99,0x30, 0 , 0},
- {0x9b,0x85, 0 , 0},
- {0x9c,0x08, 0 , 0},
- {0x9d,0x12, 0 , 0},
- {0x9e,0x23, 0 , 0},
- {0x9f,0x45, 0 , 0},
- {0xa0,0x55, 0 , 0},
- {0xa1,0x64, 0 , 0},
- {0xa2,0x72, 0 , 0},
- {0xa3,0x7f, 0 , 0},
- {0xa4,0x8b, 0 , 0},
- {0xa5,0x95, 0 , 0},
- {0xa6,0xa7, 0 , 0},
- {0xa7,0xb5, 0 , 0},
- {0xa8,0xcb, 0 , 0},
- {0xa9,0xdd, 0 , 0},
- {0xaa,0xec, 0 , 0},
- {0xab,0x1a, 0 , 0},
- {0xce,0x78, 0 , 0},
- {0xcf,0x6e, 0 , 0},
- {0xd0,0x0a, 0 , 0},
- {0xd1,0x0c, 0 , 0},
- {0xd2,0x84, 0 , 0},
- {0xd3,0x90, 0 , 0},
- {0xd4,0x1e, 0 , 0},
- {0x5a,0x24, 0 , 0},
- {0x5b,0x1f, 0 , 0},
- {0x5c,0x88, 0 , 0},
- {0x5d,0x60, 0 , 0},
- {0xac,0x6e, 0 , 0},
- {0xbe,0xff, 0 , 0},
- {0xbf,0x00, 0 , 0},
- {0xe5,0x8c, 0 , 0},
- {0x70,0x00, 0 , 0},
- {0x71,0x34, 0 , 0},
- {0x74,0x28, 0 , 0},
- {0x75,0x98, 0 , 0},
- {0x76,0x00, 0 , 0},
- {0x77,0x08, 0 , 0},
- {0x78,0x01, 0 , 0},
- {0x79,0xc2, 0 , 0},
- {0x7d,0x02, 0 , 0},
- {0x7a,0x9c, 0 , 0},
- {0x7b,0x40, 0 , 0},
- {0xec,0x02, 0 , 0},
- {0x7c,0x0c, 0 , 0},
- };
- static struct reg_value ov7740_setting_15fps_VGA_640_480[] = {
- {0x12,0x80, 0 , 10},
- {0x13,0x00, 0 , 0},
- {0x11,0x03, 0 , 0},
- #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
- {0x12,0x20, 0 , 0},
- #else
- #ifdef USE_RAW
- {0x12,0x01, 0 , 0},
- #else
- {0x12,0x00, 0 , 0}, /* YUYV */
- #endif /* USE_RAW */
- #endif /* USE_BT656 */
- {0xd5,0x10, 0 , 0},
- {0x0c,0x12, 0 , 0}, /* swap to YUYV */
- {0x0d,0x34, 0 , 0},
- {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
- {0x17,0x25, 0 , 0},
- {0x18,0xa0, 0 , 0},
- {0x19,0x03, 0 , 0},
- {0x1a,0xf0, 0 , 0},
- {0x1b,0x89, 0 , 0},
- {0x1e,0x13, 0 , 0},
- {0x22,0x03, 0 , 0},
- {0x29,0x17, 0 , 0},
- {0x2b,0xf8, 0 , 0},
- {0x2c,0x01, 0 , 0},
- {0x31,0xa0, 0 , 0},
- {0x32,0xf0, 0 , 0},
- {0x33,0xc4, 0 , 0},
- {0x3a,0xb4, 0 , 0},
- {0x36,0x3f, 0 , 0},
- {0x04,0x60, 0 , 0},
- {0x27,0x80, 0 , 0},
- {0x3d,0x0f, 0 , 0},
- {0x3e,0x82, 0 , 0},
- {0x3f,0x40, 0 , 0},
- {0x40,0x7f, 0 , 0},
- {0x41,0x6a, 0 , 0},
- {0x42,0x29, 0 , 0},
- {0x44,0xe5, 0 , 0},
- {0x45,0x41, 0 , 0},
- {0x47,0x42, 0 , 0},
- {0x48,0x00, 0 , 0},
- {0x49,0x61, 0 , 0},
- {0x4a,0xa1, 0 , 0},
- {0x4b,0x46, 0 , 0},
- {0x4c,0x18, 0 , 0},
- {0x4d,0x50, 0 , 0},
- {0x4e,0x13, 0 , 0},
- {0x64,0x00, 0 , 0},
- {0x67,0x88, 0 , 0},
- {0x68,0x1a, 0 , 0},
- {0x14,0x38, 0 , 0},
- {0x24,0x3c, 0 , 0},
- {0x25,0x30, 0 , 0},
- {0x26,0x72, 0 , 0},
- {0x50,0x4c, 0 , 0},
- {0x51,0x3f, 0 , 0},
- {0x52,0x00, 0 , 0},
- {0x53,0x00, 0 , 0},
- {0x20,0x00, 0 , 0},
- {0x21,0x57, 0 , 0},
- {0x38,0x14, 0 , 0},
- {0xe9,0x00, 0 , 0},
- {0x56,0x55, 0 , 0},
- {0x57,0xff, 0 , 0},
- {0x58,0xff, 0 , 0},
- {0x59,0xff, 0 , 0},
- {0x5f,0x04, 0 , 0},
- {0x13,0xff, 0 , 0},
- {0x80,0x7d, 0 , 0},
- {0x81,0x3f, 0 , 0},/* YUV422 enabled */
- {0x82,0x32, 0 , 0},
- {0x83,0x03, 0 , 0},
- {0x38,0x11, 0 , 0},
- {0x84,0x70, 0 , 0},
- {0x85,0x00, 0 , 0},
- {0x86,0x03, 0 , 0},
- {0x87,0x01, 0 , 0},
- {0x88,0x05, 0 , 0},
- {0x89,0x30, 0 , 0},
- {0x8d,0x30, 0 , 0},
- {0x8f,0x85, 0 , 0},
- {0x93,0x30, 0 , 0},
- {0x95,0x85, 0 , 0},
- {0x99,0x30, 0 , 0},
- {0x9b,0x85, 0 , 0},
- {0x9c,0x08, 0 , 0},
- {0x9d,0x12, 0 , 0},
- {0x9e,0x23, 0 , 0},
- {0x9f,0x45, 0 , 0},
- {0xa0,0x55, 0 , 0},
- {0xa1,0x64, 0 , 0},
- {0xa2,0x72, 0 , 0},
- {0xa3,0x7f, 0 , 0},
- {0xa4,0x8b, 0 , 0},
- {0xa5,0x95, 0 , 0},
- {0xa6,0xa7, 0 , 0},
- {0xa7,0xb5, 0 , 0},
- {0xa8,0xcb, 0 , 0},
- {0xa9,0xdd, 0 , 0},
- {0xaa,0xec, 0 , 0},
- {0xab,0x1a, 0 , 0},
- {0xce,0x78, 0 , 0},
- {0xcf,0x6e, 0 , 0},
- {0xd0,0x0a, 0 , 0},
- {0xd1,0x0c, 0 , 0},
- {0xd2,0x84, 0 , 0},
- {0xd3,0x90, 0 , 0},
- {0xd4,0x1e, 0 , 0},
- {0x5a,0x24, 0 , 0},
- {0x5b,0x1f, 0 , 0},
- {0x5c,0x88, 0 , 0},
- {0x5d,0x60, 0 , 0},
- {0xac,0x6e, 0 , 0},
- {0xbe,0xff, 0 , 0},
- {0xbf,0x00, 0 , 0},
- {0x70,0x00, 0 , 0},
- {0x71,0x34, 0 , 0},
- {0x74,0x28, 0 , 0},
- {0x75,0x98, 0 , 0},
- {0x76,0x00, 0 , 0},
- {0x77,0x08, 0 , 0},
- {0x78,0x01, 0 , 0},
- {0x79,0xc2, 0 , 0},
- {0x7d,0x02, 0 , 0},
- {0x7a,0x9c, 0 , 0},
- {0x7b,0x40, 0 , 0},
- {0xec,0x82, 0 , 0},
- {0x7c,0x0c, 0 , 0},
- };
- //default one
- static struct reg_value ov7740_setting_30fps_VGA_640_480[] = {
- {0x12,0x80, 0 , 10},
- {0x13,0x00, 0 , 0},
- {0x11,0x01, 0 , 0},
- #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
- {0x12,0x20, 0 , 0},
- #else
- #ifdef USE_RAW
- {0x12,0x01, 0 , 0},
- #else
- {0x12,0x00, 0 , 0}, /* YUYV */
- #endif /* USE_RAW */
- #endif /* USE_BT656 */
- {0xd5,0x10, 0 , 0},
- {0x0c,0x12, 0 , 0}, /* swap to YUYV */
- {0x0d,0x34, 0 , 0},
- {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
- {0x17,0x25, 0 , 0},
- {0x18,0xa0, 0 , 0},
- {0x19,0x03, 0 , 0},
- {0x1a,0xf0, 0 , 0},
- {0x1b,0x89, 0 , 0},
- {0x1e,0x13, 0 , 0},
- {0x22,0x03, 0 , 0},
- {0x29,0x17, 0 , 0},
- {0x2b,0xf8, 0 , 0},
- {0x2c,0x01, 0 , 0},
- {0x31,0xa0, 0 , 0},
- {0x32,0xf0, 0 , 0},
- {0x33,0xc4, 0 , 0},
- {0x3a,0xb4, 0 , 0},
- {0x36,0x3f, 0 , 0},
- {0x04,0x60, 0 , 0},
- {0x27,0x80, 0 , 0},
- {0x3d,0x0f, 0 , 0},
- {0x3e,0x82, 0 , 0},
- {0x3f,0x40, 0 , 0},
- {0x40,0x7f, 0 , 0},
- {0x41,0x6a, 0 , 0},
- {0x42,0x29, 0 , 0},
- {0x44,0xe5, 0 , 0},
- {0x45,0x41, 0 , 0},
- {0x47,0x42, 0 , 0},
- {0x48,0x00, 0 , 0},
- {0x49,0x61, 0 , 0},
- {0x4a,0xa1, 0 , 0},
- {0x4b,0x46, 0 , 0},
- {0x4c,0x18, 0 , 0},
- {0x4d,0x50, 0 , 0},
- {0x4e,0x13, 0 , 0},
- {0x64,0x00, 0 , 0},
- {0x67,0x88, 0 , 0},
- {0x68,0x1a, 0 , 0},
- {0x14,0x38, 0 , 0},
- {0x24,0x3c, 0 , 0},
- {0x25,0x30, 0 , 0},
- {0x26,0x72, 0 , 0},
- {0x50,0x97, 0 , 0},
- {0x51,0x7e, 0 , 0},
- {0x52,0x00, 0 , 0},
- {0x53,0x00, 0 , 0},
- {0x20,0x00, 0 , 0},
- {0x21,0x23, 0 , 0},
- {0x38,0x14, 0 , 0},
- {0xe9,0x00, 0 , 0},
- {0x56,0x55, 0 , 0},
- {0x57,0xff, 0 , 0},
- {0x58,0xff, 0 , 0},
- {0x59,0xff, 0 , 0},
- {0x5f,0x04, 0 , 0},
- {0x13,0xff, 0 , 0},
- {0x80,0x7d, 0 , 0},
- {0x81,0x3f, 0 , 0},/* YUV422 enabled */
- {0x82,0x32, 0 , 0},
- {0x83,0x03, 0 , 0},
- {0x38,0x11, 0 , 0},
- {0x84,0x70, 0 , 0},
- {0x85,0x00, 0 , 0},
- {0x86,0x03, 0 , 0},
- {0x87,0x01, 0 , 0},
- {0x88,0x05, 0 , 0},
- {0x89,0x30, 0 , 0},
- {0x8d,0x30, 0 , 0},
- {0x8f,0x85, 0 , 0},
- {0x93,0x30, 0 , 0},
- {0x95,0x85, 0 , 0},
- {0x99,0x30, 0 , 0},
- {0x9b,0x85, 0 , 0},
- {0x9c,0x08, 0 , 0},
- {0x9d,0x12, 0 , 0},
- {0x9e,0x23, 0 , 0},
- {0x9f,0x45, 0 , 0},
- {0xa0,0x55, 0 , 0},
- {0xa1,0x64, 0 , 0},
- {0xa2,0x72, 0 , 0},
- {0xa3,0x7f, 0 , 0},
- {0xa4,0x8b, 0 , 0},
- {0xa5,0x95, 0 , 0},
- {0xa6,0xa7, 0 , 0},
- {0xa7,0xb5, 0 , 0},
- {0xa8,0xcb, 0 , 0},
- {0xa9,0xdd, 0 , 0},
- {0xaa,0xec, 0 , 0},
- {0xab,0x1a, 0 , 0},
- {0xce,0x78, 0 , 0},
- {0xcf,0x6e, 0 , 0},
- {0xd0,0x0a, 0 , 0},
- {0xd1,0x0c, 0 , 0},
- {0xd2,0x84, 0 , 0},
- {0xd3,0x90, 0 , 0},
- {0xd4,0x1e, 0 , 0},
- {0x5a,0x24, 0 , 0},
- {0x5b,0x1f, 0 , 0},
- {0x5c,0x88, 0 , 0},
- {0x5d,0x60, 0 , 0},
- {0xac,0x6e, 0 , 0},
- {0xbe,0xff, 0 , 0},
- {0xbf,0x00, 0 , 0},
- {0x70,0x00, 0 , 0},
- {0x71,0x34, 0 , 0},
- {0x74,0x28, 0 , 0},
- {0x75,0x98, 0 , 0},
- {0x76,0x00, 0 , 0},
- {0x77,0x08, 0 , 0},
- {0x78,0x01, 0 , 0},
- {0x79,0xc2, 0 , 0},
- {0x7d,0x02, 0 , 0},
- {0x7a,0x9c, 0 , 0},
- {0x7b,0x40, 0 , 0},
- {0xec,0x82, 0 , 0},
- {0x7c,0x0c, 0 , 0},
- };
- static struct ov7740_mode_info ov7740_mode_info_data[2][ov7740_mode_MAX + 1] = {
- {
- {ov7740_mode_VGA_640_480, 640, 480,
- ov7740_setting_15fps_VGA_640_480,
- ARRAY_SIZE(ov7740_setting_15fps_VGA_640_480)},
- {ov7740_mode_QVGA_320_240, 320, 240,
- ov7740_setting_15fps_QVGA_320_240,
- ARRAY_SIZE(ov7740_setting_15fps_QVGA_320_240)},
- },
- {
- {ov7740_mode_VGA_640_480, 640, 480,
- ov7740_setting_30fps_VGA_640_480,
- ARRAY_SIZE(ov7740_setting_30fps_VGA_640_480)},
- {ov7740_mode_QVGA_320_240, 320, 240,
- ov7740_setting_30fps_QVGA_320_240,
- ARRAY_SIZE(ov7740_setting_30fps_QVGA_320_240)},
- },
- };
- static struct regulator *io_regulator;
- static struct regulator *core_regulator;
- static struct regulator *analog_regulator;
- static struct regulator *gpo_regulator;
- static int ov7740_probe(struct i2c_client *adapter,
- const struct i2c_device_id *device_id);
- static int ov7740_remove(struct i2c_client *client);
- static s32 ov7740_read_reg(u16 reg, u8 *val);
- static s32 ov7740_write_reg(u16 reg, u8 val);
- static const struct i2c_device_id ov7740_id[] = {
- {"ov7740", 0},
- {"ov564x", 0},
- {},
- };
- MODULE_DEVICE_TABLE(i2c, ov7740_id);
- static struct i2c_driver ov7740_i2c_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "ov7740",
- },
- .probe = ov7740_probe,
- .remove = ov7740_remove,
- .id_table = ov7740_id,
- };
- static void ov7740_standby(s32 enable)
- {
- return ;
- }
- static void ov7740_reset(void)
- {
- return ;
- }
- static int ov7740_power_on(struct device *dev)
- {
- return 0;
- }
- /*!
- * ovx_write_reg I2C write function
- *
- * @param reg : register to write
- * @param value : value to write
- * @return Error code indicating success or failure
- */
- static s32 ov7740_write_reg(u16 reg, u8 val)
- {
- u8 au8Buf[2] = {0};
- if(reg > 0xff){
- pr_info("%s: register too high :0x%02x\n",__func__,reg);
- return -1;
- }
- au8Buf[0] = reg & 0xff;
- au8Buf[1] = val;
- if (i2c_master_send(ov7740_data.i2c_client, au8Buf, 2) < 0) {
- pr_err("%s:write reg error:reg=%x,val=%x\n",
- __func__, reg, val);
- return -1;
- }
- return 0;
- }
- /*!
- * ovx_read_reg I2C write function
- *
- * @param reg : register to read
- * @param value : value read, -1 if no value is read
- * @return Error code indicating success or failure
- */
- static s32 ov7740_read_reg(u16 reg, u8 *value)
- {
- int returned = 0;
- u8 au8RegBuf[1] = {0};
- u8 u8RdVal = 0;
- if(reg > 0xff){
- pr_info("%s: register too high :0x%02x\n",__func__,reg);
- return -1;
- }
- au8RegBuf[0] = reg & 0xff;
- returned = i2c_master_send(ov7740_data.i2c_client, au8RegBuf, 1);
- if (1 != returned) {
- pr_err("%s:write reg error:reg=%x error:%d\n",
- __func__, reg,returned);
- return -1;
- }
- if (1 != i2c_master_recv(ov7740_data.i2c_client, &u8RdVal, 1)) {
- pr_err("%s:read reg error:reg=%x,val=%x\n",
- __func__, reg, u8RdVal);
- return -1;
- }
- *value = u8RdVal;
- return u8RdVal;
- }
- static int ov7740_init_mode(enum ov7740_frame_rate frame_rate,
- enum ov7740_mode mode)
- {
- struct reg_value *pModeSetting = NULL;
- s32 i = 0;
- s32 iModeSettingArySize = 0;
- register u32 Delay_ms = 0;
- register u16 RegAddr = 0;
- register u8 Mask = 0;
- register u8 Val = 0;
- u8 RegVal = 0;
- int retval = 0;
- pr_info("%s mode is %s and framerate is %d\n",__func__,stringize_mode(mode),ov7740_framerates[frame_rate]);
- if (mode > ov7740_mode_MAX || mode < ov7740_mode_MIN) {
- pr_err("Wrong ov7740 mode detected!\n");
- return -1;
- }
- pModeSetting = ov7740_mode_info_data[frame_rate][mode].init_data_ptr;
- iModeSettingArySize =
- ov7740_mode_info_data[frame_rate][mode].init_data_size;
- ov7740_data.pix.width = ov7740_mode_info_data[frame_rate][mode].width;
- ov7740_data.pix.height = ov7740_mode_info_data[frame_rate][mode].height;
- pr_info("%s use w:%d, h:%d\n",__func__,ov7740_data.pix.width,ov7740_data.pix.height);
- if (ov7740_data.pix.width == 0 || ov7740_data.pix.height == 0 ||
- pModeSetting == NULL || iModeSettingArySize == 0)
- return -EINVAL;
- for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
- Delay_ms = pModeSetting->u32Delay_ms;
- RegAddr = pModeSetting->u16RegAddr;
- Val = pModeSetting->u8Val;
- Mask = pModeSetting->u8Mask;
- if (Mask) {
- retval = ov7740_read_reg(RegAddr, &RegVal);
- if (retval < 0) {
- pr_err("read reg error addr=0x%x", RegAddr);
- goto err;
- }
- RegVal &= ~(u8)Mask;
- Val &= Mask;
- Val |= RegVal;
- }
- retval = ov7740_write_reg(RegAddr, Val);
- if (retval < 0) {
- pr_err("write reg error addr=0x%x", RegAddr);
- goto err;
- }
- if (Delay_ms)
- msleep(Delay_ms);
- }
- err:
- return retval;
- }
- /* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
- /***********************************************************************
- * IOCTL Functions from v4l2_int_ioctl_desc.
- ***********************************************************************/
- /*!
- * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
- * s: pointer to standard V4L2 device structure
- * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
- *
- * Gets slave interface parameters.
- * Calculates the required xclk value to support the requested
- * clock parameters in p. This value is returned in the p
- * parameter.
- *
- * vidioc_int_g_ifparm returns platform-specific information about the
- * interface settings used by the sensor.
- *
- * Called on open.
- */
- static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
- {
- pr_info("%s start\n",__func__);
- if (s == NULL) {
- pr_err(" ERROR!! no slave device set!\n");
- return -1;
- }
- memset(p, 0, sizeof(*p));
- p->if_type = V4L2_IF_TYPE_BT656;
- p->u.bt656.latch_clk_inv = 1;//data sur front montant de pixclk
- p->u.bt656.swap = 0;//if 1 it is for test
- #ifdef USE_BT656
- //IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE
- pr_info("Use BT656 progressive synchronization code\n");
- p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_BT_8BIT;
- p->u.bt656.bt_sync_correct = 0; /* 1 Indicate external vsync */
- p->u.bt656.clock_curr = 0;//in mxc_v4l2_capture
- #else
- pr_info("Not using BT656 synchronization code\n");
- p->u.bt656.frame_start_on_rising_vs = 1;/* Not handled by imx */
- p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
- p->u.bt656.latch_clk_inv = 0; /* 1 : clock on falling edge */
- p->u.bt656.nobt_hs_inv = 0;
- p->u.bt656.nobt_vs_inv = 0;
- p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
- /* p->u.bt656.clock_curr = ov7740_data.mclk; external clock */
- #if 0
- ov7740_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */
- #endif
- #endif
- pr_info(" clock_curr=mclk=%d\n", ov7740_data.mclk);
- p->u.bt656.clock_min = OV7740_XCLK_MIN;
- p->u.bt656.clock_max = OV7740_XCLK_MAX;
- return 0;
- }
- /*!
- * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
- * @s: pointer to standard V4L2 device structure
- * @on: indicates power mode (on or off)
- *
- * Turns the power on or off, depending on the value of on and returns the
- * appropriate error code.
- */
- static int ioctl_s_power(struct v4l2_int_device *s, int on)
- {
- struct sensor_data *sensor = s->priv;
- if (on && !sensor->on) {
- if (io_regulator)
- if (regulator_enable(io_regulator) != 0)
- return -EIO;
- if (core_regulator)
- if (regulator_enable(core_regulator) != 0)
- return -EIO;
- if (gpo_regulator)
- if (regulator_enable(gpo_regulator) != 0)
- return -EIO;
- if (analog_regulator)
- if (regulator_enable(analog_regulator) != 0)
- return -EIO;
- /* Make sure power on */
- ov7740_standby(0);
- } else if (!on && sensor->on) {
- if (analog_regulator)
- regulator_disable(analog_regulator);
- if (core_regulator)
- regulator_disable(core_regulator);
- if (io_regulator)
- regulator_disable(io_regulator);
- if (gpo_regulator)
- regulator_disable(gpo_regulator);
- ov7740_standby(1);
- }
- sensor->on = on;
- return 0;
- }
- /*!
- * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- * @s: pointer to standard V4L2 device structure
- * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- *
- * Returns the sensor's video CAPTURE parameters.
- */
- static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- {
- struct sensor_data *sensor = s->priv;
- struct v4l2_captureparm *cparm = &a->parm.capture;
- int ret = 0;
- pr_info("%s start\n",__func__);
- switch (a->type) {
- /* This is the only case currently handled. */
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- memset(a, 0, sizeof(*a));
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- cparm->capability = sensor->streamcap.capability;
- cparm->timeperframe = sensor->streamcap.timeperframe;
- cparm->capturemode = sensor->streamcap.capturemode;
- ret = 0;
- break;
- /* These are all the possible cases. */
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- case V4L2_BUF_TYPE_VBI_OUTPUT:
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- ret = -EINVAL;
- break;
- default:
- pr_info(" type is unknown - %d\n", a->type);
- ret = -EINVAL;
- break;
- }
- return ret;
- }
- /*!
- * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- * @s: pointer to standard V4L2 device structure
- * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- *
- * Configures the sensor to use the input parameters, if possible. If
- * not possible, reverts to the old parameters and returns the
- * appropriate error code.
- */
- static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- {
- struct sensor_data *sensor = s->priv;
- struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
- u32 tgt_fps, old_fps; /* target frames per secound */
- enum ov7740_frame_rate new_frame_rate, old_frame_rate;
- int ret = 0;
- /* Make sure power on */
- ov7740_standby(0);
- pr_info("%s start\n",__func__);
- switch (a->type) {
- /* This is the only case currently handled. */
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- /* Check that the new frame rate is allowed. */
- if ((timeperframe->numerator == 0) ||
- (timeperframe->denominator == 0)) {
- timeperframe->denominator = DEFAULT_FPS;
- timeperframe->numerator = 1;
- }
- tgt_fps = timeperframe->denominator /
- timeperframe->numerator;
- if (tgt_fps > MAX_FPS) {
- timeperframe->denominator = MAX_FPS;
- timeperframe->numerator = 1;
- } else if (tgt_fps < MIN_FPS) {
- timeperframe->denominator = MIN_FPS;
- timeperframe->numerator = 1;
- }
- /* Actual frame rate we use */
- tgt_fps = timeperframe->denominator /
- timeperframe->numerator;
- if (tgt_fps == 15)
- new_frame_rate = ov7740_15_fps;
- else if (tgt_fps == 30)
- new_frame_rate = ov7740_30_fps;
- else {
- pr_err(" The camera frame rate is not supported!\n");
- return -EINVAL;
- }
- if (sensor->streamcap.timeperframe.numerator != 0)
- old_fps = sensor->streamcap.timeperframe.denominator /
- sensor->streamcap.timeperframe.numerator;
- else
- old_fps = 30;
- if (old_fps == 15)
- old_frame_rate = ov7740_15_fps;
- else if (old_fps == 30)
- old_frame_rate = ov7740_30_fps;
- else
- old_frame_rate = ov7740_30_fps;
- ret = ov7740_init_mode(new_frame_rate,
- sensor->streamcap.capturemode);
- if (ret < 0)
- return ret;
- sensor->streamcap.timeperframe = *timeperframe;
- sensor->streamcap.capturemode =
- (u32)a->parm.capture.capturemode;
- break;
- /* These are all the possible cases. */
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- case V4L2_BUF_TYPE_VBI_OUTPUT:
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- pr_info(" type is not " \
- "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
- a->type);
- ret = -EINVAL;
- break;
- default:
- pr_info(" type is unknown - %d\n", a->type);
- ret = -EINVAL;
- break;
- }
- return ret;
- }
- /*!
- * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
- * @s: pointer to standard V4L2 device structure
- * @f: pointer to standard V4L2 v4l2_format structure
- *
- * Returns the sensor's current pixel format in the v4l2_format
- * parameter.
- */
- static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
- {
- struct sensor_data *sensor = s->priv;
- pr_info("%s start\n",__func__);
- f->fmt.pix = sensor->pix;
- return 0;
- }
- /*!
- * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
- * @s: pointer to standard V4L2 device structure
- * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
- *
- * If the requested control is supported, returns the control's current
- * value from the video_control[] array. Otherwise, returns -EINVAL
- * if the control is not supported.
- */
- static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- {
- int ret = 0;
- switch (vc->id) {
- case V4L2_CID_BRIGHTNESS:
- vc->value = ov7740_data.brightness;
- break;
- case V4L2_CID_HUE:
- vc->value = ov7740_data.hue;
- break;
- case V4L2_CID_CONTRAST:
- vc->value = ov7740_data.contrast;
- break;
- case V4L2_CID_SATURATION:
- vc->value = ov7740_data.saturation;
- break;
- case V4L2_CID_RED_BALANCE:
- vc->value = ov7740_data.red;
- break;
- case V4L2_CID_BLUE_BALANCE:
- vc->value = ov7740_data.blue;
- break;
- case V4L2_CID_EXPOSURE:
- vc->value = ov7740_data.ae_mode;
- break;
- default:
- ret = -EINVAL;
- }
- return ret;
- }
- /*!
- * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
- * @s: pointer to standard V4L2 device structure
- * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
- *
- * If the requested control is supported, sets the control's current
- * value in HW (and updates the video_control[] array). Otherwise,
- * returns -EINVAL if the control is not supported.
- */
- static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- {
- int retval = 0;
- pr_info("In ov7740:ioctl_s_ctrl %d\n",
- vc->id);
- switch (vc->id) {
- case V4L2_CID_BRIGHTNESS:
- break;
- case V4L2_CID_CONTRAST:
- break;
- case V4L2_CID_SATURATION:
- break;
- case V4L2_CID_HUE:
- break;
- case V4L2_CID_AUTO_WHITE_BALANCE:
- break;
- case V4L2_CID_DO_WHITE_BALANCE:
- break;
- case V4L2_CID_RED_BALANCE:
- break;
- case V4L2_CID_BLUE_BALANCE:
- break;
- case V4L2_CID_GAMMA:
- break;
- case V4L2_CID_EXPOSURE:
- break;
- case V4L2_CID_AUTOGAIN:
- break;
- case V4L2_CID_GAIN:
- break;
- case V4L2_CID_HFLIP:
- break;
- case V4L2_CID_VFLIP:
- break;
- case V4L2_CID_MXC_ROT:
- case V4L2_CID_MXC_VF_ROT:
- break;
- default:
- retval = -EPERM;
- break;
- }
- return retval;
- }
- /*!
- * ioctl_enum_framesizes - V4L2 sensor interface handler for
- * VIDIOC_ENUM_FRAMESIZES ioctl
- * @s: pointer to standard V4L2 device structure
- * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
- static int ioctl_enum_framesizes(struct v4l2_int_device *s,
- struct v4l2_frmsizeenum *fsize)
- {
- if (fsize->index > ov7740_mode_MAX)
- return -EINVAL;
- fsize->pixel_format = ov7740_data.pix.pixelformat;
- fsize->discrete.width =
- max(ov7740_mode_info_data[0][fsize->index].width,
- ov7740_mode_info_data[1][fsize->index].width);
- fsize->discrete.height =
- max(ov7740_mode_info_data[0][fsize->index].height,
- ov7740_mode_info_data[1][fsize->index].height);
- pr_info("%s get w:%d, h:%d, pixelformat:%s\n",__func__,fsize->discrete.width,fsize->discrete.height,stringize_pixelformat(fsize->pixel_format));
- return 0;
- }
- /*!
- * ioctl_enum_frameintervals - V4L2 sensor interface handler for
- * VIDIOC_ENUM_FRAMEINTERVALS ioctl
- * @s: pointer to standard V4L2 device structure
- * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
- static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
- struct v4l2_frmivalenum *fival)
- {
- int i, j, count;
- if (fival->index < 0 || fival->index > ov7740_mode_MAX)
- return -EINVAL;
- if (fival->pixel_format == 0 || fival->width == 0 ||
- fival->height == 0) {
- pr_warning("Please assign pixelformat, width and height.\n");
- return -EINVAL;
- }
- fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
- fival->discrete.numerator = 1;
- count = 0;
- for (i = 0; i < ARRAY_SIZE(ov7740_mode_info_data); i++) {
- for (j = 0; j < (ov7740_mode_MAX + 1); j++) {
- if (fival->pixel_format == ov7740_data.pix.pixelformat
- && fival->width == ov7740_mode_info_data[i][j].width
- && fival->height == ov7740_mode_info_data[i][j].height
- && ov7740_mode_info_data[i][j].init_data_ptr != NULL) {
- count++;
- }
- if (fival->index == (count - 1)) {
- fival->discrete.denominator =
- ov7740_framerates[i];
- return 0;
- }
- }
- }
- pr_info("%s get numerator:%d, denominator:%d\n",__func__,fival->discrete.numerator,fival->discrete.denominator);
- return -EINVAL;
- }
- /*!
- * ioctl_g_chip_ident - V4L2 sensor interface handler for
- * VIDIOC_DBG_G_CHIP_IDENT ioctl
- * @s: pointer to standard V4L2 device structure
- * @id: pointer to int
- *
- * Return 0.
- */
- static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
- {
- ((struct v4l2_dbg_chip_ident *)id)->match.type =
- V4L2_CHIP_MATCH_I2C_DRIVER;
- strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov7740_camera");
- return 0;
- }
- /*!
- * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
- * @s: pointer to standard V4L2 device structure
- */
- static int ioctl_init(struct v4l2_int_device *s)
- {
- return 0;
- }
- /*!
- * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
- * @s: pointer to standard V4L2 device structure
- * @fmt: pointer to standard V4L2 fmt description structure
- *
- * Return 0.
- */
- static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
- struct v4l2_fmtdesc *fmt)
- {
- if (fmt->index > 0) /* only 1 pixelformat support so far */
- return -EINVAL;
- fmt->pixelformat = ov7740_data.pix.pixelformat;
- return 0;
- }
- /*!
- * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
- * @s: pointer to standard V4L2 device structure
- *
- * Initialise the device when slave attaches to the master.
- */
- static int ioctl_dev_init(struct v4l2_int_device *s)
- {
- struct sensor_data *sensor = s->priv;
- u32 tgt_xclk; /* target xclk */
- u32 tgt_fps; /* target frames per secound */
- enum ov7740_frame_rate frame_rate;
- ov7740_data.on = true;
- /* mclk */
- tgt_xclk = ov7740_data.mclk;
- tgt_xclk = min(tgt_xclk, (u32)OV7740_XCLK_MAX);
- tgt_xclk = max(tgt_xclk, (u32)OV7740_XCLK_MIN);
- ov7740_data.mclk = tgt_xclk;
- pr_info(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
- /* Default camera frame rate is set in probe */
- tgt_fps = sensor->streamcap.timeperframe.denominator /
- sensor->streamcap.timeperframe.numerator;
- if (tgt_fps == 15)
- frame_rate = ov7740_15_fps;
- else if (tgt_fps == 30){
- frame_rate = ov7740_30_fps;
- }
- else
- return -EINVAL; /* Only support 15fps or 30fps now. */
- return ov7740_init_mode(frame_rate,sensor->streamcap.capturemode);
- }
- /*!
- * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
- * @s: pointer to standard V4L2 device structure
- *
- * Delinitialise the device when slave detaches to the master.
- */
- static int ioctl_dev_exit(struct v4l2_int_device *s)
- {
- return 0;
- }
- /*!
- * This structure defines all the ioctls for this module and links them to the
- * enumeration.
- */
- static struct v4l2_int_ioctl_desc ov7740_ioctl_desc[] = {
- { vidioc_int_dev_init_num,
- (v4l2_int_ioctl_func *)ioctl_dev_init },
- { vidioc_int_dev_exit_num, ioctl_dev_exit},
- { vidioc_int_s_power_num,
- (v4l2_int_ioctl_func *)ioctl_s_power },
- { vidioc_int_g_ifparm_num,
- (v4l2_int_ioctl_func *)ioctl_g_ifparm },
- /* { vidioc_int_g_needs_reset_num,
- (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, */
- /* { vidioc_int_reset_num,
- (v4l2_int_ioctl_func *)ioctl_reset }, */
- { vidioc_int_init_num,
- (v4l2_int_ioctl_func *)ioctl_init },
- { vidioc_int_enum_fmt_cap_num,
- (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
- /* { vidioc_int_try_fmt_cap_num,
- (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, */
- { vidioc_int_g_fmt_cap_num,
- (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
- /* { vidioc_int_s_fmt_cap_num,
- (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, */
- { vidioc_int_g_parm_num,
- (v4l2_int_ioctl_func *)ioctl_g_parm },
- { vidioc_int_s_parm_num,
- (v4l2_int_ioctl_func *)ioctl_s_parm },
- /* { vidioc_int_queryctrl_num,
- (v4l2_int_ioctl_func *)ioctl_queryctrl }, */
- { vidioc_int_g_ctrl_num,
- (v4l2_int_ioctl_func *)ioctl_g_ctrl },
- { vidioc_int_s_ctrl_num,
- (v4l2_int_ioctl_func *)ioctl_s_ctrl },
- { vidioc_int_enum_framesizes_num,
- (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
- { vidioc_int_enum_frameintervals_num,
- (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
- { vidioc_int_g_chip_ident_num,
- (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
- };
- static struct v4l2_int_slave ov7740_slave = {
- .ioctls = ov7740_ioctl_desc,
- .num_ioctls = ARRAY_SIZE(ov7740_ioctl_desc),
- };
- static struct v4l2_int_device ov7740_int_device = {
- .module = THIS_MODULE,
- .name = "ov7740",
- .type = v4l2_int_type_slave,
- .u = {
- .slave = &ov7740_slave,
- },
- };
- /*!
- * ov7740 I2C probe function
- *
- * @param adapter struct i2c_adapter *
- * @return Error code indicating success or failure
- */
- static int ov7740_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
- {
- struct pinctrl *pinctrl;
- struct device *dev = &client->dev;
- int retval;
- u8 chip_id_high, chip_id_low;
- /* ov7740 pinctrl */
- pinctrl = devm_pinctrl_get_select_default(dev);
- if (IS_ERR(pinctrl)) {
- dev_err(dev, "ov7740 setup pinctrl failed!");
- return PTR_ERR(pinctrl);
- }
- #if 0
- /* request power down pin */
- pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
- if (!gpio_is_valid(pwn_gpio)) {
- dev_warn(dev, "no sensor pwdn pin available");
- return -EINVAL;
- }
- retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
- "ov7740_pwdn");
- if (retval < 0)
- return retval;
- /* request reset pin */
- rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
- if (!gpio_is_valid(rst_gpio)) {
- dev_warn(dev, "no sensor reset pin available");
- return -EINVAL;
- }
- retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
- "ov7740_reset");
- if (retval < 0)
- return retval;
- #endif
- /* Set initial values for the sensor struct. */
- memset(&ov7740_data, 0, sizeof(ov7740_data));
- ov7740_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
- if (IS_ERR(ov7740_data.sensor_clk)) {
- /* assuming clock enabled by default */
- ov7740_data.sensor_clk = NULL;
- dev_err(dev, "clock-frequency missing or invalid\n");
- return PTR_ERR(ov7740_data.sensor_clk);
- }
- retval = of_property_read_u32(dev->of_node, "mclk",
- (u32 *) &(ov7740_data.mclk));
- if (retval) {
- dev_err(dev, "mclk missing or invalid\n");
- return retval;
- }
- //#define FORCE_27MHZ
- #ifdef FORCE_27MHZ
- ov7740_data.mclk = 27000000; /* Not working ... */
- #endif
- pr_info("Using mclk to %d Hz\n",ov7740_data.mclk);
- retval = of_property_read_u32(dev->of_node, "mclk_source",
- (u32 *) &(ov7740_data.mclk_source));
- if (retval) {
- dev_err(dev, "mclk_source missing or invalid\n");
- return retval;
- }
- pr_info("Using mclk_source to %d\n",ov7740_data.mclk_source);
- retval = of_property_read_u32(dev->of_node, "csi_id",
- &(ov7740_data.csi));
- if (retval) {
- dev_err(dev, "csi_id missing or invalid\n");
- return retval;
- }
- clk_prepare_enable(ov7740_data.sensor_clk);
- ov7740_data.io_init = ov7740_reset;
- ov7740_data.i2c_client = client;
- #ifdef USE_RAW
- ov7740_data.pix.pixelformat = V4L2_PIX_FMT_RGB565;
- #else
- #if 1
- ov7740_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; /* Changed by register 0x0c set 0x12 for YUYV */
- #else
- ov7740_data.pix.pixelformat = V4L2_PIX_FMT_YUV420;
- /* ov7740_data.pix.pixelformat = V4L2_PIX_FMT_YUV422P; */
- #endif
- #endif
- pr_info("Using %s pixelformat\n",stringize_pixelformat(ov7740_data.pix.pixelformat));
- ov7740_data.pix.width = 640;
- ov7740_data.pix.height = 480;
- #if 0
- /* https://community.freescale.com/thread/328880 */
- ov7740_data.pix.priv = 0; /* 1 : indicate TV in format */
- #endif
- /* V4L2_CAP_TIMEPERFRAME which indicates that the device can vary its frame rate */
- /* V4L2_MODE_HIGHQUALITY, intended to put the hardware into a high-quality mode suitable for single-frame captures */
- ov7740_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
- V4L2_CAP_TIMEPERFRAME;
- ov7740_data.streamcap.capturemode = 0;
- ov7740_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
- ov7740_data.streamcap.timeperframe.numerator = 1;
- ov7740_power_on(&client->dev);
- ov7740_reset();
- ov7740_standby(0);
- retval = ov7740_read_reg(OV7740_CHIP_ID_HIGH_BYTE, &chip_id_high);
- if (retval < 0 || chip_id_high != OV7740_CHIP_ID_HIGH_BYTE_READ) {
- pr_warning("camera ov7740 is not found\n");
- clk_disable_unprepare(ov7740_data.sensor_clk);
- return -ENODEV;
- }
- retval = ov7740_read_reg(OV7740_CHIP_ID_LOW_BYTE, &chip_id_low);
- if (retval < 0 || chip_id_low != OV7740_CHIP_ID_LOW_BYTE_READ) {
- pr_warning("camera ov7740 is not found\n");
- clk_disable_unprepare(ov7740_data.sensor_clk);
- return -ENODEV;
- }
- ov7740_standby(1);
- ov7740_int_device.priv = &ov7740_data;
- retval = v4l2_int_device_register(&ov7740_int_device);
- pr_info("camera ov7740 is found\n");
- return retval;
- }
- /*!
- * ov7740 I2C detach function
- *
- * @param client struct i2c_client *
- * @return Error code indicating success or failure
- */
- static int ov7740_remove(struct i2c_client *client)
- {
- v4l2_int_device_unregister(&ov7740_int_device);
- //TODO
- //clk_disable_unprepare(ov7740_data.sensor_clk);
- if (gpo_regulator)
- regulator_disable(gpo_regulator);
- if (analog_regulator)
- regulator_disable(analog_regulator);
- if (core_regulator)
- regulator_disable(core_regulator);
- if (io_regulator)
- regulator_disable(io_regulator);
- return 0;
- }
- /*!
- * ov7740 init function
- * Called by insmod ov7740_camera.ko.
- *
- * @return Error code indicating success or failure
- */
- static __init int ov7740_init(void)
- {
- u8 err;
- err = i2c_add_driver(&ov7740_i2c_driver);
- if (err != 0)
- pr_err("%s:driver registration failed, error=%d\n",
- __func__, err);
- return err;
- }
- /*!
- * OV7740 cleanup function
- * Called on rmmod ov7740_camera.ko
- *
- * @return Error code indicating success or failure
- */
- static void __exit ov7740_clean(void)
- {
- i2c_del_driver(&ov7740_i2c_driver);
- }
- module_init(ov7740_init);
- module_exit(ov7740_clean);
- MODULE_AUTHOR("Aurelien BOUIN");
- MODULE_DESCRIPTION("OV7740 Camera Driver");
- MODULE_LICENSE("GPL");
- MODULE_VERSION("1.0");
- MODULE_ALIAS("CSI");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement