/*
* Copyright (C) 2015 MediaTek Inc.
*
* 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.
*
* 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.
*/
#define PFX "OV8856"
#define pr_fmt(fmt) PFX "[%s] " fmt, __func__
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
/*#include <asm/atomic.h>*/
#include "kd_camera_typedef.h"
#include "kd_imgsensor.h"
#include "kd_imgsensor_define.h"
#include "kd_imgsensor_errcode.h"
#include "ov8856mipiraw_Sensor.h"
enum OV8856_VERSION {
OV8856R2A,
OV8856R1A
};
enum OV8856_VERSION ov8856version = OV8856R1A;
static DEFINE_SPINLOCK(imgsensor_drv_lock);
static struct imgsensor_info_struct imgsensor_info = {
/*record sensor id defined in Kd_imgsensor.h*/
.sensor_id = OV8856_SENSOR_ID,
.checksum_value = 0xb1893b4f, /*checksum value for Camera Auto Test*/
.pre = {
.pclk = 144000000, /*record different mode's pclk*/
.linelength = 1932, /*record different mode's linelength*/
.framelength = 2482, /*record different mode's framelength*/
.startx = 0, /*record different mode's startx of grabwindow*/
.starty = 0, /*record different mode's starty of grabwindow*/
/*record different mode's width of grabwindow*/
.grabwindow_width = 1632,
/*record different mode's height of grabwindow*/
.grabwindow_height = 1224,
/* following for MIPIDataLowPwr2HighSpeedSettleDelayCount
* nby different scenario
*/
.mipi_data_lp2hs_settle_dc = 85,
/* following for GetDefaultFramerateByScenario() */
.max_framerate = 300,
.mipi_pixel_rate = 289000000,
},
.cap = {
.pclk = 144000000,
.linelength = 1932,
.framelength = 2482,
.startx = 0,
.starty = 0,
.grabwindow_width = 3264,
.grabwindow_height = 2448,
.mipi_data_lp2hs_settle_dc = 85,
.max_framerate = 300,
.mipi_pixel_rate = 289000000,
},
.cap1 = { /*capture for 15fps*/
.pclk = 144000000,
.linelength = 1932,
.framelength = 4964,
.startx = 0,
.starty = 0,
.grabwindow_width = 3264,
.grabwindow_height = 2448,
.mipi_data_lp2hs_settle_dc = 85,
.max_framerate = 150,
.mipi_pixel_rate = 289000000,
},
.normal_video = { /* cap*/
.pclk = 144000000,
.linelength = 1932,
.framelength = 2482,
.startx = 0,
.starty = 0,
.grabwindow_width = 3264,
.grabwindow_height = 2448,
.mipi_data_lp2hs_settle_dc = 85,
.max_framerate = 300,
.mipi_pixel_rate = 289000000,
},
.hs_video = {
.pclk = 144000000, /*record different mode's pclk*/
.linelength = 1932, /*record different mode's linelength*/
.framelength = 620, /*record different mode's framelength*/
.startx = 0, /*record different mode's startx of grabwindow*/
.starty = 0, /*record different mode's starty of grabwindow*/
/*record different mode's width of grabwindow*/
.grabwindow_width = 640,
/*record different mode's height of grabwindow*/
.grabwindow_height = 480,
.mipi_data_lp2hs_settle_dc = 85,
.max_framerate = 1200,
.mipi_pixel_rate = 290000000,
},
.slim_video = {/*pre*/
.pclk = 144000000, /*record different mode's pclk*/
.linelength = 1932, /*record different mode's linelength*/
.framelength = 2482, /*record different mode's framelength*/
.startx = 0, /*record different mode's startx of grabwindow*/
.starty = 0, /*record different mode's starty of grabwindow*/
/*record different mode's width of grabwindow*/
.grabwindow_width = 1632,
/*record different mode's height of grabwindow*/
.grabwindow_height = 1224,
/* following for MIPIDataLowPwr2HighSpeedSettleDelayCount
* by different scenario
*/
.mipi_data_lp2hs_settle_dc = 85,
/* following for GetDefaultFramerateByScenario() */
.max_framerate = 300,
.mipi_pixel_rate = 289000000,
},
.margin = 6, /*sensor framelength & shutter margin*/
.min_shutter = 6, /*min shutter*/
/*max framelength by sensor register's limitation*/
.max_frame_length = 0x90f7,
.ae_shut_delay_frame = 0,
.ae_sensor_gain_delay_frame = 0,
.ae_ispGain_delay_frame = 2, /*isp gain delay frame for AE cycle*/
.ihdr_support = 0, /*1, support; 0,not support*/
.ihdr_le_firstline = 0, /*1,le first ; 0, se first*/
/*support sensor mode num ,don't support Slow motion*/
.sensor_mode_num = 5,
.cap_delay_frame = 3, /*enter capture delay frame num*/
.pre_delay_frame = 3, /*enter preview delay frame num*/
.video_delay_frame = 3, /*enter video delay frame num*/
.hs_video_delay_frame = 3, /*enter high speed video delay frame num*/
.slim_video_delay_frame = 3,/*enter slim video delay frame num*/
.isp_driving_current = ISP_DRIVING_6MA, /*mclk driving current*/
/*Sensor_interface_type*/
.sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,
/*0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2*/
.mipi_sensor_type = MIPI_OPHY_NCSI2,
/*0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL*/
.mipi_settle_delay_mode = MIPI_SETTLEDELAY_MANUAL,
/*sensor output first pixel color*/
.sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B,
.mclk = 24,/*mclk value, suggest 24 or 26 for 24Mhz or 26Mhz*/
.mipi_lane_num = SENSOR_MIPI_4_LANE,/*mipi lane num*/
/*record sensor support all write id addr, only supprt 4must end with 0xff*/
.i2c_addr_table = {0x42, 0xff},
};
static struct imgsensor_struct imgsensor = {
.mirror = IMAGE_NORMAL, /*mirrorflip information*/
.sensor_mode = IMGSENSOR_MODE_INIT,
.shutter = 0x4C00, /*current shutter*/
.gain = 0x200, /*current gain*/
.dummy_pixel = 0, /*current dummypixel*/
.dummy_line = 0, /*current dummyline*/
/*full size current fps : 24fps for PIP, 30fps for Normal or ZSD*/
.current_fps = 30,
.autoflicker_en = KAL_FALSE,
.test_pattern = KAL_FALSE,
/*current scenario id*/
.current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,
.ihdr_en = 0, /*sensor need support LE, SE with HDR feature*/
.i2c_write_id = 0x42, /*record current sensor's i2c write id*/
};
/* Sensor output window information*/
static struct SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = {
/* Preview */
{ 3296, 2480, 0, 12, 3296, 2456, 1648,
1228, 2, 2, 1632, 1224, 0, 0, 1632, 1224},
/* capture */
{ 3296, 2480, 0, 12, 3296, 2456, 3296,
2456, 4, 2, 3264, 2448, 0, 0, 3264, 2448},
/* video*/
{ 3296, 2480, 0, 12, 3296, 2456, 3296,
2456, 4, 2, 3264, 2448, 0, 0, 3264, 2448},
/*hight speed video */
{ 3296, 2480, 336, 272, 2624, 1936, 656,
484, 8, 2, 640, 480, 0, 0, 640, 480},
/* slim video */
{ 3296, 2480, 0, 12, 3296, 2456, 1648,
1228, 2, 2, 1632, 1224, 0, 0, 1632, 1224}
};
#define SET_STREAMING_TEST 0
#define MULTI_WRITE 1
#if MULTI_WRITE
#define I2C_BUFFER_LEN 225
#else
#define I2C_BUFFER_LEN 3
#endif
static kal_uint16 ov8856_table_write_cmos_sensor(
kal_uint16 *para, kal_uint32 len)
{
char puSendCmd[I2C_BUFFER_LEN];
kal_uint32 tosend, IDX;
kal_uint16 addr = 0, addr_last = 0, data;
tosend = 0;
IDX = 0;
while (len > IDX) {
addr = para[IDX];
{
puSendCmd[tosend++] = (char)(addr >> 8);
puSendCmd[tosend++] = (char)(addr & 0xFF);
data = para[IDX + 1];
puSendCmd[tosend++] = (char)(data & 0xFF);
IDX += 2;
addr_last = addr;
}
#if MULTI_WRITE
if ((I2C_BUFFER_LEN - tosend) < 3 || IDX == len || addr != addr_last) {
iBurstWriteReg_multi(puSendCmd, tosend,
imgsensor.i2c_write_id, 3, imgsensor_info.i2c_speed);
tosend = 0;
}
#else
iWriteRegI2C(puSendCmd, 3, imgsensor.i2c_write_id);
tosend = 0;
#endif
}
return 0;
}
static kal_uint16 read_cmos_sensor(kal_uint32 addr)
{
kal_uint16 get_byte = 0;
char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) };
iReadRegI2C(pu_send_cmd, 2, (u8 *)&get_byte, 1, imgs