os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/elphel/mt9x001.c

Go to the documentation of this file.
00001 /*!********************************************************************************
00002 *! FILE NAME  : mt9x001.c
00003 *! DESCRIPTION: sensor support for Micron image sensors:
00004 *! MT9M001(1280x1024)
00005 *! MT9D001(1600x1200)
00006 *! MT9T001(2048x1536)
00007 *! MT9P001/MT9P031(2592x1944)
00008 *!
00009 *! Copyright (C) 2004-2007 Elphel, Inc.
00010 *! -----------------------------------------------------------------------------**
00011 *!
00012 *!  This program is free software: you can redistribute it and/or modify
00013 *!  it under the terms of the GNU General Public License as published by
00014 *!  the Free Software Foundation, either version 3 of the License, or
00015 *!  (at your option) any later version.
00016 *!
00017 *!  This program is distributed in the hope that it will be useful,
00018 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 *!  GNU General Public License for more details.
00021 *!
00022 *!  You should have received a copy of the GNU General Public License
00023 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00024 *! -----------------------------------------------------------------------------**
00025 *!  $Log: mt9x001.c,v $
00026 *!  Revision 1.10  2008/07/23 02:24:57  elphel
00027 *!  typo
00028 *!
00029 *!  Revision 1.9  2008/05/02 15:13:35  elphel
00030 *!  switch to hardware i2c write,added related sensor parameters
00031 *!
00032 *!  Revision 1.8  2008/05/01 01:28:57  elphel
00033 *!  hardware i2c control - macros, variables
00034 *!
00035 *!  Revision 1.7  2008/03/20 22:29:30  elphel
00036 *!  added trigger-related code and parameters
00037 *!
00038 *!  Revision 1.6  2008/02/12 21:53:20  elphel
00039 *!  Modified I2c to support multiple buses, added raw access (no address registers) and per-slave protection bitmasks
00040 *!
00041 *!  Revision 1.5  2008/02/05 18:28:59  spectr_rain
00042 *!  correct timing for MT9P sensor with binning and skipping 1,2,4
00043 *!
00044 *!  Revision 1.4  2007/12/27 14:27:43  spectr_rain
00045 *!  fixed FPS, correct work with the skipping - TODO - check the binning
00046 *!
00047 *!  Revision 1.3  2007/10/16 23:17:51  elphel
00048 *!  cosmetic
00049 *!
00050 
00051 //  Revision 1.2  2007/10/16 20:03:38  elphel
00052 //  cosmetic
00053 //
00054 //  Revision 1.1.1.1  2007/09/30 03:19:56  elphel
00055 //  This is a fresh tree based on elphel353-2.10
00056 //
00057 //  Revision 1.12  2007/09/30 03:19:56  elphel
00058 //  Cleanup, fixed broken acquisition of individual JPEG images into circbuf (in mode 7)
00059 //
00060 //  Revision 1.11  2007/09/19 04:22:33  elphel
00061 //  fixed debug output
00062 //
00063 //  Revision 1.10  2007/09/19 00:34:21  elphel
00064 //  support for frame rate limiting, disabled extra debug  messages
00065 //
00066 //  Revision 1.9  2007/09/18 06:09:22  elphel
00067 //  support for merged P_FLIP, support fro P_FPSLM (fps limit mode) that allow to limit FPS (upper limit) and maintain FPS (lower limit) preventing exposure time to exceed one divided by fps limit
00068 //
00069 //  Revision 1.8  2007/09/12 18:05:35  spectr_rain
00070 //  *** empty log message ***
00071 //
00072 //  Revision 1.7  2007/08/17 10:23:19  spectr_rain
00073 //  switch to GPL3 license
00074 //
00075 //  Revision 1.6  2007/07/20 10:17:46  spectr_rain
00076 //  *** empty log message ***
00077 //
00078 //  Revision 1.10  2007/07/09 22:05:43  elphel
00079 //  minor sensor phase adjustment (constant so far)
00080 //
00081 //  Revision 1.9  2007/07/09 21:10:14  elphel
00082 //  Reducing EMI from the sensor front end cable by reducing the drive strengths on the lines. Improving phase adjustment (and phase error measurements) for the sensors. Dealing with the delayed (with respect to pixel data) line/frame valid signals in MT9P001 sensors
00083 //
00084 //  Revision 1.8  2007/07/09 05:15:17  elphel
00085 //  set slowest speed on the outputs to reduce EMI
00086 //
00087 //  Revision 1.7  2007/06/28 02:24:40  elphel
00088 //  Increased default frequency for 5MPix sensor to 96MHz
00089 //
00090 //  Revision 1.6  2007/06/18 07:57:24  elphel
00091 //  Fixed bug working with MT9P031 - added sensor reset/reinit after frequency change
00092 //
00093 //  Revision 1.5  2007/05/21 17:45:11  elphel
00094 //  boundary scan support, added 359/347 detection
00095 //
00096 //  Revision 1.4  2007/04/23 22:48:32  spectr_rain
00097 //  *** empty log message ***
00098 //
00099 //  Revision 1.3  2007/04/17 18:28:06  spectr_rain
00100 //  *** empty log message ***
00101 //
00102 //  Revision 1.2  2007/04/04 03:55:22  elphel
00103 //  Improved i2c, added i2c as character devices (to use from php)
00104 //
00105 //  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00106 //  initial import into CVS
00107 //
00108 //  Revision 1.12  2006/12/01 00:18:12  spectr_rain
00109 //  *** empty log message ***
00110 //
00111 //  Revision 1.11  2006/11/28 18:33:26  spectr_rain
00112 //  *** empty log message ***
00113 //
00114 //  Revision 1.9  2006/11/01 18:49:57  spectr_rain
00115 //  *** empty log message ***
00116 //
00117 //  Revision 1.8  2006/09/12 15:21:55  spectr_rain
00118 //  use ve for integration time if e == 0
00119 //
00120 //  Revision 1.7  2006/09/02 22:04:17  spectr_rain
00121 //  *** empty log message ***
00122 //
00123 //  Revision 1.6  2006/09/02 00:19:49  spectr_rain
00124 //  lock sensor while readrawimage
00125 //
00126 //  Revision 1.5  2006/07/17 12:22:42  spectr_rain
00127 //  enable autoexposition
00128 //
00129 //  Revision 1.4  2006/07/13 04:21:15  elphel
00130 //  mt9p031 now wants the same bayer as others - maybe DLYHOR bit was set earlier?
00131 //
00132 //  Revision 1.3  2006/07/12 19:32:49  spectr_rain
00133 //  fix Bayer pattern for less than 5MPx sensors
00134 //
00135 //  Revision 1.2  2006/07/12 06:03:16  elphel
00136 //  bug fix
00137 //
00138 //  Revision 1.1.1.1  2006/07/11 19:15:00  spectr_rain
00139 //  unwork with less than 5MPx Micron sensor, initial branch
00140 //
00141 //  Revision 1.25  2006/06/05 07:31:22  spectr_rain
00142 //  set blank vertical to 0 if pfh > 0
00143 //
00144 //  Revision 1.24  2006/02/16 03:37:06  elphel
00145 //  *** empty log message ***
00146 //
00147 //  Revision 1.23  2006/02/08 01:53:56  spectr_rain
00148 //  fix broken mutex in check of down_interruptible
00149 //
00150 //  Revision 1.22  2006/01/15 22:24:03  elphel
00151 //  bug fix, made binning a non-stop parameter
00152 //
00153 //  Revision 1.21  2006/01/15 13:03:27  spectr_rain
00154 //  fix deadlock
00155 //
00156 //  Revision 1.19  2006/01/12 03:52:14  elphel
00157 //  *** empty log message ***
00158 //
00159 //  Revision 1.18  2006/01/10 15:41:54  spectr_rain
00160 //  use gain compensation for color canal scale
00161 //
00162 //  Revision 1.17  2006/01/05 05:36:13  spectr_rain
00163 //  *** empty log message ***
00164 //
00165 //  Revision 1.15  2006/01/05 05:21:32  spectr_rain
00166 //  *** empty log message ***
00167 //
00168 //  Revision 1.14  2006/01/05 05:15:27  spectr_rain
00169 //  new sensitivity/scale iface
00170 //
00171 //  Revision 1.13  2006/01/05 00:01:21  elphel
00172 //  fixed hang-up - removed restarting a frame that was sometimes hanging a sensor until reset
00173 //
00174 //  Revision 1.12  2005/11/29 09:13:31  spectr_rain
00175 //  add autoexposure
00176 //
00177 //  Revision 1.11  2005/11/23 05:13:25  spectr_rain
00178 //  use exposition and gain with autoexposition
00179 //
00180 //  Revision 1.10  2005/11/22 09:21:01  elphel
00181 //  Fixed skipping of half frames, improved period calculation (not yet for binning modes)
00182 //
00183 //  Revision 1.9  2005/10/12 17:58:08  elphel
00184 //  fixed wrong fps reporting in mt9x001.c
00185 //
00186 //  Revision 1.8  2005/10/11 08:25:41  elphel
00187 //  fixed long exposures without slowing down sensor (especially for 3MPix sensor)
00188 //
00189 //  Revision 1.7  2005/09/15 22:46:51  elphel
00190 //  Fixed bug with 1.3MPix Micron sensor (introduced in previous release)
00191 //
00192 //  Revision 1.6  2005/09/10 23:33:22  elphel
00193 //  Support of realtime clock and timestamps in the images
00194 //
00195 //  Revision 1.5  2005/09/06 03:40:37  elphel
00196 //  changed parameters, added support for the photo-finish mode
00197 //
00198 //  Revision 1.4  2005/08/27 05:16:27  elphel
00199 //  binning
00200 //
00201 //  Revision 1.3  2005/08/27 00:46:39  elphel
00202 //  bayer control with &byr=
00203 //
00204 //  Revision 1.2  2005/05/10 21:08:49  elphel
00205 //  *** empty log message ***
00206 //
00207 
00208 */
00209 
00210 
00211 /****************** INCLUDE FILES SECTION ***********************************/
00212 
00213 #include <linux/module.h>
00214 #include <linux/sched.h>
00215 #include <linux/slab.h>
00216 
00217 #include <linux/time.h>
00218 
00219 
00220 #include <linux/errno.h>
00221 #include <linux/kernel.h>
00222 #include <linux/fs.h>
00223 #include <linux/string.h>
00224 #include <linux/init.h>
00225 #include <linux/autoconf.h>
00226 
00227 #include <asm/system.h>
00228 //#include <asm/svinto.h> // obsolete
00229 #include <asm/io.h>
00230 
00231 #include <asm/irq.h>
00232 
00233 #include <asm/delay.h>
00234 #include <asm/uaccess.h>
00235 #include <asm/elphel/c313a.h>
00236 
00237 #include "cc3x3.h"
00238 #include "cci2c.h"
00239 #include "mt9x001.h"
00240 #include "hist.h"
00241 
00242 //#define MD9(x) printk("%s:%d:",__FILE__,__LINE__);x
00243 #define MD9(x)
00244 //#define D(x) printk("%s:%d:",__FILE__,__LINE__);x
00245 #define D(x)
00246 //#define MD7(x) printk("%s:%d:",__FILE__,__LINE__);x
00247 #define MD7(x)
00248 
00249 #define DEFAULT_XTRA          1000   // number of pixel times to add to the frame compression time (just a guess)
00250 
00251 extern struct frame_params_t frame_params; // cc353.c
00252 
00253 struct sensor_t mt9m001={
00254 // sensor constants
00255    .imageWidth  = 1280,    //nominal image width for final images
00256    .imageHeight = 1024,    //nominal image height for final images
00257    .clearWidth  = 1289,    //maximal clear image width
00258    .clearHeight = 1033,    //maximal clear image height;
00259    .clearTop    = 8,       //top margin to the first clear pixel
00260    .clearLeft   = 16,      //left margin to the first clear pixel
00261    .arrayWidth  = 1312,    //total image array width (including black and boundary)
00262    .arrayHeight = 1048,    //total image array height (including black and boundary)
00263    .minWidth    = 4,       // minimal WOI width
00264    .minHeight   = 3,       // minimal WOI height
00265    .minHorBlank = 19,       // minimal horizontal blanking, in pixels in no-decimation, no-binning mode.
00266    .minLineDur  = 244,     // minimal total line duration, in pixels in no-decimation, no-binning mode.
00267    .maxHorBlank = 2047,    // maximal horizontal blanking/Virtual frame width (depends on sensor type)
00268    .minVertBlank= 16,       // minimal vertical blanking
00269    .maxVertBlank= 2047,    // maximal vertical blanking/Virtual frame height (depends on sensor type)
00270    .maxShutter  = 0x3fff,  // Maximal shutter duration (in lines)
00271    .flips       = 3,       // bit mask bit 0 - flipX, 1 - flipY
00272    .dcmHor      = 0x8b,    // 1,2,4,8
00273    .dcmVert     = 0x8b,    // 1,2,4,8
00274    .binHor      = 0x01,    // 1
00275    .binVert     = 0x01,    // 1
00276    .maxGain256  = 4032,    // (15.75) maximal analog gain times 0x100
00277    .maxClockFreq= 48000000, // Maximal clock frequency
00278    .nomClockFreq= 48000000, //nominal clock frequency
00279    .sensorType  = SENSOR_MT9X001 + MT9M_TYP,     // sensor type (for Elphel cameras)
00280    .i2c_addr    = MT9X001_I2C_ADDR,
00281    .i2c_period  = 2500,     // SCL period in ns, (standard i2c - 2500)
00282    .i2c_bytes   = 2,        // number of bytes/ register
00283    .margins     = 0,        // actually - property of FPGA code, not the sensor. Will be set in common sensor code
00284    .hact_delay  = 0,        // delay in ps, TBD
00285 // dynamic variables
00286    .pixelWidth  = 0,        // number of the pixels output in a line (including margins, decimation)
00287    .pixelHeight = 0,        // number of the lines output in a frame (including margins, decimation)
00288    .sensorPhase90=0,        // (0..3) 90-degree shift (fpcf -w 8 80)
00289    .sensorPhase = 0         // positive "fpcf -w 8 20", negative - "fpcf -w 8 10"
00290 
00291 };
00292 struct sensor_t mt9d001={
00293 // sensor constants
00294    .imageWidth  = 1600,    //nominal image width for final images
00295    .imageHeight = 1200,    //nominal image height for final images
00296    .clearWidth  = 1609,    //maximal clear image width
00297    .clearHeight = 1209,    //maximal clear image height;
00298    .clearTop    = 8,       //top margin to the first clear pixel
00299    .clearLeft   = 20,      //left margin to the first clear pixel
00300    .arrayWidth  = 1632,    //total image array width (including black and boundary)
00301    .arrayHeight = 1224,    //total image array height (including black and boundary)
00302    .minWidth    = 4,       // minimal WOI width
00303    .minHeight   = 3,       // minimal WOI height
00304    .minHorBlank = 19,      // minimal horizontal blanking, in pixels in no-decimation, no-binning mode.
00305    .minLineDur  = 617,     // minimal total line duration, in pixels in no-decimation, no-binning mode.
00306    .maxHorBlank = 2047,    // maximal horizontal blanking/Virtual frame width (depends on sensor type)
00307    .minVertBlank= 16,      // minimal vertical blanking
00308    .maxVertBlank= 2047,    // maximal vertical blanking/Virtual frame height (depends on sensor type)
00309    .maxShutter  = 0x3fff,  // Maximal shutter duration (in lines)
00310    .flips       = 3,       // bit mask bit 0 - flipX, 1 - flipY
00311    .dcmHor      = 0x8b,    // 1,2,4,8
00312    .dcmVert     = 0x8b,    // 1,2,4,8
00313    .binHor      = 0x01,    // 1
00314    .binVert     = 0x01,    // 1
00315    .maxGain256  = 4032,    // (15.75) maximal analog gain times 0x100
00316    .maxClockFreq= 48000000,      // Maximal clock frequency
00317    .nomClockFreq= 48000000,      //nominal clock frequency
00318    .sensorType  = SENSOR_MT9X001 + MT9D_TYP,     // sensor type (for Elphel cameras)
00319    .i2c_addr    = MT9X001_I2C_ADDR,
00320    .i2c_period  = 2500,     // SCL period in ns, (standard i2c - 2500)
00321    .i2c_bytes   = 2,        // number of bytes/ register
00322    .margins     = 0,        // actually - property of FPGA code, not the sensor. Will be set in common sensor code
00323    .hact_delay  = 0,        // delay in ps, TBD
00324 // dynamic variables
00325    .pixelWidth  = 0,       // number of the pixels output in a line (including margins, decimation)
00326    .pixelHeight = 0,        // number of the lines output in a frame (including margins, decimation)
00327    .sensorPhase90=0,        // (0..3) 90-degree shift (fpcf -w 8 80)
00328    .sensorPhase = 0         // positive "fpcf -w 8 20", negative - "fpcf -w 8 10"
00329 };
00330 struct sensor_t mt9t001={
00331 // sensor constants
00332    .imageWidth  = 2048,    //nominal image width for final images
00333    .imageHeight = 1536,    //nominal image height for final images
00334 //   .clearWidth  = 2047,    //maximal clear image width
00335    .clearWidth  = 2048,    //maximal clear image width
00336    .clearHeight = 1545,    //maximal clear image height;
00337    .clearTop    = 16,      //top margin to the first clear pixel
00338    .clearLeft   = 28,      //left margin to the first clear pixel
00339    .arrayWidth  = 2112,    //total image array width (including black and boundary)
00340    .arrayHeight = 1568,    //total image array height (including black and boundary)
00341    .minWidth    = 2,       // minimal WOI width
00342    .minHeight   = 2,       // minimal WOI height
00343    .minHorBlank = 21,      // minimal horizontal blanking, in pixels in no-decimation, no-binning mode.
00344    .minLineDur  = 511,     // minimal total line duration, in pixels in no-decimation, no-binning mode.
00345    .maxHorBlank = 2047,    // maximal horizontal blanking/Virtual frame width (depends on sensor type)
00346    .minVertBlank= 4,       // minimal vertical blanking
00347    .maxVertBlank= 2047,    // maximal vertical blanking/Virtual frame height (depends on sensor type)
00348    .maxShutter  = 0xfffff, // Maximal shutter duration (in lines)
00349    .flips       = 3,       // bit mask bit 0 - flipX, 1 - flipY
00350    .dcmHor      = 0xff,    // 1,2,3,4,5,6,7,8
00351    .dcmVert     = 0xff,    // 1,2,3,4,5,6,7,8
00352    .binHor      = 0xff,    // 1,2,3,4,5,6,7,8
00353    .binVert     = 0xff,    // 1,2,3,4,5,6,7,8
00354    .maxGain256  = 4032,    // (15.75) maximal analog gain times 0x100
00355    .maxClockFreq= 48000000,      // Maximal clock frequency
00356    .nomClockFreq= 48000000,       //nominal clock frequency
00357    .sensorType  = SENSOR_MT9X001 + MT9T_TYP,     // sensor type (for Elphel cameras)
00358    .i2c_addr    = MT9X001_I2C_ADDR,
00359    .i2c_period  = 2500,     // SCL period in ns, (standard i2c - 2500)
00360    .i2c_bytes   = 2,        // number of bytes/ register
00361    .margins     = 0,        // actually - property of FPGA code, not the sensor. Will be set in common sensor code
00362    .hact_delay  = 0,        // delay in ps, TBD
00363 // dynamic variables
00364    .pixelWidth  = 0,       // number of the pixels output in a line (including margins, decimation)
00365    .pixelHeight = 0,        // number of the lines output in a frame (including margins, decimation)
00366    .sensorPhase90=0,        // (0..3) 90-degree shift (fpcf -w 8 80)
00367    .sensorPhase = 0         // positive "fpcf -w 8 20", negative - "fpcf -w 8 10"
00368 };
00369 struct sensor_t mt9p001={
00370 // sensor constants
00371    .imageWidth  = 2592,    //nominal image width for final images
00372    .imageHeight = 1944,    //nominal image height for final images
00373    .clearWidth  = 2608,    //maximal clear image width
00374    .clearHeight = 1952,    //maximal clear image height;
00375    .clearTop    = 50,      //top margin to the first clear pixel
00376    .clearLeft   = 10,      //left margin to the first clear pixel
00377    .arrayWidth  = 2752,    //total image array width (including black and boundary)
00378    .arrayHeight = 2003,    //total image array height (including black and boundary)
00379    .minWidth    = 2,       // minimal WOI width
00380    .minHeight   = 2,       // minimal WOI height
00381    .minHorBlank = 0,       // minimal horizontal blanking, in pixels in no-decimation, no-binning mode.
00382    .minLineDur  = 647,     // minimal total line duration, in pixels in no-decimation, no-binning mode.
00383    .maxHorBlank = 4095,    // maximal horizontal blanking/Virtual frame width (depends on sensor type)
00384    .minVertBlank= 9,       // minimal vertical blanking
00385    .maxVertBlank= 2047,    // maximal vertical blanking/Virtual frame height (depends on sensor type)
00386    .maxShutter  = 0xfffff, // Maximal shutter duration (in lines)
00387    .flips       = 3,       // bit mask bit 0 - flipX, 1 - flipY
00388    .dcmHor      = 0xff,    // 1,2,3,4,5,6,7,8 (doc show [0,6] - change to 0x7f
00389    .dcmVert     = 0xff,    // 1,2,3,4,5,6,7,8
00390    .binHor      = 0xff,    // 1,2,4 0xb{0,1,3}
00391    .binVert     = 0xff,    // 1,2,3,4 0xf [0,3]
00392    .maxGain256  = 4032,    // (15.75) maximal analog gain times 0x100
00393    .maxClockFreq= 96000000,      // Maximal clock frequency
00394 //   .nomClockFreq= 48000000,       //nominal clock frequency
00395    .nomClockFreq= 96000000,       //nominal clock frequency - somethingv wrong in FPGA - needs a fix (fixed)
00396    .sensorType  = SENSOR_MT9X001 + MT9P_TYP,     // sensor type (for Elphel cameras)
00397    .i2c_addr    = MT9P001_I2C_ADDR,
00398    .i2c_period  = 2500,     // SCL period in ns, (standard i2c - 2500)
00399    .i2c_bytes   = 2,        // number of bytes/ register
00400    .margins     = 0,        // actually - property of FPGA code, not the sensor. Will be set in common sensor code
00401    .hact_delay  = 7500,     // 7.5ns delay in ps
00402 // dynamic variables
00403    .pixelWidth  = 0,       // number of the pixels output in a line (including margins, decimation)
00404    .pixelHeight = 0,        // number of the lines output in a frame (including margins, decimation)
00405    .sensorPhase90=0,        // (0..3) 90-degree shift (fpcf -w 8 80)
00406    .sensorPhase = -60         // positive "fpcf -w 8 20", negative - "fpcf -w 8 10" (slow drive, 96MHz, fpga rev 0353300f)
00407 };
00408 extern struct sensor_t sensor; // current sensor (will be copied to by sensor driver)
00409 static int mt9t_broken = 0x00; // what does it mean "broken" ? AF
00410 
00411 
00412 // **************************************************************
00413 //static int pf_stripes=0;      //number of stripes in a frame
00414 
00415 // a place to add some general purpose register writes to sensors during init
00416 
00417 static  unsigned int mt9m001_inits[]= \
00418   {
00419   };
00420 // just to fix id=8501 to 8511. Maybe just some are needed
00421 static  unsigned int mt9d001_inits[]= \
00422   {
00423    (P_MT9X001_CALTHRESH<<16) | 0xa39d,
00424    (P_MT9X001_CALCTRL<<16) | 0x8498
00425   };
00426 static  unsigned int mt9t001_inits[]= \
00427   {
00428   };
00429 
00430 static  unsigned int mt9p001_inits[]= \
00431   {
00432    (P_MT9X001_OUTCTRL<<16) | 0x2, // set slowesdt output signals (clock and non-clock) to reduce EMI (for FCC part 15)
00433    (P_MT9X001_7F     <<16) | 0x0  /* Should be written 0 to prevent blue "bluming" columns*/
00434   };
00435 
00436 
00437 
00438 /* **************************************************************
00439  * sensor detection/initialization.
00440  * Noramlly called once, but it is possible to force to rerun it
00441  * (i.e. to recover from sensor lock up)
00442  ****************************************************************
00443  */
00444 int     init_mt9x001(void) {
00445   unsigned char d[3];
00446   int i;
00447   int styp=0;
00448 //   struct timeval tv_b;
00449 //   struct timeval tv_e;
00450    unsigned char r[3];
00451    unsigned char w[3];
00452    int f;
00453    int first;
00454   d[0]=P_MT9X001_CHIPVER;
00455   struct sensor_t * psensor; // current sensor
00456 
00457 // try MT9P001 first
00458   psensor= &mt9p001;
00459 
00460   i2c_writeData(0, (psensor->i2c_addr) & 0xfe,  &d[0], 1, 0); // no stop before read
00461   i2c_readData (0, (psensor->i2c_addr) | 1,     &d[1], 2, 0); //restart, not strart
00462   printk("sensor id= 0x%x\r\n",d[1]);
00463   if (((((d[1]<<8)+d[2]) ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) {
00464     printk("Found MT9P001 2592x1944 sensor, chip ID=%x\n",(d[1]<<8)+d[2]);
00465     styp=MT9P_TYP; //1;
00466     if(d[2] == 0x01)  mt9t_broken = 1; // what is it "broken"? Andrey
00467     set_imageParamsR(P_SENSOR,SENSOR_MT9X001+styp);
00468   }
00469   if (styp ==0)  { // not a 5MPix chip
00470     psensor= &mt9m001; //address the same for all others
00471     i2c_writeData(0, (psensor->i2c_addr) & 0xfe, &d[0], 1, 0); // no stop before read
00472     i2c_readData (0, (psensor->i2c_addr) | 1,     &d[1], 2, 0); //restart, not strart
00473     printk("-sensor id= 0x%x\r\n",d[1]);
00474     if (((((d[1]<<8)+d[2])^MT9M001_PARTID) & MT9X001_PARTIDMASK)==0) {
00475       printk("Found MT9M001 1280x1024 sensor, chip ID=%x\r\n",(d[1]<<8)+d[2]);
00476       psensor= &mt9m001;
00477       styp=MT9M_TYP; //1;
00478     } else if (((((d[1]<<8)+d[2])^MT9D001_PARTID) & MT9X001_PARTIDMASK)==0) {
00479       printk("Found MT9D001 1600x1200 sensor, chip ID=%x\r\n",(d[1]<<8)+d[2]);
00480       psensor= &mt9d001; 
00481       styp=MT9D_TYP; //2;
00482     } else if (((((d[1]<<8)+d[2])^MT9T001_PARTID) & MT9X001_PARTIDMASK)==0) {
00483       printk("Found MT9T001 2048x1536 sensor, chip ID=%x\r\n",(d[1]<<8)+d[2]);
00484       psensor= &mt9t001;
00485       styp=MT9T_TYP; //3;
00486       if(d[2] == 0x01)
00487       mt9t_broken = 1;
00488     }
00489    if (styp>0)   set_sensor_i2c_addr(MT9X001_I2C_ADDR);
00490   }
00491   if (styp ==0)   return 0;  // no sensor found
00492   memcpy(&sensor, psensor, sizeof(mt9p001));
00493   MD7(printk("copied %d bytes of sensor parameters\r\n",sizeof(mt9p001)));
00494 
00495   set_sensor_i2c_addr(sensor.i2c_addr);
00496 //  set_imageParamsR(P_SENSOR,sensor.sensorType);
00497     printk("Initializing MT9X001 registers with default values:\r\n");
00498 //#if 0
00499 
00500    switch (styp) {
00501      case MT9M_TYP:
00502       for (i=0;i<sizeof(mt9m001_inits)/sizeof(mt9m001_inits[0]);i++)
00503         writeSensorReg16(((mt9m001_inits[i]>>16) & 0xff),
00504                          ( mt9m001_inits[i]      & 0xffff), // i2c data (16 bit)
00505                           1);
00506       break;
00507      case MT9D_TYP:
00508       for (i=0;i<sizeof(mt9d001_inits)/sizeof(mt9d001_inits[0]);i++) {
00509         writeSensorReg16(((mt9d001_inits[i]>>16) & 0xff),
00510                          ( mt9d001_inits[i]      & 0xffff), // i2c data (16 bit)
00511                           1);
00512       }
00513       break;
00514      case MT9T_TYP:
00515       for (i=0;i<sizeof(mt9t001_inits)/sizeof(mt9t001_inits[0]);i++)
00516         writeSensorReg16(((mt9t001_inits[i]>>16) & 0xff),
00517                          ( mt9t001_inits[i]      & 0xffff), // i2c data (16 bit)
00518                           1);
00519       break;
00520      case MT9P_TYP:
00521       for (i=0;i<sizeof(mt9p001_inits)/sizeof(mt9p001_inits[0]);i++)
00522         writeSensorReg16(((mt9p001_inits[i]>>16) & 0xff),
00523                          ( mt9p001_inits[i]      & 0xffff), // i2c data (16 bit)
00524                           1);
00525    }
00526 //#endif
00527 
00528 //TODO: remove this timing hack from this function - have it separate. It can be a source of strange errors.
00529 //*************************************
00530 // read appropriate i2c to shadow registers
00531     printk("Reading all MT9X001 registers to shadows\r\n"); // let's use relevant for any of 3 sensors
00532    for (i=0x00;i<=0xff;i++) readSensorReg16(   i, 1);
00534 #if 0
00535         /* measure read time */
00536         do_gettimeofday(&tv_b);
00537         r[0] = 0x01;
00538         first = 0;
00539         for(i = 0; i < 100; i++) {
00540                 f = i2c_writeData(0, MT9X001_I2C_ADDR & 0xfe, &r[0], 1, 0); // no stop before read
00541                 if(f != 0 && first == 0) {
00542 //                      printk("read 1 error!\r\n");
00543                         first = 1;
00544                 }
00545                 f = i2c_readData(0, MT9X001_I2C_ADDR | 1, &r[1], 2, 0); //restart, not strart
00546                 if(f != 0 && first == 0) {
00547 //                      printk("read 1 error!\r\n");
00548                         first = 1;
00549                 }
00550         }
00551         do_gettimeofday(&tv_e);
00552         tv_e.tv_usec += 1000000 * (tv_e.tv_sec - tv_b.tv_sec);
00553         tv_e.tv_usec -= tv_b.tv_usec;
00554         printk("\r\nsensor read delay: %ld usec\r\n", tv_e.tv_usec / 100);
00555         /* measure write time */
00556         do_gettimeofday(&tv_b);
00557         w[0] = 0x01;
00558         w[1] = r[1];
00559         w[2] = r[2];
00560         first = 0;
00561         for(i = 0; i < 100; i++) {
00562                 f = i2c_writeData(0, MT9X001_I2C_ADDR & 0xfe, &w[0], 3, 1); // stop at the end of write
00563                 if(f != 0 && first == 0) {
00564 //                      printk("write error!\r\n");
00565                         first = 1;
00566                 }
00567         }
00568         do_gettimeofday(&tv_e);
00569         tv_e.tv_usec += 1000000 * (tv_e.tv_sec - tv_b.tv_sec);
00570         tv_e.tv_usec -= tv_b.tv_usec;
00571         printk("\r\nsensor write delay: %ld usec\r\n", tv_e.tv_usec / 100);
00572         /* --==-- */
00573 //save and restore sensor clock specified in init script (if any)
00574 #endif
00575    set_imageParamsR(P_SENSOR,sensor.sensorType);
00576    return (sensor.sensorType);
00577 
00578 }
00579 
00580 /*
00581  * Add program_mt9x001_exposition
00582  */
00583 
00584 //static int _nonstop;
00585 //static DECLARE_MUTEX(sensor_lock);
00586 
00587 /* ****************************************************************************************************************************************************** */
00588 // sensor-specific corrections to decimation/binning combinations, called only when binning/decimation is changed (not nonstop)
00589 //int program_woi_mt9x001(int nonstop);
00590 //int program_gains_mt9x001(void);
00591 //int program_exposure_mt9x001(void);
00592 
00593 int adjustBinning_mt9x001(void){
00594         int styp=get_imageParamsR(P_SENSOR) & 0x7;
00595         int dh = get_imageParamsR(P_DCM_HOR);
00596         int dv = get_imageParamsR(P_DCM_VERT);
00597         int bh = get_imageParamsR(P_BIN_HOR);
00598         int bv = get_imageParamsR(P_BIN_VERT);
00599         // put here specific exceptions   
00600         switch(styp) {
00601         case MT9P_TYP: // leave same as MT9T001 for now
00602                 // see page 45   
00603                 break;
00604         case MT9T_TYP:
00605                 break;
00606         }
00607         set_imageParamsR(P_DCM_HOR,  dh);
00608         set_imageParamsR(P_DCM_VERT, dv);
00609         set_imageParamsR(P_BIN_HOR,  bh);
00610         set_imageParamsR(P_BIN_VERT, bv);
00611 }
00612 
00613 // will use decimation, binning, flipx/y, virtual width and calcualte line duration
00614 int program_woi_mt9x001(int nonstop) { 
00615         int i,dh,dv,bv,bh,ww,wh,wl,wt,pfh,flipX,flipY,d;
00616         int w,hbmin,p1,p2;
00617         int r =    0;
00618         int hb =   0;
00619         int trow = 0;
00620         int fclk,sclk,xtra;
00621         int styp = get_imageParamsR(P_SENSOR) & 0x7;
00622 
00623 //    if  (get_imageParamsW(P_CLK_SENSOR)  > sensor.maxClockFreq) set_imageParamsW(P_CLK_SENSOR, sensor.maxClockFreq);
00624 //       sensor.pixelHeight=h+X313_MARGINS;
00625 
00626         fclk=get_imageParamsW(P_CLK_FPGA);   if (fclk==0) fclk=get_imageParamsR(P_CLK_FPGA);
00627         sclk=get_imageParamsW(P_CLK_SENSOR); if (sclk==0) sclk=get_imageParamsR(P_CLK_SENSOR);
00628         xtra=get_imageParamsR(P_FPGA_XTRA);
00629         pfh= get_imageParamsR(P_PF_HEIGHT) & 0xffff;
00630         dh=  get_imageParamsR(P_DCM_HOR);
00631         dv=  get_imageParamsR(P_DCM_VERT);
00632         bh=  get_imageParamsR(P_BIN_HOR);
00633         bv=  get_imageParamsR(P_BIN_VERT);
00634 //      ww=  get_imageParamsR(P_WOI_WIDTH)+X313_MARGINS;
00635 //      wh=  get_imageParamsR(P_WOI_HEIGHT)+X313_MARGINS;
00636         ww=  sensor.pixelWidth*dh;
00637         wh=  sensor.pixelHeight*dv;
00638 //      if (pfh) wh=pfh*dv;  // sensor frame hight (i.e. two lines) already done
00639         flipX = get_imageParamsR(P_FLIP) & 1;
00640         flipY = (get_imageParamsR(P_FLIP) & 2)?1:0;
00641         if(styp == MT9P_TYP) { 
00642                 flipX = (get_imageParamsR(P_FLIP) & 1) ? 0 : 1;
00643                 flipY = (get_imageParamsR(P_FLIP) & 2) ? 0 : 1;
00644         }
00645         MD7(printk("ww=%d, wh=%d, dh=%d, dv=%d\r\n", ww,wh,dv,dh));
00646 
00647         if(!nonstop) { // set decimation, woi size,  (binning, position, flip, virtual window - always)
00648                 d = 2 * bh * (ww / (2 * bh));
00649                 if(d != ww) { // correct window width if needed
00650                         sensor.pixelWidth = d / dh;
00651                         ww = d;
00652                 }
00653                 r |= writeSensorReg16(P_MT9X001_WIDTH, ww - 1, 0);
00654                 d = 2 * (wh / 2);
00655                 if(d != wh) { // correct window height if needed
00656                         sensor.pixelHeight = d / dh;
00657                         wh = d;
00658                         set_imageParamsR(P_WOI_HEIGHT, wh);
00659                 }
00660                 r |= writeSensorReg16(P_MT9X001_HEIGHT, wh - 1, 0);
00661                 MD7(printk("ww=%d, wh=%d, dh=%d, dv=%d\r\n", ww, wh, dv, dh));
00662       set_imageParamsR(P_TRIG,(get_imageParamsR(P_TRIG) & ~4) | (get_imageParamsW(P_TRIG) & 4)); 
00663         } else { // nonstop
00664         } // end of stop/nonstop
00665         MD7(printk("sensor.pixelWidth=0x%lx, sensor.pixelHeight=0x%lx\r\n", sensor.pixelWidth,sensor.pixelHeight));
00666 
00667         wl = get_imageParamsR(P_WOI_LEFT);
00668         wt = get_imageParamsR(P_WOI_TOP);
00669         MD7(printk("wl=0x%x, wt=0x%x\r\n", wl, wt));
00670    if (!get_imageParamsR(P_OVERSIZE)) {
00671         if(flipX) {
00672                 wl = sensor.clearWidth - ww - wl - sensor.margins * dh;
00673                    if(wl < 0) wl = 0;
00674            }
00675            if(flipY) {
00676                    wt = sensor.clearHeight - wh - wt - sensor.margins * dv;
00677                    if(wt < 0) wt = 0;
00678            }
00679    }
00680         MD7(printk("wl=0x%x, wt=0x%x\r\n", wl, wt));
00681 // the fields that should not chnage in non-stop will not change, so it is OK to write them always
00682         if((styp == MT9T_TYP) || (styp == MT9P_TYP)) { 
00683                 r |= writeSensorReg16(P_MT9X001_RAM,
00684                         (get_sensor_i2c_regs16(P_MT9X001_RAM) & 0xff88) | // preserve other bits from shadows
00685                         ((bv - 1) << 4) | (dv - 1),
00686                         0);
00687                 r |= writeSensorReg16(P_MT9X001_CAM,
00688                         (get_sensor_i2c_regs16(P_MT9X001_CAM) & 0xff88) | // preserve other bits from shadows
00689                         ((bh - 1) << 4) | (dh - 1),
00690                         0);
00691                 r |= writeSensorReg16(P_MT9X001_RMODE2,
00692                         (get_sensor_i2c_regs16(P_MT9X001_RMODE2) & 0x3fff) | // preserve other bits from shadows
00693                         (flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
00694                         (flipY ? (1 << 15) : 0) , // FLIPV
00695                         0);
00696                 r |= writeSensorReg16(P_MT9X001_RMODE1,
00697                         (get_sensor_i2c_regs16(P_MT9X001_RMODE1) & 0xfeff) | // preserve other bits from shadows
00698                         ((get_imageParamsR(P_TRIG) & 4)?0x100:0) , //set async mode
00699                         0);
00700         } else {
00701                 r |= writeSensorReg16(P_MT9X001_RMODE1,
00702                         (get_sensor_i2c_regs16(P_MT9X001_RMODE1) & 0xfec3) | // preserve other bits from shadows
00703                         ((get_imageParamsR(P_TRIG) & 4)?0x100:0) | //set async mode
00704                         ((dh == 4) ? (1 << 2) : 0) | // Column skip 4
00705                         ((dv == 4) ? (1 << 3) : 0) | // Row skip    4
00706                         ((dh == 8) ? (1 << 4) : 0) | // Column skip 8
00707                         ((dv == 8) ? (1 << 5) : 0) , // Row skip    8
00708                         0);
00709                 r |= writeSensorReg16(P_MT9X001_RMODE2,
00710                         (get_sensor_i2c_regs16(P_MT9X001_RMODE2) & 0x3fe7) | // preserve other bits from shadows
00711                         ((dh == 2) ? (1 << 3) : 0) | // Column skip 2
00712                         ((dv == 2) ? (1 << 4) : 0) | // Row skip    2
00713                         (flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
00714                         (flipY ? (1 << 15) : 0) , // FLIPV
00715                         0);
00716         }
00717         // now position. Adjust wl, wt (increment only) to decimation/binning
00718    if (!get_imageParamsR(P_OVERSIZE)) {
00719         wt = (wt + sensor.clearTop) & 0xfffe; 
00720            wl = (wl + sensor.clearLeft) & 0xfffe; 
00721            MD7(printk("wl=%d, wt=%d\r\n", wl, wt));
00722            switch(styp) {
00723            case MT9P_TYP:
00724                    d = (bh > 1) ? ((bh > 2) ? 16 : 8) : 4;
00725                    if(flipX)
00726                            i = d * ((wl - 2) / d) + 2;
00727                    else
00728                         i = d * (wl / d);
00729                    if(i < wl)
00730                            i += d;
00731                    wl = i;
00732                    break;
00733            case MT9T_TYP:
00734                    d = (bh > 1) ? ((bh > 2) ? (16) : (8)) : (4);
00735                    if(flipX)
00736                            i = d * ((wl - 2) / d) + 2;
00737                    else
00738                            i = d * (wl / d);
00739                    if(i < wl)
00740                            i += d;
00741                    wl = i;
00742                    break;
00743            }
00744    }
00745         // program wl, wt (don't increase r?)
00746         writeSensorReg16(P_MT9X001_COLSTART, wl, 0);
00747         writeSensorReg16(P_MT9X001_ROWSTART, wt, 0);
00748         MD7(printk("wl=%d, wt=%d\r\n", wl,wt));
00749         // now - calculate line duration in clocks 
00750         int _binning_cost = 0;
00751         if(!nonstop)   { // should not change in nonstop mode
00752                 switch(styp)  {
00753                 case MT9P_TYP: //page 16
00754                         w = 2 * ww / (2 * dh);
00755                         if((w * dh) < ww)
00756                                 w++;
00757 //                      hbmin = 208 * bv + 64 + (40 / bh);
00758 //                      hbmin = 208 * bv + 64 + (312 + 11) / 2;
00759             switch(bv) {
00760 /*                              
00761                         case 1:
00762                                 switch(bh) {
00763                                         case 2: _binning_cost = 0;  break;
00764                                         case 4: _binning_cost = 0;  break;
00765                                         break;
00766                                 }
00767                                 break;
00768 */
00769                         case 2:
00770                                 switch(bh) {
00771                                         case 1: _binning_cost = 276;    break;
00772                                         case 2: _binning_cost = 236;    break;
00773                                         case 4: _binning_cost = 236;    break;
00774                                         break;
00775                                 }
00776                                 break;
00777                         case 4:
00778                                 switch(bh) {
00779                                         case 1: _binning_cost = 826;    break;
00780                                         case 2: _binning_cost = 826;    break;
00781                                         case 4: _binning_cost = 826;    break;
00782                                         break;
00783                                 }
00784                                 break;
00785                         }
00786                         hbmin = 208 * bv + 64 + (312 + 44 + _binning_cost) / 2;
00787 //                      hb = hbmin + 102;
00788                         hb = hbmin;
00789                         trow = w + hb * 2;
00790                         i = 2 * (41 + 208 * bv + 99); //strange 41 and 99, why not 140?
00791 //                      MD7(printk("trow = %d, i = %d\r\n", trow, i));
00792                         if(i > trow)
00793                                 trow = i;
00794                         if(((i = get_imageParamsW(P_VIRT_WIDTH))) > trow) { // extend line by adding horizontal blanking
00795                                 hb = (i - w) / 2;
00796                                 if(hb > sensor.maxHorBlank)
00797                                         hb = sensor.maxHorBlank;
00798                                 trow = w + 2 * hb;
00799                         }
00800                         break;
00801                 case MT9T_TYP:
00802                         w = 2 * ww / (2 * dh);
00803                         if((w * dh) < ww)
00804                                 w++;
00805                         switch(bv) {
00806                                 case 1:  p1 = 331; break;
00807                                 case 2:  p1 = 673; break;
00808                                 case 3:  p1 = 999; break;
00809                                 default: p1 = 999; break; //undocumented
00810                         }
00811                         switch(bh) {
00812                                 case 1:  p2 = 38; break;
00813                                 case 2:  p2 = 22; break;
00814                                 case 3:  p2 = 14; break;
00815                                 default: p2 = 38; break; //undocumented
00816                         }
00817                         hb = sensor.minHorBlank;
00818                         trow = w + p1 + p2 + hb;
00819                         MD7(printk("trow=%d, w=%d, p1= %d, p2=%d, hb=%d\r\n", trow, w, p1, p2, hb));
00820                         if(((i = get_imageParamsW(P_VIRT_WIDTH))) > trow) { // extend line by adding horizontal blanking
00821                                 hb = i - w - p1 - p2;
00822                                 if(hb > sensor.maxHorBlank)
00823                                         hb = sensor.maxHorBlank;
00824                                 trow = w + p1 + p2 + hb;
00825                         }
00826                         hb--; // confusing - for mt9p001 (not others which refer reg[0x05]) :"HB Horizontal Blanking Horizontal_Blank+1"
00827                         break;
00828                 case MT9D_TYP:
00829 //                      w = 2 * ww / (2 * dh); if ((w * dh) < ww) w++;
00830                         w = 2 * ((ww - 1) / (2 * dh)) + 2; //docs, p.6
00831                         hb = sensor.minHorBlank;
00832                         p1 = 322;
00833                         p2 = 2 - 19; //excluded hb
00834                         trow = w + p1 + p2 + hb;
00835                         i = p1 + 295;
00836                         if(i > trow)
00837                                 trow = i;
00838                         MD7(printk("trow=%d, w=%d, p1= %d, p2=%d, hb=%d, i=%d\r\n", trow, w, p1, p2, hb, i));
00839                         if(((i = get_imageParamsW(P_VIRT_WIDTH))) > trow) { // extend line by adding horizontal blanking
00840                                 hb = i - w - p1 - p2;
00841                                 if (hb > sensor.maxHorBlank) hb = sensor.maxHorBlank;
00842                                         trow = w + p1 + p2 + hb;
00843                         }
00844                         break;
00845                 case MT9M_TYP:
00846 //                      w = 2 * ww / (2 * dh); if ((w * dh) < ww) w++;
00847                         w = 2 * ((ww - 1) / (2 * dh)) + 2; //docs, p.6
00848                         hb = sensor.minHorBlank;
00849                         p1 = 242;
00850                         p2 = 2 - 19; //excluded hb
00851                         trow= w + p1 + p2 + hb;
00852                         MD7(printk("trow=%d, w=%d, p1= %d, p2=%d, hb=%d\r\n", trow, w, p1, p2, hb));
00853                         if(((i = get_imageParamsW(P_VIRT_WIDTH))) > trow) { // extend line by adding horizontal blanking
00854                                 hb = i - w - p1 - p2;
00855                                 if(hb > sensor.maxHorBlank)
00856                                         hb = sensor.maxHorBlank;
00857                                 trow = w + p1 + p2 + hb;
00858                         }
00859                         break;
00860                 }
00861                 set_imageParamsR(P_VIRT_WIDTH, trow); // line duration in clocks
00862                 MD7(printk("trow = %d\r\n", trow));
00863                 r |= writeSensorReg16(P_MT9X001_HORBLANK, hb, 0);
00864         }
00865         // calculate Bayer shift
00866         // seems nor MT9P031 wants the same. Maybe DLYHOR bit in FPGA CR was set?
00867 //      if(styp == MT9P_TYP)
00868 //              set_imageParamsR(P_BAYER, (flipX ? 1 : 0) | (flipY ? 0 : 2));
00869 //      else
00870                 set_imageParamsR(P_BAYER, (flipX ? 0 : 1) | (flipY ? 0 : 2));
00871         return r;
00872 }
00873 
00874 int normalize_gain(int g) {
00875         if(g < 0x0400)
00876                 return (g & 0xFFE0);
00877         if(g < 0x0800)
00878                 return (g & 0xFFC0);
00879         return (g & 0xFF00);
00880 }
00881 
00882 int gain_mt9x001(int g) {
00883         if(g > sensor.maxGain256)
00884                 g = sensor.maxGain256;
00885         if(g <= 0x400)
00886                 g >>= 5;
00887         else 
00888                 g = (g >> 6) + 0x40;
00889         return g;
00890 }
00891 
00892 int program_gains_mt9x001(void) {
00893         int gg, gr, gb, ggb;
00894         int r = 0;
00895         gr  = get_imageParamsW(P_GAINR ); if (gr  > sensor.maxGain256) gr  = sensor.maxGain256 ; else if (gr  < 0) gr  = 0;
00896         gg  = get_imageParamsW(P_GAING ); if (gg  > sensor.maxGain256) gg  = sensor.maxGain256 ; else if (gg  < 0) gg  = 0;
00897         gb  = get_imageParamsW(P_GAINB ); if (gb  > sensor.maxGain256) gb  = sensor.maxGain256 ; else if (gb  < 0) gb  = 0;
00898         ggb = get_imageParamsW(P_GAINGB); if (ggb > sensor.maxGain256) ggb = sensor.maxGain256 ; else if (ggb < 0) ggb = 0;
00899 //      printk("1: ggb == 0x%04X\r\n", ggb);
00900         gr = normalize_gain(gr);
00901         gg = normalize_gain(gg);
00902         gb = normalize_gain(gb);
00903         ggb = normalize_gain(ggb);
00904 //      printk("2: ggb == 0x%04X\r\n", ggb);
00905         set_imageParamsR(P_GAINR, gr);
00906         set_imageParamsR(P_GAING, gg);
00907         set_imageParamsR(P_GAINB, gb);
00908         set_imageParamsR(P_GAINGB,ggb);
00909 //      printk("\n____====____\ngains: gr == 0x%04X, gg == 0x%04X, gb == 0x%04X\n____----____\n", gr, gg, gb);
00910         r |= writeSensorReg16(P_MT9X001_RED,     gain_mt9x001(gr), 0);
00911         r |= writeSensorReg16(P_MT9X001_GREEN1,  gain_mt9x001(gg), 0);
00912         r |= writeSensorReg16(P_MT9X001_BLUE,    gain_mt9x001(gb), 0);
00913         r |= writeSensorReg16(P_MT9X001_GREEN2,  gain_mt9x001(ggb),0);
00918         frame_params.gain_r=  gr  >> 4;
00919         frame_params.gain_g=  gg  >> 4;
00920         frame_params.gain_b=  gb  >> 4;
00921         frame_params.gain_gb= ggb >> 4;
00922 
00923         if(r >= 0)
00924                 r = 0; // disable wait here?
00925         return r;
00926 }
00927 
00928 // will set shutter duration and "virtual height" (vertical blank).
00929 // line duration (imageParamsR[P_VIRT_WIDTH]) is set by program_woi_mt9x001()
00930 // if imageParamsW[P_VEXPOS] >0 it will be used (measured in scan lines) instead of imageParamsW[P_EXPOS] (measured in 0.1 ms)
00931 // both imageParamsR[P_VEXPOS] and imageParamsR[P_EXPOS] will be updated
00932 // imageParamsW[P_FP100S]
00933 
00934 void check_fps(void);
00935 
00936 // TODO: add code to cc333.c/cc313.c to use imageParamsW[FP100S] to limit sensor frame rate if FPGA can not handle it??
00937 int program_exposure_mt9x001(void) {
00938         int vh, vb, wh, h, dv, sclk, trow, ve, e, i;
00939         int r = 0;
00940         int styp = get_imageParamsR(P_SENSOR) & 0x7;
00941         // calculate minimal virtual heigth for current window height
00942         dv = get_imageParamsR(P_DCM_VERT);
00943         wh = get_sensor_i2c_regs16(P_MT9X001_HEIGHT) + 1;
00944         h = 2 * (wh / (2 * dv));
00945         if((h * dv) < wh)
00946                 h++;
00947         vh = h + sensor.minVertBlank;
00948         sclk = get_imageParamsW(P_CLK_SENSOR);
00949         if(sclk == 0)
00950                 sclk = get_imageParamsR(P_CLK_SENSOR);
00951         trow = get_imageParamsR(P_VIRT_WIDTH);
00952 // now get_imageParamsW(P_FP100S) will be always non-zero (if specified 0 will use maximal compressor fps
00953    if ((get_imageParamsR(P_TRIG) & 4)==0) { 
00954      i = (((sclk * 1) / trow) * 100) / get_imageParamsW(P_FP100S); // number of virtual lines // changed to Hz instead of MHz
00955      if (i > vh) {
00956        vh = i;
00957      }
00958    }
00959         vb = vh - h;
00960 //printk("fp100s=0x%08x vb=0x%08X, vh == 0x%08X\r\n", get_imageParamsW(P_FP100S), vb, vh);
00961         if(vb > sensor.maxVertBlank) {
00962                 vb = sensor.maxVertBlank;
00963                 vh = vb + h;
00964         }
00965         MD7(printk("vh=%d, h=%d, vb=%d\r\n", vh, h, vb));
00966         set_imageParamsR(P_VIRT_HEIGHT, vh);
00967         r |= writeSensorReg16(P_MT9X001_VERTBLANK, vb - 1, 0);
00968         //  exposure
00969         if((ve = get_imageParamsW(P_VEXPOS))) {
00970                 e = (ve * trow) / (sclk/10000); //why was it vh+1?
00971         } else {
00972                 if(((e = ((int)get_imageParamsW(P_EXPOS)))) < 0) {//use frame time as exposure time . get_imageParamsW - unsigned
00973                         // calculate actual frame period (in clocks)
00974                         e = (ve * trow) / (sclk/10000); //why was it vh+1?
00975                 } else {
00976                         // here calculate exposure (1 unit= 100usec) and using actual clock frequency
00977                         i = get_imageParamsW(P_EXPOS) * (sclk/10000); // msec->MCLK periods. (<10.7 sec @ 20MHz)
00978                         MD7(printk("trow= %d, i=%d\r\r\n", trow, i));
00979                         ve = i / trow;
00980                 }
00981         }
00982         if(e < 1)
00983                 e = 1; // measured in 0.1 msec
00984         if(ve < 1)
00985                 ve = 1; // in lines - can be more accurate than e
00986         if(ve > sensor.maxShutter)
00987                 ve = sensor.maxShutter;
00988         if((get_imageParamsR(P_FPSLM) & 2) && (ve > vh)) ve = vh; // P_FPSLM bit 1 - "maintain FPS" (not lower than), exposure should not increase frame time
00989         set_imageParamsR(P_VEXPOS, ve);
00990         set_imageParamsR(P_EXPOS, e);
00991 long t;
00992         if(vh > ve){
00993                 set_imageParamsR(P_PERIOD, vh * trow);
00994 //              set_imageParamsR(P_FP100S, t = (((sclk * 1000000) / trow) * 100) / vh);
00995                 set_imageParamsR(P_FP100S, t = (((sclk * 1) / trow) * 100) / vh);
00996         } else {
00997                 set_imageParamsR(P_PERIOD, ve * trow);
00998 //              set_imageParamsR(P_FP100S, t = (((sclk * 1000000) / trow) * 100) / ve);
00999                 set_imageParamsR(P_FP100S, t = (((sclk * 1) / trow) * 100) / ve);
01000         }
01001 MD9(printk("vb == 0x%08X, vh == 0x%08X, fps == %d\r\n", vb, vh, t));
01002         r |= writeSensorReg16(P_MT9X001_VERTBLANK, vb - 1, 0);
01003 //      r |= writeSensorReg16(P_MT9X001_VERTBLANK, 0xFFF0, 0);
01004         // set video exposure time
01005         if((styp == MT9T_TYP) || (styp == MT9P_TYP)) {
01006                 r |= writeSensorReg16(P_MT9X001_SHTRWDTHU, ve >> 16, 0);
01007         }
01008         r |= writeSensorReg16(P_MT9X001_SHTRWDTH,  ve & 0xffff, 0);
01009 //      check_fps();
01010         return r;
01011 }
01012 
01013 long max_(long a, long b) {
01014         long _max = (a > b) ? a : b;
01015         return _max;
01016 }
01017 
01018 void check_fps(void) {
01019         long H = readSensorReg16(P_MT9X001_HEIGHT, 1) + 1;
01020         long W = readSensorReg16(P_MT9X001_WIDTH, 1) + 1;
01021         long HB = readSensorReg16(P_MT9X001_HORBLANK, 1) + 1;
01022         long VB = readSensorReg16(P_MT9X001_VERTBLANK, 1) + 1;
01023 
01024         long HBmin = 312;
01025         long SW = max_(1, 65536 * readSensorReg16(P_MT9X001_SHTRWDTHU, 1) + readSensorReg16(P_MT9X001_SHTRWDTH, 1));
01026         long VBmin = max_(8, SW - H) + 1;
01027 
01028         long Trow = 2 * max_(W / 2 + max_(HB, HBmin), 41 + 208 + 99);
01029         long Tframe = (H + max_(VB, VBmin)) * Trow;
01030         MD9(printk("-->> Tframe == %d clck; Trow == %d clck\n", Tframe, Trow));
01031 }

Generated on Thu Aug 7 16:19:00 2008 for elphel by  doxygen 1.5.1