Hi,
I am currently working on the atmel video driver, and I am facing a issue.
I have written a driver for the ov2640 omnivison sensor(enclosed). In
the ov2640 driver I am using the v4l2_subdev API. The point is I don't
how how can I access it in my video driver?
How to register the subdev struct in the atmel driver, so I could access
the s_ftm function for instance.
Regards,
Sedji
/*
* Omnivision ov2640 Camera driver
*
* Copyright (C) 2006 Atmel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <mach/gpio.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv.h>
#include <media/atmel-isi.h>
#include "ov2640.h"
static char mclk_name[32] = "isi_clk";
module_param_string(mclk, mclk_name, sizeof(mclk_name), 0644);
MODULE_PARM_DESC(mclk, "Name of the clock used as camera clock input");
MODULE_PARM_DESC(mclk, "Name of mclk parent clock");
struct ov2640 {
struct v4l2_subdev sd;
struct mutex mutex;
u8 miscel_ctrl;
u16 pll_avr_ctrl;
struct clk *mclk;
struct i2c_client client;
struct atmel_isi_camera cam;
};
#define to_ov2640(cam) container_of(cam, struct ov2640, cam)
/*
* OV2640 register configuration for all combinations of pixel format and
* image size(for the moment only qvga YUV...)
*/
static struct ov2640_reg dump_list[] = {
{ OV2640_REG_TERM, OV2640_VAL_TERM }
};
/* YUV configs */
const static struct ov2640_reg qqcif_yuv[] = { };
const static struct ov2640_reg qqvga_yuv[] = { };
const static struct ov2640_reg sqcif_yuv[] = {
{ OV2640_REG_TERM, OV2640_VAL_TERM }
};
const static struct ov2640_reg qcif_yuv[] = {
{0xff, 0x01},{0x12, 0x80},{0xff, 0x00},{0x2c, 0xff},{0x2e, 0xdf},
{0xff, 0x01},{0x3c, 0x32},{0x11, 0x00},{0x09, 0x02},{0x04, 0x28},
{0x13, 0xe5},{0x14, 0x48},{0x2c, 0x0c},{0x33, 0x78},{0x3a, 0x33},
{0x3b, 0xfb},{0x3e, 0x00},{0x43, 0x11},{0x16, 0x10},{0x39, 0x02},
{0x35, 0x88},{0x22, 0x0a},{0x37, 0x40},{0x23, 0x00},{0x34, 0xa0},
{0x36, 0x1a},{0x06, 0x02},{0x07, 0xc0},{0x0d, 0xb7},{0x0e, 0x01},
{0x4c, 0x00},{0x4a, 0x81},{0x21, 0x99},{0x24, 0x3a},{0x25, 0x32},
{0x26, 0x82},{0x5c, 0x00},{0x63, 0x00},{0x5d, 0x55},{0x5e, 0x7d},
{0x5f, 0x7d},{0x60, 0x55},{0x61, 0x70},{0x62, 0x80},{0x7c, 0x05},
{0x20, 0x80},{0x28, 0x30},{0x6c, 0x00},{0x6d, 0x80},{0x6e, 0x00},
{0x70, 0x02},{0x71, 0x94},{0x73, 0xc1},{0x3d, 0x34},{0x5a, 0x57},
{0x4f, 0xbb},{0x50, 0x9c},{0xff, 0x00},{0xe5, 0x7f},{0xf9, 0xc0},
{0x41, 0x24},{0xe0, 0x14},{0x76, 0xff},{0x33, 0xa0},{0x42, 0x20},
{0x43, 0x18},{0x4c, 0x00},{0x87, 0xd0},{0x88, 0x3f},{0xd7, 0x03},
{0xd9, 0x10},{0xd3, 0x82},{0xc8, 0x08},{0xc9, 0x80},{0x7c, 0x00},
{0x7d, 0x02},{0x7c, 0x03},{0x7d, 0x48},{0x7d, 0x48},{0x7c, 0x08},
{0x7d, 0x20},{0x7d, 0x10},{0x7d, 0x0e},{0x90, 0x00},{0x91, 0x0e},
{0x91, 0x1a},{0x91, 0x31},{0x91, 0x5a},{0x91, 0x69},{0x91, 0x75},
{0x91, 0x7e},{0x91, 0x88},{0x91, 0x8f},{0x91, 0x96},{0x91, 0xa3},
{0x91, 0xaf},{0x91, 0xc4},{0x91, 0xd7},{0x91, 0xe8},{0x91, 0x20},
{0x92, 0x00},{0x93, 0x06},{0x93, 0xe3},{0x93, 0x05},{0x93, 0x05},
{0x93, 0x00},{0x93, 0x02},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},
{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x96, 0x00},
{0x97, 0x08},{0x97, 0x19},{0x97, 0x02},{0x97, 0x0c},{0x97, 0x24},
{0x97, 0x30},{0x97, 0x28},{0x97, 0x26},{0x97, 0x02},{0x97, 0x98},
{0x97, 0x80},{0x97, 0x00},{0x97, 0x00},{0xc3, 0xed},{0xa4, 0x00},
{0xa8, 0x00},{0xc5, 0x11},{0xc6, 0x51},{0xbf, 0x80},{0xc7, 0x10},
{0xb6, 0x66},{0xb8, 0xa5},{0xb7, 0x64},{0xb9, 0x7c},{0xb3, 0xaf},
{0xb4, 0x97},{0xb5, 0xff},{0xb0, 0xc5},{0xb1, 0x94},{0xb2, 0x0f},
{0xc4, 0x5c},{0xc0, 0xc8},{0xc1, 0x96},{0x86, 0x1d},{0x50, 0x00},
{0x51, 0x90},{0x52, 0x18},{0x53, 0x00},{0x54, 0x00},{0x55, 0x88},
{0x57, 0x00},{0x5a, 0x90},{0x5b, 0x18},{0x5c, 0x05},{0xc3, 0xed},
{0x7f, 0x00},{0xda, 0x04},{0xe5, 0x1f},{0xe1, 0x67},{0xe0, 0x00},
{0xdd, 0xff},{0x05, 0x00},{0xff, 0x01},{0x11, 0x01},
{0xff, 0x01},{0x12, 0x40},{0x17, 0x11},{0x18, 0x43},{0x19, 0x00},
{0x1a, 0x4b},{0x32, 0x09},{0x4f, 0xca},{0x50, 0xa8},{0x5a, 0x23},
{0x6d, 0x00},{0x3d, 0x38},
{0x39, 0x12},{0x35, 0xda},{0x22, 0x1a},{0x37, 0xc3},{0x23, 0x00},
{0x34, 0xc0},{0x36, 0x1a},{0x06, 0x88},{0x07, 0xc0},{0x0d, 0x87},
{0x0e, 0x41},{0x4c, 0x00},{0x48, 0x00},{0x5B, 0x00},{0x42, 0x03},
{0xff, 0x00},{0xe0, 0x04},{0xc0, 0x64},{0xc1, 0x4B},{0x8c, 0x00},
{0x86, 0x1D},{0xd3, 0x82},{0xe0, 0x00},
/* QCIF */
{0xff, 0x00},{0xc0, 0x64},{0xc1, 0x4B},{0x8c, 0x00},{0x86, 0x3D},
{0x50, 0x92},{0x51, 0xC8},{0x52, 0x96},{0x53, 0x00},{0x54, 0x00},
{0x55, 0x00},{0x5a, 0x2C},{0x5b, 0x24},{0x5c, 0x00},{0xd3, 0x04},
{0xFF, 0x00},{0xE0, 0x04},{0xE1, 0x67},{0xD7, 0x01},{0xDA, 0x00},
{0xD3, 0x82},{0xE0, 0x00},
{ OV2640_REG_TERM, OV2640_VAL_TERM }
};
/* QVGA YUV */
const static struct ov2640_reg qvga_yuv[] = {
/* Value provided by Omnivision */
{0xff, 0x01},{0x12, 0x80},{0xff, 0x00},{0x2c, 0xff},{0x2e, 0xdf},
{0xff, 0x01},{0x3c, 0x32},{0x11, 0x00},{0x09, 0x02},{0x04, 0x28},
{0x13, 0xe5},{0x14, 0x48},{0x2c, 0x0c},{0x33, 0x78},{0x3a, 0x33},
{0x3b, 0xfb},{0x3e, 0x00},{0x43, 0x11},{0x16, 0x10},{0x39, 0x02},
{0x35, 0x88},{0x22, 0x0a},{0x37, 0x40},{0x23, 0x00},{0x34, 0xa0},
{0x36, 0x1a},{0x06, 0x02},{0x07, 0xc0},{0x0d, 0xb7},{0x0e, 0x01},
{0x4c, 0x00},{0x4a, 0x81},{0x21, 0x99},{0x24, 0x3a},{0x25, 0x32},
{0x26, 0x82},{0x5c, 0x00},{0x63, 0x00},{0x5d, 0x55},{0x5e, 0x7d},
{0x5f, 0x7d},{0x60, 0x55},{0x61, 0x70},{0x62, 0x80},{0x7c, 0x05},
{0x20, 0x80},{0x28, 0x30},{0x6c, 0x00},{0x6d, 0x80},{0x6e, 0x00},
{0x70, 0x02},{0x71, 0x94},{0x73, 0xc1},{0x3d, 0x34},{0x5a, 0x57},
{0x4f, 0xbb},{0x50, 0x9c},{0xff, 0x00},{0xe5, 0x7f},{0xf9, 0xc0},
{0x41, 0x24},{0xe0, 0x14},{0x76, 0xff},{0x33, 0xa0},{0x42, 0x20},
{0x43, 0x18},{0x4c, 0x00},{0x87, 0xd0},{0x88, 0x3f},{0xd7, 0x03},
{0xd9, 0x10},{0xd3, 0x82},{0xc8, 0x08},{0xc9, 0x80},{0x7c, 0x00},
{0x7d, 0x02},{0x7c, 0x03},{0x7d, 0x48},{0x7d, 0x48},{0x7c, 0x08},
{0x7d, 0x20},{0x7d, 0x10},{0x7d, 0x0e},{0x90, 0x00},{0x91, 0x0e},
{0x91, 0x1a},{0x91, 0x31},{0x91, 0x5a},{0x91, 0x69},{0x91, 0x75},
{0x91, 0x7e},{0x91, 0x88},{0x91, 0x8f},{0x91, 0x96},{0x91, 0xa3},
{0x91, 0xaf},{0x91, 0xc4},{0x91, 0xd7},{0x91, 0xe8},{0x91, 0x20},
{0x92, 0x00},{0x93, 0x06},{0x93, 0xe3},{0x93, 0x05},{0x93, 0x05},
{0x93, 0x00},{0x93, 0x02},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},
{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x96, 0x00},
{0x97, 0x08},{0x97, 0x19},{0x97, 0x02},{0x97, 0x0c},{0x97, 0x24},
{0x97, 0x30},{0x97, 0x28},{0x97, 0x26},{0x97, 0x02},{0x97, 0x98},
{0x97, 0x80},{0x97, 0x00},{0x97, 0x00},{0xc3, 0xed},{0xa4, 0x00},
{0xa8, 0x00},{0xc5, 0x11},{0xc6, 0x51},{0xbf, 0x80},{0xc7, 0x10},
{0xb6, 0x66},{0xb8, 0xa5},{0xb7, 0x64},{0xb9, 0x7c},{0xb3, 0xaf},
{0xb4, 0x97},{0xb5, 0xff},{0xb0, 0xc5},{0xb1, 0x94},{0xb2, 0x0f},
{0xc4, 0x5c},{0xc0, 0xc8},{0xc1, 0x96},{0x86, 0x1d},{0x50, 0x00},
{0x51, 0x90},{0x52, 0x18},{0x53, 0x00},{0x54, 0x00},{0x55, 0x88},
{0x57, 0x00},{0x5a, 0x90},{0x5b, 0x18},{0x5c, 0x05},{0xc3, 0xed},
{0x7f, 0x00},{0xda, 0x04},{0xe5, 0x1f},{0xe1, 0x67},{0xe0, 0x00},
{0xdd, 0xff},{0x05, 0x00},{0xff, 0x01},{0x11, 0x01},
{0xff, 0x01},{0x12, 0x40},{0x17, 0x11},{0x18, 0x43},{0x19, 0x00},
{0x1a, 0x4b},{0x32, 0x09},{0x4f, 0xca},{0x50, 0xa8},{0x5a, 0x23},
{0x6d, 0x00},{0x3d, 0x38},
{0x39, 0x12},{0x35, 0xda},{0x22, 0x1a},{0x37, 0xc3},{0x23, 0x00},
{0x34, 0xc0},{0x36, 0x1a},{0x06, 0x88},{0x07, 0xc0},{0x0d, 0x87},
{0x0e, 0x41},{0x4c, 0x00},{0x48, 0x00},{0x5B, 0x00},
{0x42, 0x03},{0xff, 0x00},{0xe0, 0x04},{0xc0, 0x64},{0xc1, 0x4B},
{0x8c, 0x00},{0x86, 0x1D},{0xd3, 0x82},{0xe0, 0x00},
{0xff, 0x00},{0xc0, 0x64},{0xc1, 0x4B},{0x8c, 0x00},{0x86, 0x3D},
{0x50, 0x89},{0x51, 0xC8},{0x52, 0x96},{0x53, 0x00},{0x54, 0x00},
{0x55, 0x00},{0x5a, 0x50},{0x5b, 0x3C},{0x5c, 0x00},{0xd3, 0x04},
/* 10 fps */
/*{0xff, 0x01},{0x11, 0x01},{0x3d, 0x3a},{0x2b, 0x95},*/
/* 15 fps */
/*{0xff, 0x01},{0x11, 0x01},{0x3d, 0x38},{0x2b, 0x00},*/
/* 20 fps */
/*{0xff, 0x01},{0x11, 0x00},{0x3d, 0x3a},{0x2b, 0x95},*/
/* 25 fps */
/*{0xff, 0x01},{0x11, 0x00},{0x3d, 0x39},{0x2b, 0x3c},*/
/* 30 fps*/
{0xff, 0x01},{0x11, 0x01},{0x3d, 0x38},{0x2b, 0x00},
{0xFF, 0x00},{0xE0, 0x04},{0xE1, 0x67},{0xD7, 0x01},{0xDA, 0x00},
{0xD3, 0x82},{0xE0, 0x00},
{ OV2640_REG_TERM, OV2640_VAL_TERM }
};
const static struct ov2640_reg cif_yuv[] = { };
const static struct ov2640_reg vga_yuv[] = {
{0xff, 0x01},{0x12, 0x80},{0xff, 0x00},{0x2c, 0xff},{0x2e, 0xdf},
{0xff, 0x01},{0x3c, 0x32},{0x11, 0x00},{0x09, 0x02},{0x04, 0x28},
{0x13, 0xe5},{0x14, 0x48},{0x2c, 0x0c},{0x33, 0x78},{0x3a, 0x33},
{0x3b, 0xfb},{0x3e, 0x00},{0x43, 0x11},{0x16, 0x10},{0x39, 0x02},
{0x35, 0x88},{0x22, 0x0a},{0x37, 0x40},{0x23, 0x00},{0x34, 0xa0},
{0x36, 0x1a},{0x06, 0x02},{0x07, 0xc0},{0x0d, 0xb7},{0x0e, 0x01},
{0x4c, 0x00},{0x4a, 0x81},{0x21, 0x99},{0x24, 0x3a},{0x25, 0x32},
{0x26, 0x82},{0x5c, 0x00},{0x63, 0x00},{0x5d, 0x55},{0x5e, 0x7d},
{0x5f, 0x7d},{0x60, 0x55},{0x61, 0x70},{0x62, 0x80},{0x7c, 0x05},
{0x20, 0x80},{0x28, 0x30},{0x6c, 0x00},{0x6d, 0x80},{0x6e, 0x00},
{0x70, 0x02},{0x71, 0x94},{0x73, 0xc1},{0x3d, 0x34},{0x5a, 0x57},
{0x4f, 0xbb},{0x50, 0x9c},{0xff, 0x00},{0xe5, 0x7f},{0xf9, 0xc0},
{0x41, 0x24},{0xe0, 0x14},{0x76, 0xff},{0x33, 0xa0},{0x42, 0x20},
{0x43, 0x18},{0x4c, 0x00},{0x87, 0xd0},{0x88, 0x3f},{0xd7, 0x03},
{0xd9, 0x10},{0xd3, 0x82},{0xc8, 0x08},{0xc9, 0x80},{0x7c, 0x00},
{0x7d, 0x02},{0x7c, 0x03},{0x7d, 0x48},{0x7d, 0x48},{0x7c, 0x08},
{0x7d, 0x20},{0x7d, 0x10},{0x7d, 0x0e},{0x90, 0x00},{0x91, 0x0e},
{0x91, 0x1a},{0x91, 0x31},{0x91, 0x5a},{0x91, 0x69},{0x91, 0x75},
{0x91, 0x7e},{0x91, 0x88},{0x91, 0x8f},{0x91, 0x96},{0x91, 0xa3},
{0x91, 0xaf},{0x91, 0xc4},{0x91, 0xd7},{0x91, 0xe8},{0x91, 0x20},
{0x92, 0x00},{0x93, 0x06},{0x93, 0xe3},{0x93, 0x05},{0x93, 0x05},
{0x93, 0x00},{0x93, 0x02},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},
{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x96, 0x00},
{0x97, 0x08},{0x97, 0x19},{0x97, 0x02},{0x97, 0x0c},{0x97, 0x24},
{0x97, 0x30},{0x97, 0x28},{0x97, 0x26},{0x97, 0x02},{0x97, 0x98},
{0x97, 0x80},{0x97, 0x00},{0x97, 0x00},{0xc3, 0xed},{0xa4, 0x00},
{0xa8, 0x00},{0xc5, 0x11},{0xc6, 0x51},{0xbf, 0x80},{0xc7, 0x10},
{0xb6, 0x66},{0xb8, 0xa5},{0xb7, 0x64},{0xb9, 0x7c},{0xb3, 0xaf},
{0xb4, 0x97},{0xb5, 0xff},{0xb0, 0xc5},{0xb1, 0x94},{0xb2, 0x0f},
{0xc4, 0x5c},{0xc0, 0xc8},{0xc1, 0x96},{0x86, 0x1d},{0x50, 0x00},
{0x51, 0x90},{0x52, 0x18},{0x53, 0x00},{0x54, 0x00},{0x55, 0x88},
{0x57, 0x00},{0x5a, 0x90},{0x5b, 0x18},{0x5c, 0x05},{0xc3, 0xed},
{0x7f, 0x00},{0xda, 0x04},{0xe5, 0x1f},{0xe1, 0x67},{0xe0, 0x00},
{0xdd, 0xff},{0x05, 0x00},{0xff, 0x01},{0x11, 0x01},
{0xff, 0x01},{0x12, 0x40},{0x17, 0x11},{0x18, 0x43},{0x19, 0x00},
{0x1a, 0x4b},{0x32, 0x09},{0x4f, 0xca},{0x50, 0xa8},{0x5a, 0x23},
{0x6d, 0x00},{0x3d, 0x38},
{0x39, 0x12},{0x35, 0xda},{0x22, 0x1a},{0x37, 0xc3},{0x23, 0x00},
{0x34, 0xc0},{0x36, 0x1a},{0x06, 0x88},{0x07, 0xc0},{0x0d, 0x87},
{0x0e, 0x41},{0x4c, 0x00},{0x48, 0x00},{0x5B, 0x00},{0x42, 0x03},
{0xff, 0x00},{0xe0, 0x04},{0xc0, 0x64},{0xc1, 0x4B},{0x8c, 0x00},
{0x86, 0x1D},{0xd3, 0x82},{0xe0, 0x00},
{0xff, 0x00},{0xc0, 0x64},{0xc1, 0x4B},{0x8c, 0x00},{0x86, 0x3D},
{0x50, 0x00},{0x51, 0xC8},{0x52, 0x96},{0x53, 0x00},{0x54, 0x00},
{0x55, 0x00},{0x5a, 0xA0},{0x5b, 0x78},{0x5c, 0x00},{0xd3, 0x04},
/* fps settings are here */
/* 10 fps */
/*{0xff, 0x01},{0x11, 0x01},{0x3d, 0x3a},{0x2b, 0x95},*/
/* 15 fps */
/*{0xff, 0x01},{0x11, 0x01},{0x3d, 0x38},{0x2b, 0x00},*/
/* 20 fps */
/*{0xff, 0x01},{0x11, 0x00},{0x3d, 0x3a},{0x2b, 0x95},*/
/* 25 fps */
{0xff, 0x01},{0x11, 0x00},{0x3d, 0x39},{0x2b, 0x3c},
/* 30 fps*/
/*{0xff, 0x01},{0x11, 0x01},{0x3d, 0x38},{0x2b, 0x00},*/
{0xFF, 0x00},{0xE0, 0x04},{0xE1, 0x67},{0xD7, 0x01},{0xDA, 0x00},
{0xD3, 0x82},{0xE0, 0x00},
{ OV2640_REG_TERM, OV2640_VAL_TERM }
};
const static struct ov2640_reg svga_yuv[] = {
{0xff, 0x01},{0x12, 0x80},{0xff, 0x00},{0x2c, 0xff},{0x2e, 0xdf},
{0xff, 0x01},{0x3c, 0x32},{0x11, 0x00},{0x09, 0x02},{0x04, 0x28},
{0x13, 0xe5},{0x14, 0x48},{0x2c, 0x0c},{0x33, 0x78},{0x3a, 0x33},
{0x3b, 0xfb},{0x3e, 0x00},{0x43, 0x11},{0x16, 0x10},{0x39, 0x02},
{0x35, 0x88},{0x22, 0x0a},{0x37, 0x40},{0x23, 0x00},{0x34, 0xa0},
{0x36, 0x1a},{0x06, 0x02},{0x07, 0xc0},{0x0d, 0xb7},{0x0e, 0x01},
{0x4c, 0x00},{0x4a, 0x81},{0x21, 0x99},{0x24, 0x3a},{0x25, 0x32},
{0x26, 0x82},{0x5c, 0x00},{0x63, 0x00},{0x5d, 0x55},{0x5e, 0x7d},
{0x5f, 0x7d},{0x60, 0x55},{0x61, 0x70},{0x62, 0x80},{0x7c, 0x05},
{0x20, 0x80},{0x28, 0x30},{0x6c, 0x00},{0x6d, 0x80},{0x6e, 0x00},
{0x70, 0x02},{0x71, 0x94},{0x73, 0xc1},{0x3d, 0x34},{0x5a, 0x57},
{0x4f, 0xbb},{0x50, 0x9c},{0xff, 0x00},{0xe5, 0x7f},{0xf9, 0xc0},
{0x41, 0x24},{0xe0, 0x14},{0x76, 0xff},{0x33, 0xa0},{0x42, 0x20},
{0x43, 0x18},{0x4c, 0x00},{0x87, 0xd0},{0x88, 0x3f},{0xd7, 0x03},
{0xd9, 0x10},{0xd3, 0x82},{0xc8, 0x08},{0xc9, 0x80},{0x7c, 0x00},
{0x7d, 0x02},{0x7c, 0x03},{0x7d, 0x48},{0x7d, 0x48},{0x7c, 0x08},
{0x7d, 0x20},{0x7d, 0x10},{0x7d, 0x0e},{0x90, 0x00},{0x91, 0x0e},
{0x91, 0x1a},{0x91, 0x31},{0x91, 0x5a},{0x91, 0x69},{0x91, 0x75},
{0x91, 0x7e},{0x91, 0x88},{0x91, 0x8f},{0x91, 0x96},{0x91, 0xa3},
{0x91, 0xaf},{0x91, 0xc4},{0x91, 0xd7},{0x91, 0xe8},{0x91, 0x20},
{0x92, 0x00},{0x93, 0x06},{0x93, 0xe3},{0x93, 0x05},{0x93, 0x05},
{0x93, 0x00},{0x93, 0x02},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},
{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x96, 0x00},
{0x97, 0x08},{0x97, 0x19},{0x97, 0x02},{0x97, 0x0c},{0x97, 0x24},
{0x97, 0x30},{0x97, 0x28},{0x97, 0x26},{0x97, 0x02},{0x97, 0x98},
{0x97, 0x80},{0x97, 0x00},{0x97, 0x00},{0xc3, 0xed},{0xa4, 0x00},
{0xa8, 0x00},{0xc5, 0x11},{0xc6, 0x51},{0xbf, 0x80},{0xc7, 0x10},
{0xb6, 0x66},{0xb8, 0xa5},{0xb7, 0x64},{0xb9, 0x7c},{0xb3, 0xaf},
{0xb4, 0x97},{0xb5, 0xff},{0xb0, 0xc5},{0xb1, 0x94},{0xb2, 0x0f},
{0xc4, 0x5c},{0xc0, 0xc8},{0xc1, 0x96},{0x86, 0x1d},{0x50, 0x00},
{0x51, 0x90},{0x52, 0x18},{0x53, 0x00},{0x54, 0x00},{0x55, 0x88},
{0x57, 0x00},{0x5a, 0x90},{0x5b, 0x18},{0x5c, 0x05},{0xc3, 0xed},
{0x7f, 0x00},{0xda, 0x04},{0xe5, 0x1f},{0xe1, 0x67},{0xe0, 0x00},
{0xdd, 0xff},{0x05, 0x00},{0xff, 0x01},{0x11, 0x01},
//SVGA
{0xff, 0x01},{0x12, 0x40},{0x17, 0x11},{0x18, 0x43},{0x19, 0x00},
{0x1a, 0x4b},{0x32, 0x09},{0x4f, 0xca},{0x50, 0xa8},{0x5a, 0x23},
{0x6d, 0x00},{0x3d, 0x38},
{0x39, 0x12},{0x35, 0xda},{0x22, 0x1a},{0x37, 0xc3},{0x23, 0x00},
{0x34, 0xc0},{0x36, 0x1a},{0x06, 0x88},{0x07, 0xc0},{0x0d, 0x87},
{0x0e, 0x41},{0x4c, 0x00},{0x48, 0x00},{0x5B, 0x00},{0x42, 0x03},
{0xff, 0x00},{0xe0, 0x04},{0xc0, 0x64},{0xc1, 0x4B},{0x8c, 0x00},
{0x86, 0x1D},{0xd3, 0x82},{0xe0, 0x00},
/* 25 fps*/
{0xff, 0x01},{0x11, 0x00},{0x3d, 0x39},{0x2b, 0x3c},
//V422
{0xFF, 0x00},{0xE0, 0x04},{0xE1, 0x67},{0xD7, 0x01},{0xDA, 0x00},
{0xD3, 0x82},{0xE0, 0x00},
{ OV2640_REG_TERM, OV2640_VAL_TERM }
};
const static struct ov2640_reg sxga_yuv[] = {
{0xff, 0x01},{0x12, 0x80},{0xff, 0x00},{0x2c, 0xff},{0x2e, 0xdf},
{0xff, 0x01},{0x3c, 0x32},{0x11, 0x00},{0x09, 0x02},{0x04, 0x28},
{0x13, 0xe5},{0x14, 0x48},{0x2c, 0x0c},{0x33, 0x78},{0x3a, 0x33},
{0x3b, 0xfb},{0x3e, 0x00},{0x43, 0x11},{0x16, 0x10},{0x39, 0x02},
{0x35, 0x88},{0x22, 0x0a},{0x37, 0x40},{0x23, 0x00},{0x34, 0xa0},
{0x36, 0x1a},{0x06, 0x02},{0x07, 0xc0},{0x0d, 0xb7},{0x0e, 0x01},
{0x4c, 0x00},{0x4a, 0x81},{0x21, 0x99},{0x24, 0x3a},{0x25, 0x32},
{0x26, 0x82},{0x5c, 0x00},{0x63, 0x00},{0x5d, 0x55},{0x5e, 0x7d},
{0x5f, 0x7d},{0x60, 0x55},{0x61, 0x70},{0x62, 0x80},{0x7c, 0x05},
{0x20, 0x80},{0x28, 0x30},{0x6c, 0x00},{0x6d, 0x80},{0x6e, 0x00},
{0x70, 0x02},{0x71, 0x94},{0x73, 0xc1},{0x3d, 0x34},{0x5a, 0x57},
{0x4f, 0xbb},{0x50, 0x9c},{0xff, 0x00},{0xe5, 0x7f},{0xf9, 0xc0},
{0x41, 0x24},{0xe0, 0x14},{0x76, 0xff},{0x33, 0xa0},{0x42, 0x20},
{0x43, 0x18},{0x4c, 0x00},{0x87, 0xd0},{0x88, 0x3f},{0xd7, 0x03},
{0xd9, 0x10},{0xd3, 0x82},{0xc8, 0x08},{0xc9, 0x80},{0x7c, 0x00},
{0x7d, 0x02},{0x7c, 0x03},{0x7d, 0x48},{0x7d, 0x48},{0x7c, 0x08},
{0x7d, 0x20},{0x7d, 0x10},{0x7d, 0x0e},{0x90, 0x00},{0x91, 0x0e},
{0x91, 0x1a},{0x91, 0x31},{0x91, 0x5a},{0x91, 0x69},{0x91, 0x75},
{0x91, 0x7e},{0x91, 0x88},{0x91, 0x8f},{0x91, 0x96},{0x91, 0xa3},
{0x91, 0xaf},{0x91, 0xc4},{0x91, 0xd7},{0x91, 0xe8},{0x91, 0x20},
{0x92, 0x00},{0x93, 0x06},{0x93, 0xe3},{0x93, 0x05},{0x93, 0x05},
{0x93, 0x00},{0x93, 0x02},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},
{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x93, 0x00},{0x96, 0x00},
{0x97, 0x08},{0x97, 0x19},{0x97, 0x02},{0x97, 0x0c},{0x97, 0x24},
{0x97, 0x30},{0x97, 0x28},{0x97, 0x26},{0x97, 0x02},{0x97, 0x98},
{0x97, 0x80},{0x97, 0x00},{0x97, 0x00},{0xc3, 0xed},{0xa4, 0x00},
{0xa8, 0x00},{0xc5, 0x11},{0xc6, 0x51},{0xbf, 0x80},{0xc7, 0x10},
{0xb6, 0x66},{0xb8, 0xa5},{0xb7, 0x64},{0xb9, 0x7c},{0xb3, 0xaf},
{0xb4, 0x97},{0xb5, 0xff},{0xb0, 0xc5},{0xb1, 0x94},{0xb2, 0x0f},
{0xc4, 0x5c},{0xc0, 0xc8},{0xc1, 0x96},{0x86, 0x1d},{0x50, 0x00},
{0x51, 0x90},{0x52, 0x18},{0x53, 0x00},{0x54, 0x00},{0x55, 0x88},
{0x57, 0x00},{0x5a, 0x90},{0x5b, 0x18},{0x5c, 0x05},{0xc3, 0xed},
{0x7f, 0x00},{0xda, 0x04},{0xe5, 0x1f},{0xe1, 0x67},{0xe0, 0x00},
{0xdd, 0xff},{0x05, 0x00},{0xff, 0x01},{0x11, 0x00},
//SXGA
{0xff, 0x00},{0xc0, 0xc8},{0xc1, 0x96},{0x8c, 0x00},{0x86, 0x3d},
{0x50, 0x00},{0x51, 0x90},{0x52, 0x2c},{0x53, 0x00},{0x54, 0x00},
{0x55, 0x88},{0x5a, 0x40},{0x5b, 0x00},{0x5c, 0x05},{0xd3, 0x82},
//V422
{0xFF, 0x00},{0xE0, 0x04},{0xE1, 0x67},{0xD7, 0x01},{0xDA, 0x00},
{0xD3, 0x82},{0xE0, 0x00},
{ OV2640_REG_TERM, OV2640_VAL_TERM }
};
/* 565 configs */
const static struct ov2640_reg qqcif_565[] = { };
const static struct ov2640_reg qqvga_565[] = { };
const static struct ov2640_reg qcif_565[] = { };
const static struct ov2640_reg qvga_565[] = { };
const static struct ov2640_reg cif_565[] = { };
const static struct ov2640_reg vga_565[] = { };
const static struct ov2640_reg svga_565[] = { };
const static struct ov2640_reg sxga_565[] = { };
/* 555 configs */
const static struct ov2640_reg qqcif_555[] = { };
const static struct ov2640_reg qqvga_555[] = { };
const static struct ov2640_reg qcif_555[] = { };
const static struct ov2640_reg qvga_555[] = { };
const static struct ov2640_reg cif_555[] = { };
const static struct ov2640_reg vga_555[] = { };
const static struct ov2640_reg svga_555[] = { };
const static struct ov2640_reg sxga_555[] = { };
const static struct ov2640_reg *
ov2640_reg_init[NUM_PIXEL_FORMATS][NUM_IMAGE_SIZES] =
{
{ qqcif_yuv, qqvga_yuv, qcif_yuv, qvga_yuv, cif_yuv, vga_yuv, svga_yuv, sxga_yuv },
{ qqcif_565, qqvga_565, qcif_565, qvga_565, cif_565, vga_565, svga_565, sxga_565 },
{ qqcif_555, qqvga_555, qcif_555, qvga_555, cif_555, vga_555, svga_555, sxga_555 },
};
//static struct i2c_driver ov2640_driver;
static inline struct ov2640 *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct ov2640, sd);
}
/*
* Write a value to a register in an OV2640 sensor device.
* Returns zero if successful, or non-zero otherwise.
*/
static int
ov2640_write_reg(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
int err;
struct i2c_msg msg[1];
unsigned char data[2];
if (!client->adapter)
return -ENODEV;
msg->addr = client->addr;
msg->flags = 0;
msg->len = 2;
msg->buf = data;
data[0] = reg;
data[1] = val;
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0)
return 0;
return err;
}
/*
* Read a value from a register in an OV2640 sensor device.
* The value is returned in 'val'.
* Returns zero if successful, or non-zero otherwise.
*/
static int
ov2640_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
int err;
struct i2c_msg msg[1];
unsigned char data[1];
if (!client->adapter)
return -ENODEV;
msg->addr = client->addr;
msg->flags = 0;
msg->len = 1;
msg->buf = data;
*data = reg;
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0) {
msg->flags = I2C_M_RD;
err = i2c_transfer(client->adapter, msg, 1);
}
if (err >= 0) {
*val = *data;
return 0;
}
return err;
}
/* fct use to initialize all the registers */
static int
ov2640_write_regs(struct v4l2_subdev *sd, const struct ov2640_reg reglist[])
{
int err;
const struct ov2640_reg *next = reglist;
while (!((next->reg == OV2640_REG_TERM)
&& (next->val == OV2640_VAL_TERM))) {
err = ov2640_write_reg(sd, next->reg, next->val);
udelay(100);
if (err)
return err;
next++;
}
return 0;
}
/*
* Find the best match for a requested image capture size. The best match
* is chosen as the nearest match that has the same number or fewer pixels
* as the requested size, or the smallest image size if the requested size
* has fewer pixels than the smallest image.
*/
static enum image_size
ov2640_find_size(unsigned int width, unsigned int height)
{
enum image_size isize;
unsigned long pixels = width*height;
for (isize = QQCIF; isize < SXGA; isize++) {
if (ov2640_sizes[isize + 1].height *
ov2640_sizes[isize + 1].width > pixels)
return isize;
}
return SXGA;
}
static int ov2640_init(struct v4l2_subdev *sd, u32 val)
{
return ov2640_write_regs(sd, vga_yuv);
}
static int ov2640_get_format(struct atmel_isi_camera *cam,
struct atmel_isi_format *fmt)
{
int err = 0;
return err;
}
static int ov2640_s_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mf)
{
int err;
printk(KERN_INFO "ov2640 s fmt\n");
/* For time being only YUV422 vga */
err = ov2640_write_regs(sd, vga_yuv);
return err;
}
static int ov2640_s_stream(struct v4l2_subdev *sd, int enable)
{
int err = 0;
printk(KERN_INFO "ov2640 start frame\n");
/* Set the color bar test mode: to test wether the sensor is
* properly configure or not.
*/
/*err = ov2640_write_reg(&info->sd, 0xFF, 0x01);
err = ov2640_write_reg(&info->sd, OV2640_COM7, OV2640_COLORBAR);*/
return err;
}
static int ov2640_reset(struct ov2640 *is)
{
int err;
err = ov2640_write_reg(&is->sd, 0XFF, 0x01);
/* Reset Pin = COM7 bit 7*/
err = ov2640_write_reg(&is->sd, OV2640_COM7, OV2640_RESET);
if (err)
pr_debug("ov2640_reset failed\n");
return err;
}
static int ov2640_detect(struct v4l2_subdev *sd)
{
int err = 0;
u8 midh, midl, pidh;
/* Try to identify the camera */
if (ov2640_read_reg(sd, OV2640_MIDH, &midh))
return -ENODEV;
if (ov2640_read_reg(sd, OV2640_MIDL, &midl))
return -ENODEV;
if (ov2640_read_reg(sd, OV2640_PIDH, &pidh))
return -ENODEV;
if ((midh != OV2640_MIDH_MAGIC)
|| (midl != OV2640_MIDL_MAGIC)
|| (pidh != OV2640_PID_MAGIC))
/*
* We didn't read the values we expected, so
* this must not be an OV2640.
*/
return -ENODEV;
return err;
}
static int ov2640_g_chip_ident(struct v4l2_subdev *sd,
struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV2640, 0);
}
/* ----------------------------------------------------------------------- */
static const struct v4l2_subdev_core_ops ov2640_core_ops = {
.g_chip_ident = ov2640_g_chip_ident,
.reset = ov2640_reset,
.init = ov2640_init,
};
static const struct v4l2_subdev_video_ops ov2640_video_ops = {
.s_stream = ov2640_s_stream,
.s_fmt = ov2640_s_fmt,
};
static const struct v4l2_subdev_ops ov2640_ops = {
.core = &ov2640_core_ops,
.video = &ov2640_video_ops,
};
/* ----------------------------------------------------------------------- */
static struct clk *mclk;
static int ov2640_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct v4l2_subdev *sd;
struct ov2640 *info;
int ret;
/*
* Set up the master clock, if available. If clk_get() fails,
* this hopefully means that the board generates a suitable
* master clock some other way, which is fine by us.
*
* We need to do this before probing the i2c bus, as the
* camera won't ack any messages when it doesn't have a clock.
*/
mclk = clk_get(NULL, mclk_name);
if (!IS_ERR(mclk)) {
clk_enable(mclk);
pr_debug("isi_clk enable\n");
}
else {
mclk = NULL;
pr_debug("no isi clock enable\n");
}
info = kzalloc(sizeof(struct ov2640), GFP_KERNEL);
if (info == NULL)
return -ENOMEM;
sd = &info->sd;
v4l2_i2c_subdev_init(sd, client, &ov2640_ops);
/* Make sure it's an ov2640 */
ret =ov2640_detect(sd);
if (ret) {
pr_debug("chip found @ 0x%x (%s) is not an ov2640 chip.\n",
client->addr << 1, client->adapter->name);
kfree(info);
return ret;
}
/* default config */
ov2640_write_regs(sd, vga_yuv);
v4l_info(client, "chip found @ 0x%02x (%s)\n",
client->addr << 1, client->adapter->name);
return 0;
}
static int ov2640_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd);
kfree(to_state(sd));
return 0;
}
static const struct i2c_device_id ov2640_i2c_id[] = {
{ "ov2640", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ov2640_i2c_id);
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "ov2640",
.probe = ov2640_probe,
.remove = ov2640_remove,
.id_table = ov2640_i2c_id,
};
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@xxxxxxxxx>");
MODULE_DESCRIPTION("Omnivision ov955 Image Sensor driver");
MODULE_LICENSE("GPL");