本文共 44490 字,大约阅读时间需要 148 分钟。
code:
/* Copyright (c) 2013, The Linux Foundation. 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 version 2 and * only 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. * */ #include "msm_sensor.h" #include "msm_cci.h" #include "msm_camera_io_util.h" #include <linux/hipad_board_id.h> #define AT2250_SENSOR_NAME "at2250" #define PLATFORM_DRIVER_NAME "msm_camera_at2250" #define CONFIG_MSMB_CAMERA_DEBUG #define ONLINE_DEBUG #undef CDBG #ifdef CONFIG_MSMB_CAMERA_DEBUG #define CDBG(fmt, args...) pr_err(fmt, ##args) #else #define CDBG(fmt, args...) do { } while (0) #endif //#define CLOSE_FUNCTION //#define LOW_speed DEFINE_MSM_MUTEX(at2250_mut); static struct msm_sensor_ctrl_t at2250_s_ctrl; static struct msm_sensor_power_setting at2250_power_setting[] = { { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_RESET, .config_val = GPIO_OUT_LOW, .delay = 0, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_STANDBY, .config_val = GPIO_OUT_HIGH, .delay = 0, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VIO, .config_val = 0, .delay = 1, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VDIG, .config_val = 0, .delay = 1, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VANA, .config_val = 0, .delay = 1, }, { .seq_type = SENSOR_CLK, .seq_val = SENSOR_CAM_MCLK, .config_val = 24000000, .delay = 5, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_STANDBY, .config_val = GPIO_OUT_LOW, .delay = 10, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_RESET, .config_val = GPIO_OUT_HIGH, .delay = 10, }, }; static struct msm_camera_i2c_reg_conf at2250_uxga_settings[] = { {0xb5, 0xf0}, {0x12, 0x40}, #ifdef LOW_speed {0x0d,0xd0}, {0x0e,0x10}, {0x0f,0x66}, {0x10,0x11}, {0x11,0x04}, #else {0x0d,0xd0}, {0x0e,0x10}, {0x0f,0x07}, {0x10,0x18}, {0x11,0x41}, #endif {0X13,0X8E}, {0x1b,0x44}, {0x1f,0x40}, {0x20,0x8e}, {0x21,0x07}, {0x22,0xD8}, {0x23,0x04}, {0x24,0x40}, {0x25,0xB4}, {0x26,0x46}, {0x27,0xE6}, //0xE4 {0x28,0x08}, {0x29,0x00}, {0x2a,0xd4}, {0x2b,0x10}, {0x2c,0x00}, {0x2d,0x00}, {0x2e,0x30}, {0x2f,0xa4}, {0x38,0x40}, {0x39,0xb0}, {0x3a,0x46}, {0x3b,0x40}, {0x3c,0xb0}, {0x3d,0x46}, {0x40,0x02}, {0xbd,0x80}, {0xbe,0x0c}, #ifdef LOW_speed {0xb7,0x22},//6a {0xb8,0x23},//69 {0xb9,0x27},//69 {0xba,0x11},//33 {0xbb,0x14},//0x16 {0xbf,0x15}, #else {0xb7,0xb6},//6a {0xb8,0xd1},//69 {0xb9,0xab},//69 {0xba,0x55},//33 {0xbb,0x14},//0x16 {0xbf,0x15}, #endif {0x3e,0xae}, {0x3f,0x24}, {0x60,0x0b}, {0x61,0x11}, {0x62,0x0b}, {0x63,0x11}, {0x64,0x40}, {0x65,0xaa}, {0x18,0x64},//5d {0x19,0x90}, {0x36,0x7b}, {0x12,0x32}, {0xb5,0xf0}, }; static struct msm_camera_i2c_reg_conf at2250_uxga1_settings[] = { {0xb5, 0xf0}, {0x12, 0x40}, #ifdef LOW_speed {0x0d,0xd0}, {0x0e,0x10}, {0x0f,0x66}, {0x10,0x11}, {0x11,0x04}, #else {0x0d,0xd0}, {0x0e,0x10}, {0x0f,0x07}, {0x10,0x18}, {0x11,0x41}, #endif {0X13,0X8E}, {0x1b,0x44}, {0x1f,0x40}, {0x20,0x8e}, {0x21,0x07}, {0x22,0xD8}, {0x23,0x04}, {0x24,0x40}, {0x25,0xB4}, {0x26,0x46}, {0x27,0xE5}, //0xE4 // 0xE6 {0x28,0x08}, {0x29,0x00}, {0x2a,0xd4}, {0x2b,0x10}, {0x2c,0x00}, {0x2d,0x00}, {0x2e,0x30}, {0x2f,0xa4}, {0x38,0x40}, {0x39,0xb0}, {0x3a,0x46}, {0x3b,0x40}, {0x3c,0xb0}, {0x3d,0x46}, {0x40,0x02}, {0xbd,0x80}, {0xbe,0x0c}, #ifdef LOW_speed {0xb7,0x22},//6a {0xb8,0x23},//69 {0xb9,0x27},//69 {0xba,0x11},//33 {0xbb,0x14},//0x16 {0xbf,0x15}, #else {0xb7,0xb6},//6a {0xb8,0xd1},//69 {0xb9,0xab},//69 {0xba,0x55},//33 {0xbb,0x14},//0x16 {0xbf,0x15}, #endif {0x3e,0xa4}, {0x3f,0x24}, {0x60,0x11}, {0x61,0x0b}, {0x62,0x11}, {0x63,0x1b}, {0x64,0x40}, {0x65,0xaa}, {0x18,0x74},//5d {0x19,0x91}, {0x36,0x7b}, {0x12,0x02}, // 0x32 {0xb5,0xf0},//0x50 }; static struct msm_camera_i2c_reg_conf at2250_start_settings[] = { {0xb5, 0x50}, }; static struct msm_camera_i2c_reg_conf at2250_stop_settings[] = { {0xb5, 0xf0}, }; static struct msm_camera_i2c_reg_conf at2250_recommend_settings[] = { {0x12,0x80},// ;reset, sleep, mirror, flip, fmt, downsample {0x12,0x42},// ;sleep {0x0c,0x04},// ;Bsun, ADCKDLY, PH_Gap, TM {0x30,0x96},// ;96 RST option, RST width {0x31,0x10},// ;16 TX option, PTX width {0x32,0x0c},// ;20 Bitline option, STX width {0x33,0x28},// ;28 Hold option, hold width {0xaa,0x28},// ;array iref,bias,blsw,ibit<3:0> {0xab,0x11},// ;cs gap,sa2ck delay,ianhlf,anbias {0xac,0x15},// ;Bsun 2x, vrSun<3:0>=1.5v 2x {0xad,0x25},// ;adbias, adrefc, adref, ad_r4 {0xae,0x40},// ;adref, adph delay {0xaf,0xa0},// ;sa1-adc delay, agc vref, sa1-adc clock gap {0xb0,0x40},// ;60 pwc, byRSVDD,RSVDD<2:0>,ihlfary,pd_other,pd_bias,byRgu {0xb1,0x00},// ;00 pwc, vrBG<3:0>, vrBGlp<3:0> {0xb2,0x74},// ;74 pwc, byNpump, vrNvdd<2:0>, byPpump, vrHvdd<2:0> {0xb3,0x39},// ;41 pwc, vrFD<3:0>=0.4v, vrSun<3:0>=1.7v 1x ;10302012 from 38 to 39 {0x0e,0x10}, {0x0f,0x07},//03 13 {0x10,0x18}, {0x11,0x41},//01 02 {0x0d,0xd0}, {0x1d,0x00},// ;interface, pclk/href/vsync/dvp[9:0] off {0x1e,0x00},// {0xb5,0xF0},// ;;b5 mipi phy: pd, 2nd lane dis, 1st lane dis, data lane hs latch en, vcom, lpdrv {0xb8,0xd1},// ;;8a mipi: hs zero width<2:0>, ck zero width<4:0> {0xb9,0xab},// ;;68 mipi: hs prep<2:0>, ck post<4:0> {0xba,0x55},// ;;33 mipi: int pclk op, hs_trail<2:0>, ck_trail<3:0> {0xbb,0x14},//0x16// ;;0a mipi: pclk gate,pclk dly<1:0>,hs prep time manual sign,h full/v skip,man start cal,ck free,ckprep {0xbc,0x1e},// ;;2b mipi: output data type {0xbd,0x80},// ;;d0 mipi: data lane word count lsb {0xbe,0x0c},// ;;07 mipi: data lane work count msb {0xbf,0x14},// ;;14 mipi: manual prep time {0x1b,0x44},// ;hvpading {0x1f,0x40},// ;cc656, data sequence, H full, H skip/bin, V bin/skip, group {0x20,0x8e},// ;20~23 frame width, height, frame rate: 15.00375fps {0x21,0x07},// {0x22,0xD8},// {0x23,0x04},// {0x24,0x40},// ;24~26 H/V window {0x25,0xB4},// {0x26,0x46},// {0x27,0xE3},// ;27~29 H/V window start {0x28,0x0b},// {0x29,0x00},// {0x2a,0xd4},// ;2a~2b column shift start/end {0x2b,0x10},// {0x2c,0x00},// ;2c~2f H/V address shift start/end {0x2d,0x00},// {0x2e,0x30},// {0x2f,0xa4},// ;[7] AWB opt- 1:always do, 0 halt when ALC unstable, [3:2]-SenVEnd[9:8],[3:2]SenVst[9:8] {0x38,0x40},// {0x39,0xb0},// {0x3a,0x46},// {0x3b,0x40},// {0x3c,0xb0},// {0x3d,0x46},// {0xbd,0x80},// ;;mipi only: data lane word count lsb {0xbe,0x0c},// ;;mipi only: data lane work count msb*/ {0xb7,0xb6}, {0xb8,0xd1}, {0xb9,0xab}, {0xba,0x55}, {0xbb,0x14},//0x06 {0xbf,0x18}, #if 0 {0x1b,0x44}, {0x1f,0x42},//42 {0x20,0x52}, {0x21,0x06}, {0x22,0x6a}, {0x23,0x02}, {0x24,0x20}, {0x25,0x58}, {0x26,0x23}, {0x27,0x8e}, //8d {0x28,0x08}, {0x29,0x01}, {0x2a,0x7E}, {0x2b,0x11}, {0x2c,0x00}, {0x2d,0x00}, {0x2e,0x31}, {0x2f,0x24}, {0x38,0x20}, {0x39,0x58}, // 0x58 {0x3a,0x23}, {0x3b,0x80}, {0x3c,0xE0}, {0x3d,0x12}, {0xbd,0x00}, {0xbe,0x05}, {0xb7,0x92}, {0xb8,0xae}, {0xb9,0x8b}, {0xba,0x54}, {0xbb,0x14},//0x06 {0xbf,0x18}, #endif {0x13,0x8e},// ;gain ceiling, auto frame rate, banding, partial line, aec/agc auto // 0x86 {0x14,0x49},// ;;14~17 aec/agc target, trigger range, threshold // 0x4c {0x15,0x34},// ; {0x16,0x78},// ; {0x17,0x1e},// ; {0x18,0x74},// ;1 band at 50hz {0x19,0x91},// ;aec big step gap, ppchg ahead prechg, ppchg, data clip, band {0xa0,0x55},// ;avg weight {0xa1,0x55},// ;avg weight {0xa2,0x55},// ;avg weight {0xa3,0x55},// ;avg weight {0xa4,0x00},// ;a4 [2] 1 isp weight average/0 normal average, [1:0] 00 raw/01 RGB before gamma/10 RGB after gamma //{0x36,0x7b},// ;hue/scalar off, isp:hue,sde,gamma,denoise,dpc,scalar,lenc,awb {0x37,0x00},// ;awb_stblen, isp:gbrg,bgrg,yrange,neg,nc,cip simple,awb_stblen,awb_greyen {0x40,0x00},// ;;40 [4]=0 raw data with AWB applied {0x49,0x02},// {0x4a,0x0f},// ;0d {0x75,0x00},// ;7F, 75~7f sde {0x76,0x40},// ;7F {0x79,0x00},// ;FF {0x7a,0x00},// ;FF {0x7b,0x00},// ;FF {0x7c,0x00},// ;00;FF {0x7d,0x00},// ;FF {0x7e,0x00},// ;0 {0x7f,0x80},// ;FF // 0x98 {0x77,0x07},// ; {0x78,0x09},// ; //AWB //{0x80,0xFA}, //{0x81,0x20}, //{0x82,0x10}, //12 {0x83,0x05}, //27 {0x84,0x50}, // 0x50 {0x85,0x1E}, {0x86,0x64}, {0x87,0x80}, {0x88,0x92}, {0x89,0x9b}, {0x8A,0x94}, {0x8B,0xad}, {0x8C,0x8e}, {0x8D,0x62}, {0x8E,0x5b}, {0x8F,0x52}, // 0x52 {0x90,0xC8}, //SDE {0x75,0x00}, {0x76,0x40}, {0x79,0x00}, {0x7a,0x00}, {0x7b,0x00}, {0x7c,0x00}, {0x7d,0x00}, {0x7e,0x00}, {0x7f,0x80},//80 {0x77,0x07}, {0x78,0x09}, //color matrix {0x91,0x11}, {0x92,0x2e}, {0x93,0x00}, {0x94,0x0d}, {0x95,0x43}, {0x96,0x50}, {0x97,0x51}, {0x98,0x53}, {0x99,0x02}, {0x9a,0x00}, {0x9b,0x80}, {0x9c,0x80}, {0x9d,0x4C}, {0x9e,0x08}, //gamma {0x50,0x04}, // 0x04 {0x51,0x06}, // 0x06 {0x52,0x0c}, {0x53,0x1a}, {0x54,0x28}, {0x55,0x38}, {0x56,0x48}, {0x57,0x59}, {0x58,0x70}, {0x59,0x86}, {0x5a,0x9a}, {0x5b,0xa8}, {0x5c,0xb4}, {0x5d,0xcc}, {0x5e,0xe0}, {0x5f,0xff}, //ed,denoise {0x3e,0xa0}, {0x3f,0x24}, {0x60,0x18}, {0x61,0x18}, {0x62,0x18}, {0x63,0x18}, {0x64,0x50}, {0x65,0xaa}, //Lens {0x66,0xcf}, //RH {0x67,0xc4}, //RV {0x68,0xbf}, // ;GH {0x69,0xc0}, // ;GV {0x6a,0xb2}, // ;BH {0x6b,0xaf}, // ;BV {0x6c,0x12}, //RH LSB {0x6d,0x6b}, //RV LSB {0x6e,0xBB}, //[7:0]GV,GH,RV, RH {0x6f,0x12}, //GH LSB {0x70,0x58}, //GV LSB {0x71,0x08}, //BH LSB {0x72,0x50}, //BV LSB {0x73,0x0B}, //[3:0] BV, BH MSB {0x05,0x60}, {0x06,0x00}, {0x07,0xab}, {0x08,0x54}, {0x09,0x05}, {0x36,0x7b}, {0x12,0x32}, {0xb5,0x50}, #if 0 #ifdef LOW_speed {0x0d,0xd0}, {0x0e,0x10}, {0x0f,0x66}, {0x10,0x11}, {0x11,0x04}, #else {0x0d,0xd0}, {0x0e,0x10}, {0x0f,0x07}, {0x10,0x18}, {0x11,0x41}, #endif {0X13,0X8E}, {0x1b,0x44}, {0x1f,0x40}, {0x20,0x8e}, {0x21,0x07}, {0x22,0xD8}, {0x23,0x04}, {0x24,0x40}, {0x25,0xB4}, {0x26,0x46}, {0x27,0xE6}, //0xE4 {0x28,0x08}, {0x29,0x00}, {0x2a,0xd4}, {0x2b,0x10}, {0x2c,0x00}, {0x2d,0x00}, {0x2e,0x30}, {0x2f,0xa4}, {0x38,0x40}, {0x39,0xb0}, {0x3a,0x46}, {0x3b,0x40}, {0x3c,0xb0}, {0x3d,0x46}, {0x40,0x02}, {0xbd,0x80}, {0xbe,0x0c}, #ifdef LOW_speed {0xb7,0x22},//6a {0xb8,0x23},//69 {0xb9,0x27},//69 {0xba,0x11},//33 {0xbb,0x14},//0x16 {0xbf,0x15}, #else {0xb7,0xb6},//6a {0xb8,0xd1},//69 {0xb9,0xab},//69 {0xba,0x55},//33 {0xbb,0x14},//0x16 {0xbf,0x15}, #endif {0x3e,0xae}, {0x3f,0x24}, {0x60,0x0b}, {0x61,0x11}, {0x62,0x0b}, {0x63,0x11}, {0x64,0x40}, {0x65,0xaa}, {0x18,0x64},//5d {0x19,0x90}, {0x36,0x7b}, {0x12,0x32}, {0xb5,0xf0}, #endif }; static struct v4l2_subdev_info at2250_subdev_info[] = { { .code = V4L2_MBUS_FMT_YUYV8_2X8, .colorspace = V4L2_COLORSPACE_JPEG, .fmt = 1, .order = 0, }, }; static struct msm_camera_i2c_reg_conf at2250_svga_settings[] = { {0xb5, 0xf0}, {0x12, 0x40}, #ifdef LOW_speed {0x0d,0xd0}, {0x0e,0x10}, {0x0f,0x66}, {0x10,0x11}, {0x11,0x04}, #else {0x0e,0x13}, {0x0f,0x03}, {0x10,0x50}, {0x11,0x01}, {0x0d,0x80}, #endif {0X13,0X86}, {0x1b,0x44}, {0x1f,0x42}, {0x20,0x52}, {0x21,0x06}, {0x22,0x6a}, {0x23,0x02}, {0x24,0x20}, {0x25,0x58}, {0x26,0x23}, {0x27,0x8e}, //8d {0x28,0x08}, {0x29,0x01}, {0x2a,0x7E}, {0x2b,0x11}, {0x2c,0x00}, {0x2d,0x00}, {0x2e,0x31}, {0x2f,0x24}, //scaler {0x38,0x20}, {0x39,0x58}, {0x3a,0x23}, {0x3b,0x20}, {0x3c,0x58}, {0x3d,0x23}, {0xbd,0x40}, {0xbe,0x06}, #ifdef LOW_speed {0xb7,0x22}, {0xb8,0x23}, {0xb9,0x27}, {0xba,0x11}, {0xbb,0x04}, {0xbf,0x06}, #else {0xb7,0x92}, {0xb8,0xae}, {0xb9,0x8b}, {0xba,0x54}, {0xbb,0x04}, {0xbf,0x06}, #endif {0x3e,0x92}, {0x3f,0x24}, {0x60,0x10}, {0x61,0x14}, {0x62,0x10}, {0x63,0x14}, {0x64,0x48}, {0x65,0xaa}, {0x18,0xb9}, {0x19,0x90}, {0x36,0x7f}, {0x12,0x33}, //03 {0xb5,0x50}, }; static struct msm_camera_i2c_reg_conf at2250_sleep_settings[] = { {0x12,0x42},// ;sleep }; static struct msm_camera_i2c_reg_conf AT2250_reg_saturation[11][13] = { {//0.5 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x9 },// {0xc3,0x24},// {0xc5,0x2D},// {0xc7,0x2F},// {0xc9,0x2E},// {0xcb,0x1 },// {0x1f,0x41}, }, {//0.6 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0xA },// {0xc3,0x2B},// {0xc5,0x36},// {0xc7,0x39},// {0xc9,0x37},// {0xcb,0x1 },// {0x1f,0x41}, }, { // 0.7 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0xC },// {0xc3,0x33},// {0xc5,0x3F},// {0xc7,0x42},// {0xc9,0x40},// {0xcb,0x1 },// {0x1f,0x41}, }, { // 0.8 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x0E},// {0xc3,0x3A},// {0xc5,0x48},// {0xc7,0x4C},// {0xc9,0x49},// {0xcb,0x01},// {0x1f,0x41}, }, { // 0.9 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x10},// {0xc3,0x41},// {0xc5,0x51},// {0xc7,0x55},// {0xc9,0x52},// {0xcb,0x01},// {0x1f,0x41}, }, { #if 1 //131126_lj {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, /* {0xc1,0x12},// {0xc3,0x40},//0x45 {0xc5,0x55},// {0xc7,0x5c},// {0xc9,0x5c},// {0xcb,0x02},//*/ {0xc1,0x12},// {0xc3,0x4b},//0x45 {0xc5,0x5b},// {0xc7,0x58},//0x54 0x57 {0xc9,0x56},// {0xcb,0x00},// {0x1f,0x41}, #else {0x94,0x12,1,0},// {0x95,0x49,1,0},// {0x96,0x5a,1,0},// {0x97,0x5f,1,0},// {0x98,0x5c,1,0},// {0x99,0x02,1,0},// #endif }, {// 1.1 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x13},// {0xc3,0x50},// {0xc5,0x63},// {0xc7,0x68},// {0xc9,0x65},// {0xcb,0x2 },// {0x1f,0x41}, }, { // 1.2 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x15},// {0xc3,0x57},// {0xc5,0x6C},// {0xc7,0x72},// {0xc9,0x6E},// {0xcb,0x2 },// {0x1f,0x41}, }, { // 1.3 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x17},// {0xc3,0x5E},// {0xc5,0x75},// {0xc7,0x7B},// {0xc9,0x77},// {0xcb,0x2 },// {0x1f,0x41}, }, {// 1.4 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x19},// {0xc3,0x66},// {0xc5,0x7E},// {0xc7,0x85},// {0xc9,0x80},// {0xcb,0x2 },// {0x1f,0x41}, }, {// 1.5 {0xc0,0x94}, {0xc2,0x95}, {0xc4,0x96}, {0xc6,0x97}, {0xc8,0x98}, {0xca,0x99}, {0xc1,0x1B},// {0xc3,0x6D},// {0xc5,0x87},// {0xc7,0x8E},// {0xc9,0x8A},// {0xcb,0x3 },// {0x1f,0x41}, }, }; #define AT2250_contrast_0x7f_val 0x80 static struct msm_camera_i2c_reg_conf AT2250_reg_contrast[11][1] = { { //Contrast -5 {0x7f, AT2250_contrast_0x7f_val-40}, }, { //Contrast -4 {0x7f, AT2250_contrast_0x7f_val-32}, }, { //Contrast -3 {0x7f, AT2250_contrast_0x7f_val-24}, }, { //Contrast -2 {0x7f, AT2250_contrast_0x7f_val-16}, }, { //Contrast -1 {0x7f, AT2250_contrast_0x7f_val-8}, }, { //Contrast (Default) {0x7f, AT2250_contrast_0x7f_val}, }, { //Contrast +1 {0x7f, AT2250_contrast_0x7f_val+8}, }, { //Contrast +2 {0x7f, AT2250_contrast_0x7f_val+16}, }, { //Contrast +3 {0x7f, AT2250_contrast_0x7f_val+24}, }, { //Contrast +4 {0x7f, AT2250_contrast_0x7f_val+32}, }, { //Contrast +5 {0x7f, AT2250_contrast_0x7f_val+40}, }, }; #define AT2250_sharpness_0x3e_val 0xac static struct msm_camera_i2c_reg_conf AT2250_reg_sharpness[7][1] = { { {0x3e,AT2250_sharpness_0x3e_val-24}, }, /* SHARPNESS LEVEL 0*/ { {0x3e,AT2250_sharpness_0x3e_val-16}, }, /* SHARPNESS LEVEL 1*/ { {0x3e,AT2250_sharpness_0x3e_val-8}, }, /* SHARPNESS LEVEL 2*/ { {0x3e,AT2250_sharpness_0x3e_val}, }, /* SHARPNESS LEVEL 3*/ { {0x3e,AT2250_sharpness_0x3e_val+8}, }, /* SHARPNESS LEVEL 4*/ { {0x3e,AT2250_sharpness_0x3e_val+16}, }, /* SHARPNESS LEVEL 5*/ { {0x3e,AT2250_sharpness_0x3e_val+24}, }, /* SHARPNESS LEVEL 6*/ }; #define at2250_reg_0x14_val 0x49 static struct msm_camera_i2c_reg_conf AT2250_reg_iso[7][4] = { /* auto */ { {0x14,at2250_reg_0x14_val}, {0x15,0x22}, {0x16,0x88}, {0x17,0x30}, }, /* auto hjt */ { {0x14,at2250_reg_0x14_val}, {0x15,0x22}, {0x16,0x88}, {0x17,0x30}, }, /* iso 100 */ { {0x14,at2250_reg_0x14_val-0x30}, {0x15,0x22}, {0x16,0x88}, {0x17,0x28}, }, /* iso 200 */ { {0x14,at2250_reg_0x14_val-0x20}, {0x15,0x22}, {0x16,0x88}, {0x17,0x28}, }, /* iso 400 */ { {0x14,at2250_reg_0x14_val-0x10}, {0x15,0x22}, {0x16,0x88}, {0x17,0x28}, }, /* iso 800 */ { {0x14,at2250_reg_0x14_val+0x10}, {0x15,0x22}, {0x16,0x88}, {0x17,0x30}, }, /* iso 1600 */ { {0x14,at2250_reg_0x14_val+0x20}, {0x15,0x22}, {0x16,0x88}, {0x17,0x30} }, }; static struct msm_camera_i2c_reg_conf AT2250_reg_exposure_compensation[5][4] = { /* -2 */ { {0x14,at2250_reg_0x14_val-0x20}, {0x15,0x22}, {0x16,0x88}, {0x17,0x24}, }, /* -1 */ { {0x14,at2250_reg_0x14_val-0x10}, {0x15,0x22}, {0x16,0x88}, {0x17,0x28}, }, /* 0 */ { {0x14,at2250_reg_0x14_val}, {0x15,0x22}, {0x16,0x88}, {0x17,0x30}, }, /* 1 */ { {0x14,at2250_reg_0x14_val+0x10}, {0x15,0x22}, {0x16,0x88}, {0x17,0x30}, }, /* 2 */ { {0x14,at2250_reg_0x14_val+0x20}, {0x15,0x22}, {0x16,0x88}, {0x17,0x30}, }, }; static struct msm_camera_i2c_reg_conf AT2250_reg_antibanding[][2] = { /* OFF */ { {0x18, 0x74}, // ba {0x19, 0x91}, }, /* 50Hz */ { {0x18, 0x74}, // ba {0x19, 0x91}, }, /* 60Hz */ { {0x18, 0x36}, // 9b {0x19, 0x91}, }, /* AUTO */ { {0x18, 0x74}, // ba {0x19, 0x91}, }, }; static struct msm_camera_i2c_reg_conf AT2250_reg_effect_normal[] = { /* normal: */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_effect_black_white[] = { /* B&W: */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_effect_negative[] = { /* Negative: */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_effect_old_movie[] = { /* Sepia(antique): */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_effect_solarize[] = { {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_scene_auto[] = { /* <SCENE_auto> */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_scene_portrait[] = { /* <CAMTUNING_SCENE_PORTRAIT> */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_scene_landscape[] = { /* <CAMTUNING_SCENE_LANDSCAPE> */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_scene_night[] = { /* <SCENE_NIGHT> */ {0xff,0xff}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_wb_auto[] = { /* Auto: */ {0x05,0xcc}, {0x06,0x00}, {0x07,0x60}, {0x08,0x54}, {0x09,0x04}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_wb_sunny[] = { /* Sunny: */ {0x05, 0xa0}, {0x06, 0x10}, {0x07, 0x00}, {0x08, 0x43}, {0x09, 0x03}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_wb_cloudy[] = { /* Cloudy: */ {0x05, 0x60}, {0x06, 0x00}, {0x07, 0xd6}, {0x08, 0x64}, {0x09, 0x03}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_wb_office[] = { /* Office: */ {0x05, 0x60}, {0x06, 0x00}, {0x07, 0xab}, {0x08, 0x54}, {0x09, 0x05}, }; static struct msm_camera_i2c_reg_conf AT2250_reg_wb_home[] = { /* Home: */ {0x05, 0x32}, {0x06, 0x00}, {0x07, 0xfd}, {0x08, 0x44}, {0x09, 0x05}, }; #ifdef ONLINE_DEBUG//for debug online static u32 cur_reg=0; static u8 cur_val; static void at2250_i2c_write(struct msm_sensor_ctrl_t *s_ctrl, uint8_t reg_addr, uint8_t reg_data); static uint8_t at2250_i2c_read(struct msm_sensor_ctrl_t *s_ctrl, uint8_t reg_addr); static ssize_t fcam_show(struct device *dev, struct device_attribute *attr, char *_buf) { return sprintf(_buf, "0x%02x=0x%02x\n", cur_reg, cur_val); } static u32 strtol(const char *nptr, int base) { u32 ret; if(!nptr || (base!=16 && base!=10 && base!=8)) { printk("%s(): NULL pointer input\n", __FUNCTION__); return -1; } for(ret=0; *nptr; nptr++) { if((base==16 && *nptr>='A' && *nptr<='F') || (base==16 && *nptr>='a' && *nptr<='f') || (base>=10 && *nptr>='0' && *nptr<='9') || (base>=8 && *nptr>='0' && *nptr<='7') ) { ret *= base; if(base==16 && *nptr>='A' && *nptr<='F') ret += *nptr-'A'+10; else if(base==16 && *nptr>='a' && *nptr<='f') ret += *nptr-'a'+10; else if(base>=10 && *nptr>='0' && *nptr<='9') ret += *nptr-'0'; else if(base>=8 && *nptr>='0' && *nptr<='7') ret += *nptr-'0'; } else return ret; } return ret; } static ssize_t fcam_store(struct device *dev, struct device_attribute *attr, const char *_buf, size_t _count) { const char * p=_buf; uint16_t reg; uint16_t val; if(!strncmp(_buf, "get", strlen("get"))) { p+=strlen("get"); cur_reg=(u32)strtol(p, 16); val = at2250_i2c_read(&at2250_s_ctrl, cur_reg); printk("%s(): get 0x%04x=0x%02x\n", __FUNCTION__, cur_reg, val); cur_val=val; } else if(!strncmp(_buf, "put", strlen("put"))) { p+=strlen("put"); reg=strtol(p, 16); p=strchr(_buf, '='); if(p) { ++ p; val=strtol(p, 16); at2250_i2c_write(&at2250_s_ctrl, reg, val); printk("%s(): set 0x%04x=0x%02x\n", __FUNCTION__, reg, val); } else printk("%s(): Bad string format input!\n", __FUNCTION__); } else printk("%s(): Bad string format input!\n", __FUNCTION__); return _count; } static ssize_t currreg_show(struct device *dev, struct device_attribute *attr, char *_buf) { strcpy(_buf, "SP0A28\n"); return 8; } static struct device *fcam_dev = NULL; static struct class * fcam_class = NULL; static DEVICE_ATTR(fcam, 0666, fcam_show, fcam_store); static DEVICE_ATTR(currreg, 0666, currreg_show, NULL); #endif static const struct i2c_device_id at2250_i2c_id[] = { {AT2250_SENSOR_NAME, (kernel_ulong_t)&at2250_s_ctrl}, { } }; static int32_t msm_at2250_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc = 0; rc=msm_sensor_i2c_probe(client, id, &at2250_s_ctrl); #ifdef ONLINE_DEBUG//for online debug fcam_class = class_create(THIS_MODULE, "fcam"); if (IS_ERR(fcam_class)) { printk("Create class fcam.\n"); return -ENOMEM; } fcam_dev = device_create(fcam_class, NULL, MKDEV(0, 1), NULL, "dev"); rc = device_create_file(fcam_dev, &dev_attr_fcam); rc = device_create_file(fcam_dev, &dev_attr_currreg); #endif return rc; } static struct i2c_driver at2250_i2c_driver = { .id_table = at2250_i2c_id, .probe = msm_at2250_i2c_probe, .driver = { .name = AT2250_SENSOR_NAME, }, }; static struct msm_camera_i2c_client at2250_sensor_i2c_client = { .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, }; static const struct of_device_id at2250_dt_match[] = { {.compatible = "shinetech,at2250", .data = &at2250_s_ctrl}, {} }; MODULE_DEVICE_TABLE(of, at2250_dt_match); static struct platform_driver at2250_platform_driver = { .driver = { .name = "shinetech,at2250", .owner = THIS_MODULE, .of_match_table = at2250_dt_match, }, }; static void at2250_i2c_write(struct msm_sensor_ctrl_t *s_ctrl, uint8_t reg_addr, uint8_t reg_data) { //int i = 0; int rc = 0; //for (i = 0; i < num; ++i) { rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write( s_ctrl->sensor_i2c_client, reg_addr, reg_data, MSM_CAMERA_I2C_BYTE_DATA); // table++; //} } static uint8_t at2250_i2c_read(struct msm_sensor_ctrl_t *s_ctrl, uint8_t reg_addr) { //int i = 0; int rc = 0; uint16_t reg_data=0 ; //for (i = 0; i < num; ++i) { rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_read( s_ctrl->sensor_i2c_client,reg_addr, ®_data, MSM_CAMERA_I2C_BYTE_DATA); // table++; //} return reg_data; } static void at2250_i2c_write_table(struct msm_sensor_ctrl_t *s_ctrl, struct msm_camera_i2c_reg_conf *table, int num) { int i = 0; int rc = 0; for (i = 0; i < num; ++i) { rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write( s_ctrl->sensor_i2c_client, table->reg_addr, table->reg_data, MSM_CAMERA_I2C_BYTE_DATA); if (rc < 0) { msleep(100); rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write( s_ctrl->sensor_i2c_client, table->reg_addr, table->reg_data, MSM_CAMERA_I2C_BYTE_DATA); } table++; } } static int32_t at2250_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl) { at2250_i2c_write_table(s_ctrl, &at2250_sleep_settings[0], ARRAY_SIZE(at2250_sleep_settings)); return msm_sensor_power_down(s_ctrl); } static int32_t at2250_platform_probe(struct platform_device *pdev) { int32_t rc; const struct of_device_id *match; match = of_match_device(at2250_dt_match, &pdev->dev); rc = msm_sensor_platform_probe(pdev, match->data); return rc; } static int __init at2250_init_module(void) { int32_t rc; pr_err("%s:%d\n", __func__, __LINE__); rc = platform_driver_probe(&at2250_platform_driver, at2250_platform_probe); if (!rc) return rc; return i2c_add_driver(&at2250_i2c_driver); } static void __exit at2250_exit_module(void) { pr_info("%s:%d\n", __func__, __LINE__); if (at2250_s_ctrl.pdev) { msm_sensor_free_sensor_data(&at2250_s_ctrl); platform_driver_unregister(&at2250_platform_driver); } else i2c_del_driver(&at2250_i2c_driver); return; } static int32_t at2250_sensor_match_id(struct msm_sensor_ctrl_t *s_ctrl) { int32_t rc = 0; uint16_t chipid = 0; pr_err("%s: %d: %d:at2250 start\n", __func__, s_ctrl->sensordata->slave_info->sensor_id_reg_addr,MSM_CAMERA_I2C_BYTE_DATA); rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_read( s_ctrl->sensor_i2c_client, s_ctrl->sensordata->slave_info->sensor_id_reg_addr, &chipid, MSM_CAMERA_I2C_BYTE_DATA); if (rc < 0) { pr_err("%s: %s: at2250 read id failed\n", __func__, s_ctrl->sensordata->sensor_name); return rc; } CDBG("%s: read id: %x expected id %x:\n", __func__, chipid, s_ctrl->sensordata->slave_info->sensor_id); if (chipid != s_ctrl->sensordata->slave_info->sensor_id) { pr_err("msm_sensor_match_id chip id doesnot match\n"); return -ENODEV; } return rc; } static void at2250_set_stauration(struct msm_sensor_ctrl_t *s_ctrl, int value) { int i; #ifdef CLOSE_FUNCTION return; #endif pr_debug("%s %d", __func__, value); for(i=0xc0;i<=0xff;i++) { at2250_i2c_write(s_ctrl,i,0xff); } at2250_i2c_write_table(s_ctrl, &AT2250_reg_saturation[value][0], ARRAY_SIZE(AT2250_reg_saturation[value])); } static void at2250_set_contrast(struct msm_sensor_ctrl_t *s_ctrl, int value) { #ifdef CLOSE_FUNCTION return; #endif pr_debug("%s %d", __func__, value); at2250_i2c_write_table(s_ctrl, &AT2250_reg_contrast[value][0], ARRAY_SIZE(AT2250_reg_contrast[value])); } static void at2250_set_sharpness(struct msm_sensor_ctrl_t *s_ctrl, int value) { int val; #ifdef CLOSE_FUNCTION return; #endif val = value / 6; pr_debug("%s %d", __func__, value); at2250_i2c_write_table(s_ctrl, &AT2250_reg_sharpness[val][0], ARRAY_SIZE(AT2250_reg_sharpness[val])); } static void at2250_set_iso(struct msm_sensor_ctrl_t *s_ctrl, int value) { #ifdef CLOSE_FUNCTION return; #endif pr_debug("%s %d", __func__, value); at2250_i2c_write_table(s_ctrl, &AT2250_reg_iso[value][0], ARRAY_SIZE(AT2250_reg_iso[value])); } static void at2250_set_exposure_compensation(struct msm_sensor_ctrl_t *s_ctrl, int value) { int val; #ifdef CLOSE_FUNCTION return; #endif val = (value + 12) / 6; pr_debug("%s %d", __func__, val); at2250_i2c_write_table(s_ctrl, &AT2250_reg_exposure_compensation[val][0], ARRAY_SIZE(AT2250_reg_exposure_compensation[val])); } static void at2250_set_effect(struct msm_sensor_ctrl_t *s_ctrl, int value) { #ifdef CLOSE_FUNCTION return; #else uint8_t reg0x37; uint8_t reg0x7e; uint8_t reg0x45; uint8_t reg0x47; uint8_t reg0x36; reg0x37 = at2250_i2c_read(s_ctrl,0x37); reg0x7e = at2250_i2c_read(s_ctrl,0x7e); reg0x45 = at2250_i2c_read(s_ctrl,0x45); reg0x47 = at2250_i2c_read(s_ctrl,0x47); reg0x36 = at2250_i2c_read(s_ctrl,0x36); pr_debug("%s %d", __func__, value); switch (value) { case MSM_CAMERA_EFFECT_MODE_OFF: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_effect_normal[0], ARRAY_SIZE(AT2250_reg_effect_normal)); at2250_i2c_write(s_ctrl,0x37, reg0x37 & 0xef); at2250_i2c_write(s_ctrl,0x7e, (reg0x7e &= 0xf4)); at2250_i2c_write(s_ctrl,0x45, reg0x45 & 0x7f); at2250_i2c_write(s_ctrl,0x47, reg0x47 & 0xfa); at2250_i2c_write(s_ctrl,0x36, reg0x36 & 0x7f); at2250_i2c_write(s_ctrl,0x7b, 0x00); at2250_i2c_write(s_ctrl,0x7c, 0x00); at2250_i2c_write(s_ctrl,0x79, 0x00); at2250_i2c_write(s_ctrl,0x7a, 0x00); at2250_i2c_write(s_ctrl,0x7d, 0x00); at2250_i2c_write(s_ctrl,0x7f, 0x80); break; } case MSM_CAMERA_EFFECT_MODE_MONO: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_effect_black_white[0], ARRAY_SIZE(AT2250_reg_effect_black_white)); at2250_i2c_write(s_ctrl,0x37, reg0x37 & 0xef); at2250_i2c_write(s_ctrl,0x7e, (reg0x7e &= 0xf4)); at2250_i2c_write(s_ctrl,0x7e, reg0x7e | 0x08); at2250_i2c_write(s_ctrl,0x45, reg0x45 & 0x7f); at2250_i2c_write(s_ctrl,0x47, reg0x47 & 0xfa); at2250_i2c_write(s_ctrl,0x36, reg0x36 & 0x7f); at2250_i2c_write(s_ctrl,0x7b, 0x00); at2250_i2c_write(s_ctrl,0x7c, 0x00); at2250_i2c_write(s_ctrl,0x7d, 0x20); at2250_i2c_write(s_ctrl,0x79, 0xff); at2250_i2c_write(s_ctrl,0x7a, 0xff); at2250_i2c_write(s_ctrl,0x7f, 0xb0); break; } case MSM_CAMERA_EFFECT_MODE_NEGATIVE: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_effect_negative[0], ARRAY_SIZE(AT2250_reg_effect_negative)); at2250_i2c_write(s_ctrl,0x37, reg0x37 | 0x10); at2250_i2c_write(s_ctrl,0x7e, (reg0x7e &= 0xf4)); at2250_i2c_write(s_ctrl,0x45, reg0x45 | 0x80); at2250_i2c_write(s_ctrl,0x47, reg0x47 | 0x05); at2250_i2c_write(s_ctrl,0x36, reg0x36 | 0x80); at2250_i2c_write(s_ctrl,0x7b, 0x00); at2250_i2c_write(s_ctrl,0x7c, 0x00); at2250_i2c_write(s_ctrl,0x79, 0x00); at2250_i2c_write(s_ctrl,0x7a, 0x00); at2250_i2c_write(s_ctrl,0x7d, 0x00); at2250_i2c_write(s_ctrl,0x7f, 0x80); break; } case MSM_CAMERA_EFFECT_MODE_SEPIA: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_effect_old_movie[0], ARRAY_SIZE(AT2250_reg_effect_old_movie)); at2250_i2c_write(s_ctrl,0x37, reg0x37 & 0xef); at2250_i2c_write(s_ctrl,0x7e, (reg0x7e &= 0xf4)); at2250_i2c_write(s_ctrl,0x7e, reg0x7e | 0x01); at2250_i2c_write(s_ctrl,0x45, reg0x45 & 0x7f); at2250_i2c_write(s_ctrl,0x47, reg0x47 & 0xfa); at2250_i2c_write(s_ctrl,0x36, reg0x36 & 0x7f); at2250_i2c_write(s_ctrl,0x7b, 0x20); at2250_i2c_write(s_ctrl,0x7c, 0x20); at2250_i2c_write(s_ctrl,0x79, 0x00); at2250_i2c_write(s_ctrl,0x7a, 0x00); at2250_i2c_write(s_ctrl,0x7f, 0x80); break; } case MSM_CAMERA_EFFECT_MODE_SOLARIZE: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_effect_solarize[0], ARRAY_SIZE(AT2250_reg_effect_solarize)); break; } default: at2250_i2c_write_table(s_ctrl, &AT2250_reg_effect_normal[0], ARRAY_SIZE(AT2250_reg_effect_normal)); at2250_i2c_write(s_ctrl,0x37, reg0x37 & 0xef); at2250_i2c_write(s_ctrl,0x7e, (reg0x7e &= 0xf4)); at2250_i2c_write(s_ctrl,0x45, reg0x45 & 0x7f); at2250_i2c_write(s_ctrl,0x47, reg0x47 & 0xfa); at2250_i2c_write(s_ctrl,0x36, reg0x36 & 0x7f); at2250_i2c_write(s_ctrl,0x7b, 0x00); at2250_i2c_write(s_ctrl,0x7c, 0x00); at2250_i2c_write(s_ctrl,0x79, 0x00); at2250_i2c_write(s_ctrl,0x7a, 0x00); at2250_i2c_write(s_ctrl,0x7d, 0x00); at2250_i2c_write(s_ctrl,0x7f, 0x80); } #endif } static void at2250_set_antibanding(struct msm_sensor_ctrl_t *s_ctrl, int value) { #ifdef CLOSE_FUNCTION return; #endif pr_debug("%s %d", __func__, value); at2250_i2c_write_table(s_ctrl, &AT2250_reg_antibanding[value][0], ARRAY_SIZE(AT2250_reg_antibanding[value])); } static void at2250_set_scene_mode(struct msm_sensor_ctrl_t *s_ctrl, int value) { #ifdef CLOSE_FUNCTION return; #endif pr_debug("%s %d", __func__, value); switch (value) { case MSM_CAMERA_SCENE_MODE_OFF: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_scene_auto[0], ARRAY_SIZE(AT2250_reg_scene_auto)); at2250_i2c_write(s_ctrl,0x13, 0x8e); break; } case MSM_CAMERA_SCENE_MODE_NIGHT: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_scene_night[0], ARRAY_SIZE(AT2250_reg_scene_night)); at2250_i2c_write(s_ctrl,0xe0, 0x13); at2250_i2c_write(s_ctrl,0xe1, 0x96); at2250_i2c_write(s_ctrl,0x1f, 0x41); break; } case MSM_CAMERA_SCENE_MODE_LANDSCAPE: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_scene_landscape[0], ARRAY_SIZE(AT2250_reg_scene_landscape)); break; } case MSM_CAMERA_SCENE_MODE_PORTRAIT: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_scene_portrait[0], ARRAY_SIZE(AT2250_reg_scene_portrait)); break; } default: at2250_i2c_write_table(s_ctrl, &AT2250_reg_scene_auto[0], ARRAY_SIZE(AT2250_reg_scene_auto)); } } static void at2250_set_white_balance_mode(struct msm_sensor_ctrl_t *s_ctrl, int value) { #ifdef CLOSE_FUNCTION return; #endif uint8_t reg0x36; reg0x36 = at2250_i2c_read(s_ctrl,0x36); pr_debug("%s %d", __func__, value); switch (value) { case MSM_CAMERA_WB_MODE_AUTO: { at2250_i2c_write_table(s_ctrl, &AT2250_reg_wb_auto[0], ARRAY_SIZE(AT2250_reg_wb_auto)); at2250_i2c_write(s_ctrl,0x36, reg0x36|0x01); break; } case MSM_CAMERA_WB_MODE_INCANDESCENT: { at2250_i2c_write(s_ctrl,0x36, reg0x36&0xfe); at2250_i2c_write_table(s_ctrl, &AT2250_reg_wb_home[0], ARRAY_SIZE(AT2250_reg_wb_home)); break; } case MSM_CAMERA_WB_MODE_DAYLIGHT: { at2250_i2c_write(s_ctrl,0x36, reg0x36&0xfe); at2250_i2c_write_table(s_ctrl, &AT2250_reg_wb_sunny[0], ARRAY_SIZE(AT2250_reg_wb_sunny)); break; } case MSM_CAMERA_WB_MODE_FLUORESCENT: { at2250_i2c_write(s_ctrl,0x36, reg0x36&0xfe); at2250_i2c_write_table(s_ctrl, &AT2250_reg_wb_office[0], ARRAY_SIZE(AT2250_reg_wb_office)); break; } case MSM_CAMERA_WB_MODE_CLOUDY_DAYLIGHT: { at2250_i2c_write(s_ctrl,0x36, reg0x36&0xfe); at2250_i2c_write_table(s_ctrl, &AT2250_reg_wb_cloudy[0], ARRAY_SIZE(AT2250_reg_wb_cloudy)); break; } default: at2250_i2c_write_table(s_ctrl, &AT2250_reg_wb_auto[0], ARRAY_SIZE(AT2250_reg_wb_auto)); } } int32_t at2250_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp) { struct sensorb_cfg_data *cdata = (struct sensorb_cfg_data *)argp; long rc = 0; int32_t i = 0; mutex_lock(s_ctrl->msm_sensor_mutex); CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__, s_ctrl->sensordata->sensor_name, cdata->cfgtype); switch (cdata->cfgtype) { case CFG_GET_SENSOR_INFO: memcpy(cdata->cfg.sensor_info.sensor_name, s_ctrl->sensordata->sensor_name, sizeof(cdata->cfg.sensor_info.sensor_name)); cdata->cfg.sensor_info.session_id = s_ctrl->sensordata->sensor_info->session_id; for (i = 0; i < SUB_MODULE_MAX; i++) cdata->cfg.sensor_info.subdev_id[i] = s_ctrl->sensordata->sensor_info->subdev_id[i]; CDBG("%s:%d sensor name %s\n", __func__, __LINE__, cdata->cfg.sensor_info.sensor_name); CDBG("%s:%d session id %d\n", __func__, __LINE__, cdata->cfg.sensor_info.session_id); for (i = 0; i < SUB_MODULE_MAX; i++) CDBG("%s:%d subdev_id[%d] %d\n", __func__, __LINE__, i, cdata->cfg.sensor_info.subdev_id[i]); break; case CFG_SET_INIT_SETTING: CDBG("init setting"); at2250_i2c_write_table(s_ctrl, &at2250_recommend_settings[0], ARRAY_SIZE(at2250_recommend_settings)); for(i=0xc0;i<=0xff;i++) { at2250_i2c_write(s_ctrl,i,0xff); } for(i=0;i<ARRAY_SIZE(at2250_recommend_settings);i++) { CDBG(" AT2250 %x = %x \n", at2250_recommend_settings[i].reg_addr,at2250_i2c_read(s_ctrl,at2250_recommend_settings[i].reg_addr)); } CDBG("init setting X"); break; case CFG_SET_RESOLUTION: { int val = 0; if (copy_from_user(&val, (void *)cdata->cfg.setting, sizeof(int))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } CDBG(" AT2250 resolution val = %d\n",val); if (val == 0) { if(get_hipad_board_id()==HIPAD_BOARD_ID_CP5310){ printk("get_hipad_board_id is HIPAD_BOARD_ID_CP5310 \n"); at2250_i2c_write_table(s_ctrl, &at2250_uxga1_settings[0], ARRAY_SIZE(at2250_uxga1_settings)); for(i=0;i<ARRAY_SIZE(at2250_uxga1_settings);i++) { CDBG(" AT2250 %x = %x \n", at2250_uxga1_settings[i].reg_addr,at2250_i2c_read(s_ctrl,at2250_uxga1_settings[i].reg_addr)); } } else { printk("get_hipad_board_id is HIPAD_BOARD_ID_CP5217 or other \n"); at2250_i2c_write_table(s_ctrl, &at2250_uxga1_settings[0], ARRAY_SIZE(at2250_uxga1_settings)); for(i=0;i<ARRAY_SIZE(at2250_uxga1_settings);i++) { CDBG(" AT2250 %x = %x \n", at2250_uxga1_settings[i].reg_addr,at2250_i2c_read(s_ctrl,at2250_uxga1_settings[i].reg_addr)); } } } else if (val == 1) { at2250_i2c_write_table(s_ctrl, &at2250_svga_settings[0], ARRAY_SIZE(at2250_svga_settings)); for(i=0;i<ARRAY_SIZE(at2250_svga_settings);i++) { CDBG(" AT2250 %x = %x \n", at2250_svga_settings[i].reg_addr,at2250_i2c_read(s_ctrl,at2250_svga_settings[i].reg_addr)); } } break; } case CFG_SET_STOP_STREAM: CDBG(" at2250 stop stream \n "); at2250_i2c_write_table(s_ctrl, &at2250_stop_settings[0], ARRAY_SIZE(at2250_stop_settings)); break; case CFG_SET_START_STREAM: CDBG(" at2250 start stream \n "); at2250_i2c_write_table(s_ctrl, &at2250_start_settings[0], ARRAY_SIZE(at2250_start_settings)); break; case CFG_GET_SENSOR_INIT_PARAMS: cdata->cfg.sensor_init_params = *s_ctrl->sensordata->sensor_init_params; CDBG("%s:%d init params mode %d pos %d mount %d\n", __func__, __LINE__, cdata->cfg.sensor_init_params.modes_supported, cdata->cfg.sensor_init_params.position, cdata->cfg.sensor_init_params.sensor_mount_angle); break; case CFG_SET_SLAVE_INFO: { struct msm_camera_sensor_slave_info sensor_slave_info; struct msm_sensor_power_setting_array *power_setting_array; int slave_index = 0; if (copy_from_user(&sensor_slave_info, (void *)cdata->cfg.setting, sizeof(struct msm_camera_sensor_slave_info))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } /* Update sensor slave address */ if (sensor_slave_info.slave_addr) { s_ctrl->sensor_i2c_client->cci_client->sid = sensor_slave_info.slave_addr >> 1; } /* Update sensor address type */ s_ctrl->sensor_i2c_client->addr_type = sensor_slave_info.addr_type; /* Update power up / down sequence */ s_ctrl->power_setting_array = sensor_slave_info.power_setting_array; power_setting_array = &s_ctrl->power_setting_array; power_setting_array->power_setting = kzalloc( power_setting_array->size * sizeof(struct msm_sensor_power_setting), GFP_KERNEL); if (!power_setting_array->power_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(power_setting_array->power_setting, (void *) sensor_slave_info.power_setting_array.power_setting, power_setting_array->size * sizeof(struct msm_sensor_power_setting))) { kfree(power_setting_array->power_setting); pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } s_ctrl->free_power_setting = true; CDBG("%s sensor id %x\n", __func__, sensor_slave_info.slave_addr); CDBG("%s sensor addr type %d\n", __func__, sensor_slave_info.addr_type); CDBG("%s sensor reg %x\n", __func__, sensor_slave_info.sensor_id_info.sensor_id_reg_addr); CDBG("%s sensor id %x\n", __func__, sensor_slave_info.sensor_id_info.sensor_id); for (slave_index = 0; slave_index < power_setting_array->size; slave_index++) { CDBG("%s i %d power setting %d %d %ld %d\n", __func__, slave_index, power_setting_array->power_setting[slave_index]. seq_type, power_setting_array->power_setting[slave_index]. seq_val, power_setting_array->power_setting[slave_index]. config_val, power_setting_array->power_setting[slave_index]. delay); } kfree(power_setting_array->power_setting); break; } case CFG_WRITE_I2C_ARRAY: { struct msm_camera_i2c_reg_setting conf_array; struct msm_camera_i2c_reg_array *reg_setting = NULL; if (copy_from_user(&conf_array, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = kzalloc(conf_array.size * (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(reg_setting, (void *)conf_array.reg_setting, conf_array.size * sizeof(struct msm_camera_i2c_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(reg_setting); rc = -EFAULT; break; } conf_array.reg_setting = reg_setting; rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table( s_ctrl->sensor_i2c_client, &conf_array); kfree(reg_setting); break; } case CFG_WRITE_I2C_SEQ_ARRAY: { struct msm_camera_i2c_seq_reg_setting conf_array; struct msm_camera_i2c_seq_reg_array *reg_setting = NULL; if (copy_from_user(&conf_array, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_seq_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = kzalloc(conf_array.size * (sizeof(struct msm_camera_i2c_seq_reg_array)), GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(reg_setting, (void *)conf_array.reg_setting, conf_array.size * sizeof(struct msm_camera_i2c_seq_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(reg_setting); rc = -EFAULT; break; } conf_array.reg_setting = reg_setting; rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_seq_table(s_ctrl->sensor_i2c_client, &conf_array); kfree(reg_setting); break; } case CFG_POWER_UP: if (s_ctrl->func_tbl->sensor_power_up) rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl); else rc = -EFAULT; break; case CFG_POWER_DOWN: if (s_ctrl->func_tbl->sensor_power_down) rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl); else rc = -EFAULT; break; case CFG_SET_STOP_STREAM_SETTING: { struct msm_camera_i2c_reg_setting *stop_setting = &s_ctrl->stop_setting; struct msm_camera_i2c_reg_array *reg_setting = NULL; if (copy_from_user(stop_setting, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = stop_setting->reg_setting; stop_setting->reg_setting = kzalloc(stop_setting->size * (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); if (!stop_setting->reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(stop_setting->reg_setting, (void *)reg_setting, stop_setting->size * sizeof(struct msm_camera_i2c_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(stop_setting->reg_setting); stop_setting->reg_setting = NULL; stop_setting->size = 0; rc = -EFAULT; break; } break; } case CFG_SET_SATURATION: { int32_t sat_lev; if (copy_from_user(&sat_lev, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: Saturation Value is %d", __func__, sat_lev); at2250_set_stauration(s_ctrl, sat_lev); break; } case CFG_SET_CONTRAST: { int32_t con_lev; if (copy_from_user(&con_lev, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: Contrast Value is %d", __func__, con_lev); at2250_set_contrast(s_ctrl, con_lev); break; } case CFG_SET_SHARPNESS: { int32_t shp_lev; if (copy_from_user(&shp_lev, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: Sharpness Value is %d", __func__, shp_lev); at2250_set_sharpness(s_ctrl, shp_lev); break; } case CFG_SET_ISO: { int32_t iso_lev; if (copy_from_user(&iso_lev, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: ISO Value is %d", __func__, iso_lev); at2250_set_iso(s_ctrl, iso_lev); break; } case CFG_SET_EXPOSURE_COMPENSATION: { int32_t ec_lev; if (copy_from_user(&ec_lev, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: Exposure compensation Value is %d", __func__, ec_lev); at2250_set_exposure_compensation(s_ctrl, ec_lev); break; } case CFG_SET_EFFECT: { int32_t effect_mode; if (copy_from_user(&effect_mode, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: Effect mode is %d", __func__, effect_mode); at2250_set_effect(s_ctrl, effect_mode); break; } case CFG_SET_ANTIBANDING: { int32_t antibanding_mode; if (copy_from_user(&antibanding_mode, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: anti-banding mode is %d", __func__, antibanding_mode); at2250_set_antibanding(s_ctrl, antibanding_mode); break; } case CFG_SET_BESTSHOT_MODE: { int32_t bs_mode; if (copy_from_user(&bs_mode, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: best shot mode is %d", __func__, bs_mode); at2250_set_scene_mode(s_ctrl, bs_mode); break; } case CFG_SET_WHITE_BALANCE: { int32_t wb_mode; if (copy_from_user(&wb_mode, (void *)cdata->cfg.setting, sizeof(int32_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_debug("%s: white balance is %d", __func__, wb_mode); at2250_set_white_balance_mode(s_ctrl, wb_mode); break; } default: rc = -EFAULT; break; } mutex_unlock(s_ctrl->msm_sensor_mutex); return rc; } static struct msm_sensor_fn_t at2250_sensor_func_tbl = { .sensor_config = at2250_sensor_config, .sensor_power_up = msm_sensor_power_up, .sensor_power_down = at2250_sensor_power_down, .sensor_match_id = at2250_sensor_match_id, }; static struct msm_sensor_ctrl_t at2250_s_ctrl = { .sensor_i2c_client = &at2250_sensor_i2c_client, .power_setting_array.power_setting = at2250_power_setting, .power_setting_array.size = ARRAY_SIZE(at2250_power_setting), .msm_sensor_mutex = &at2250_mut, .sensor_v4l2_subdev_info = at2250_subdev_info, .sensor_v4l2_subdev_info_size = ARRAY_SIZE(at2250_subdev_info), .func_tbl = &at2250_sensor_func_tbl, }; module_init(at2250_init_module); module_exit(at2250_exit_module); MODULE_DESCRIPTION("At2250 2MP YUV sensor driver"); MODULE_LICENSE("GPL v2");指令:
cd /sys/devices/virtual/fcam/dev
echo put12=02 > fcam
转载地址:http://jvomi.baihongyu.com/