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

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : cc353.c
00003 *! DESCRIPTION: TBD
00004 *! Copyright (C) 2002-2007 Elphel, Inc.
00005 *! -----------------------------------------------------------------------------**
00006 *!
00007 *!  This program is free software: you can redistribute it and/or modify
00008 *!  it under the terms of the GNU General Public License as published by
00009 *!  the Free Software Foundation, either version 3 of the License, or
00010 *!  (at your option) any later version.
00011 *!
00012 *!  This program is distributed in the hope that it will be useful,
00013 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 *!  GNU General Public License for more details.
00016 *!
00017 *!  You should have received a copy of the GNU General Public License
00018 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 *! -----------------------------------------------------------------------------**
00020 *!  $Log: cc353.c,v $
00021 *!  Revision 1.32  2008/07/23 02:27:12  elphel
00022 *!  fixed hardware i2c bug - now 3MPix seem to work
00023 *!
00024 *!  Revision 1.31  2008/05/02 15:16:58  elphel
00025 *!  changed to hardware i2c writes, added P_OVERSIZE parameter to be able to read sensor with the dark pixels
00026 *!
00027 *!  Revision 1.30  2008/05/01 01:28:57  elphel
00028 *!  hardware i2c control - macros, variables
00029 *!
00030 *!  Revision 1.29  2008/04/25 21:30:12  elphel
00031 *!  implemented frame delay for the parameters, made Exif exposure to match the frame it is applied to
00032 *!
00033 *!  Revision 1.28  2008/04/20 06:49:40  elphel
00034 *!  cleanup, bug fixes
00035 *!
00036 *!  Revision 1.27  2008/04/16 20:33:23  elphel
00037 *!  driver cleanup, removed some duplicate actions, working on better recovery after parameter modification
00038 *!
00039 *!  Revision 1.26  2008/04/11 22:57:02  elphel
00040 *!  added "histogram" tasklet on/off control, removed extra local_irq_disable()
00041 *!
00042 *!  Revision 1.25  2008/04/07 09:09:31  elphel
00043 *!  Changes to handle Exif
00044 *!
00045 *!  Revision 1.24  2008/03/20 22:29:30  elphel
00046 *!  added trigger-related code and parameters
00047 *!
00048 *!  Revision 1.23  2008/02/12 21:53:19  elphel
00049 *!  Modified I2c to support multiple buses, added raw access (no address registers) and per-slave protection bitmasks
00050 *!
00051 *!  Revision 1.22  2008/02/01 04:52:08  elphel
00052 *!  Fixed focus visualization code in FPGA and related software
00053 *!
00054 *!  Revision 1.21  2008/01/27 06:25:30  elphel
00055 *!  driver update for focus processing
00056 *!
00057 *!  Revision 1.20  2008/01/25 07:15:15  elphel
00058 *!  7.1.7.8 - added fpga code FPGA code (and related software) to facilitate focusing
00059 *!
00060 *!  Revision 1.19  2008/01/12 06:53:23  elphel
00061 *!  7.1.7.2 - added elphel_autoexposure_get() function to elphel php extension
00062 *!
00063 *!  Revision 1.18  2008/01/11 07:49:12  elphel
00064 *!  added setting the autoexposure parameters for PHP
00065 *!
00066 *!  Revision 1.17  2008/01/11 01:28:23  elphel
00067 *!  7.1.7.1 - working on autoexposure to make it use the same P_* parameters.
00068 *!
00069 *!  Revision 1.16  2008/01/10 02:45:02  elphel
00070 *!  Fixed wrong frame time calculation
00071 *!
00072 *!  Revision 1.15  2008/01/07 08:56:44  elphel
00073 *!  Temporary fix to "broken" images
00074 *!
00075 *!  Revision 1.14  2007/12/13 06:47:55  elphel
00076 *!  Fixed my stupid cache/mmap bug I blamed Axis for
00077 *!
00078 *!  Revision 1.13  2007/12/13 02:47:15  elphel
00079 *!  Fixed old driver bug (related to sensor reset), changed cache_flush for PHP extension
00080 *!
00081 *!  Revision 1.12  2007/12/09 05:58:54  elphel
00082 *!  comments
00083 *!
00084 *!  Revision 1.11  2007/12/05 22:01:21  elphel
00085 *!  added handling etrax fs mmap cach problem when communicating between PHP extension and the driver
00086 *!
00087 *!  Revision 1.10  2007/12/03 08:28:46  elphel
00088 *!  Multiple changes, mostly cleanup
00089 *!
00090 *!  Revision 1.9  2007/11/30 06:46:12  elphel
00091 *!  added mmap to parameters array, starting programSensor(nonstop) from overloaded lseek (,,SEEK_END)
00092 *!
00093 *!  Revision 1.8  2007/11/14 00:57:04  spectr_rain
00094 *!  fix FPS on streamer interface
00095 *!
00096 *!  Revision 1.7  2007/11/04 05:49:31  elphel
00097 *!  fixed mmap/caching bug - (that seems to be a known Axis one)
00098 *!
00099 *!  Revision 1.6  2007/11/01 18:59:37  elphel
00100 *!  debugging mmap/caching problems
00101 *!
00102 *!  Revision 1.5  2007/10/27 00:55:32  elphel
00103 *!  untested revision - need to go
00104 *!
00105 *!  Revision 1.4  2007/10/16 20:04:38  elphel
00106 *!  debug for sensor phase, starting programSensor from write php
00107 *!
00108 *!  Revision 1.3  2007/10/11 06:41:35  elphel
00109 *!  Added support for lseek -  ioctl alternatives to control compressor/image acquisition to circbuf
00110 *!
00111 *!  Revision 1.2  2007/10/10 23:33:32  elphel
00112 *!  fixed bugs found by Spectr
00113 *!
00114 *!  Revision 1.1.1.1  2007/10/02 21:09:15  elphel
00115 *!  This is a fresh tree based on elphel353-2.10
00116 *!
00117 *!  Revision 1.16  2007/10/02 19:39:55  elphel
00118 *!  Bug fix, added notes for the future
00119 *!
00120 *!  Revision 1.15  2007/09/30 07:07:27  elphel
00121 *!  only disabled debug output
00122 *!
00123 *!  Revision 1.14  2007/09/30 03:19:56  elphel
00124 *!  Cleanup, fixed broken acquisition of individual JPEG images into circbuf (in mode 7)
00125 *!
00126 *!  Revision 1.13  2007/09/29 18:33:29  elphel
00127 *!  Split cxdma.c - /dev/circbuf is now in a separate circbuf.c file. New device driver does not support ioctl, so some curernt applications are updated to use other drivers to control the camera
00128 *!
00129 *!  Revision 1.11  2007/09/19 17:47:30  elphel
00130 *!  P_FPSLM is updated in non-stop mode (so it can be updated and read back from the camera in camvc)
00131 *!
00132 *!  Revision 1.10  2007/09/19 00:34:20  elphel
00133 *!  support for frame rate limiting, disabled extra debug  messages
00134 *!
00135 *!  Revision 1.9  2007/09/18 06:09:22  elphel
00136 *!  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
00137 *!
00138 *!  Revision 1.8  2007/08/27 04:46:16  elphel
00139 *!  Restoring JP4 format (option "j" in ccam.cgi "opt=" parameter). FPGA code for this mode is not fixed yet (but it does something different than in modes color & mono).
00140 *!
00141 *!  Revision 1.7  2007/08/17 10:23:17  spectr_rain
00142 *!  switch to GPL3 license
00143 *!
00144 *!  Revision 1.6  2007/07/20 10:17:44  spectr_rain
00145 *!  *** empty log message ***
00146 *!
00147 *!  Revision 1.14  2007/07/13 20:54:07  elphel
00148 *!  fixed operation of 10347 board to match changes in FPGA/drivers made fro EMI reduction of the 353 cameras
00149 *!
00150 *!  Revision 1.13  2007/07/10 06:08:14  elphel
00151 *!  Adding possibility to read/write sensor parameters, increasing number from 64 to 1024.
00152 *!  Now writing to first 4096 bytes of the /dev/sensorpars will write imageParams array, reading from the same first 4096 bytes will read imageParams array, next 4096 bytes - imageParamsW
00153 *!
00154 *!  Revision 1.12  2007/07/10 00:12:21  elphel
00155 *!  Fixed bug that zeroed sensor.margins
00156 *!
00157 *!  Revision 1.11  2007/07/09 21:10:13  elphel
00158 *!  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
00159 *!
00160 *!  Revision 1.10  2007/06/28 02:27:05  elphel
00161 *!  1) Added code to enable communication with sensor board FPGA over longer cable
00162 *!  2) Rewrote the histogram module to support 96MHz. It now uses doubled pixel clock.
00163 *!
00164 *!  Revision 1.9  2007/06/18 07:57:24  elphel
00165 *!  Fixed bug working with MT9P031 - added sensor reset/reinit after frequency change
00166 *!
00167 *!  Revision 1.8  2007/04/19 20:15:25  elphel
00168 *!  added KAI-11000/KAI-11002 basic support
00169 *!
00170 *!  Revision 1.7  2007/04/18 21:13:36  spectr_rain
00171 *!  *** empty log message ***
00172 *!
00173 *!  Revision 1.6  2007/04/18 21:02:06  elphel
00174 *!  working on KAI-11002 support
00175 *!
00176 *!  Revision 1.5  2007/04/09 17:32:23  spectr_rain
00177 *!  enable gamms, scale and histograms
00178 *!
00179 *!  Revision 1.4  2007/04/05 21:00:28  spectr_rain
00180 *!  remove trigger check in IRQ handler
00181 *!
00182 *!  Revision 1.3  2007/04/04 03:55:22  elphel
00183 *!  Improved i2c, added i2c as character devices (to use from php)
00184 *!
00185 *!  Revision 1.2  2007/03/25 10:14:23  elphel
00186 *!  Accommodating 10359 board
00187 *!
00188 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00189 *!  initial import into CVS
00190 *!
00191 *!  Revision 1.16  2006/11/28 18:33:26  spectr_rain
00192 *!  *** empty log message ***
00193 *!
00194 *!  Revision 1.15  2006/11/27 17:35:32  spectr_rain
00195 *!  *** empty log message ***
00196 *!
00197 *!  Revision 1.14  2006/11/24 22:59:49  spectr_rain
00198 *!  fix output data counter from FPGA
00199 *!
00200 *!  Revision 1.13  2006/11/01 18:49:57  spectr_rain
00201 *!  *** empty log message ***
00202 *!
00203 *!  Revision 1.12  2006/09/19 16:22:14  spectr_rain
00204 *!  *** empty log message ***
00205 *!
00206 *!  Revision 1.11  2006/09/02 22:04:17  spectr_rain
00207 *!  *** empty log message ***
00208 *!
00209 *!  Revision 1.10  2006/09/02 00:19:49  spectr_rain
00210 *!  lock sensor while readrawimage
00211 *!
00212 *!  Revision 1.9  2006/09/01 18:54:40  spectr_rain
00213 *!  some fixes for /dev/ccam_img (image.raw)
00214 *!
00215 *!  Revision 1.8  2006/08/30 15:56:20  spectr_rain
00216 *!  unlock manual exposition when autoexp disabled
00217 *!
00218 *!  Revision 1.7  2006/08/29 18:06:58  spectr_rain
00219 *!  6.5.2
00220 *!
00221 *!  Revision 1.5  2006/07/17 12:22:42  spectr_rain
00222 *!  enable autoexposition
00223 *!
00224 *!  Revision 1.4  2006/07/12 23:02:00  spectr_rain
00225 *!  disable gistogramm tables apply
00226 *!
00227 *!  Revision 1.3  2006/07/12 07:06:43  elphel
00228 *!  fixed a bug introduced in 333 code (was not in 313/323) that make driver be satisfied with no-sensor and do not try to reinit it during each file open.
00229 *!
00230 *!  Revision 1.2  2006/07/12 06:03:16  elphel
00231 *!  bug fix
00232 *!
00233 *!  Revision 1.1.1.1  2006/07/11 19:15:02  spectr_rain
00234 *!  unwork with less than 5MPx Micron sensor, initial branch
00235 *!
00236 *!  Revision 1.26  2006/02/22 18:03:56  spectr_rain
00237 *!  restore normal autoexp work in continuous mode
00238 *!
00239 *!  Revision 1.25  2006/02/22 09:06:46  elphel
00240 *!  Made ccam.cgi return last image from the buffer when streamer is running. Same as acquireing image, with "-" in the options, i.e. "admin-bin/ccam.cgi?opt=vhcxy-" (all parameters will be ignored)
00241 *!
00242 *!  Revision 1.24  2006/02/22 05:07:51  elphel
00243 *!  seems it was an error - closing /dev/circbuf was zeroing minors[p] - it did not let access to circular buffer while streamer was running
00244 *!
00245 *!  Revision 1.23  2006/02/12 17:35:00  spectr_rain
00246 *!  fix mutex deadlock
00247 *!
00248 *!  Revision 1.22  2006/02/08 01:53:56  spectr_rain
00249 *!  fix broken mutex in check of down_interruptible
00250 *!
00251 *!  Revision 1.21  2006/02/03 20:40:40  spectr_rain
00252 *!  use one gain for all colors
00253 *!
00254 *!  Revision 1.20  2006/01/22 09:18:40  elphel
00255 *!  fixed problem with "gamma" gains - when {r,b}scale was <1.0, it reduced the other gains proportionally but still left this one, so effectively it was changing scale to the square of the value
00256 *!
00257 *!  Revision 1.19  2006/01/17 06:44:49  elphel
00258 *!  1. changed interrupt tasklets call - no deadlocks since
00259 *!  2. fixed bug so resetting sensor is possible (ccam.cgi?resetsensor=1)
00260 *!
00261 *!  Revision 1.18  2006/01/12 15:35:29  spectr_rain
00262 *!  change color canal scale limits
00263 *!
00264 *!  Revision 1.17  2006/01/11 12:43:56  spectr_rain
00265 *!  *** empty log message ***
00266 *!
00267 *!  Revision 1.16  2006/01/11 12:19:54  spectr_rain
00268 *!  add IO_CCAM_PINS_(READ|WRITE) ioctl
00269 *!
00270 *!  Revision 1.15  2006/01/05 05:35:19  spectr_rain
00271 *!  *** empty log message ***
00272 *!
00273 *!  Revision 1.14  2006/01/05 05:13:12  spectr_rain
00274 *!  new sensitivity/scale iface
00275 *!
00276 *!  Revision 1.13  2006/01/05 00:01:21  elphel
00277 *!  fixed hang-up - removed restarting a frame that was sometimes hanging a sensor until reset
00278 *!
00279 *!  Revision 1.12  2006/01/02 23:21:24  elphel
00280 *!  modified with/for Kodak sensor
00281 *!
00282 *!  Revision 1.11  2005/12/15 05:18:13  elphel
00283 *!  FPGA to accommodate USB controller, vector interrupts, 6 i/o pins contorl
00284 *!
00285 *!  Revision 1.10  2005/11/29 23:43:24  spectr_rain
00286 *!  fix autoexpose with streamers
00287 *!
00288 *!  Revision 1.9  2005/11/29 09:13:00  spectr_rain
00289 *!  add autoexposure
00290 *!
00291 *!  Revision 1.8  2005/11/23 05:11:47  spectr_rain
00292 *!  add done_compress IRQ bottom half
00293 *!
00294 *!  Revision 1.7  2005/09/10 23:33:22  elphel
00295 *!  Support of realtime clock and timestamps in the images
00296 *!
00297 *!  Revision 1.6  2005/09/06 03:40:37  elphel
00298 *!  changed parameters, added support for the photo-finish mode
00299 *!
00300 *!  Revision 1.5  2005/08/27 05:16:27  elphel
00301 *!  binning
00302 *!
00303 *!  Revision 1.4  2005/08/27 00:46:39  elphel
00304 *!  bayer control with &byr=
00305 *!
00306 *!  Revision 1.3  2005/08/26 02:59:06  elphel
00307 *!  working on histogram
00308 *!
00309 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00310 *!  *** empty log message ***
00311 *!
00312 */
00313 //TODO: remove sensor i2c communication from this file - move it to sensor driver
00314 /****************** INCLUDE FILES SECTION ***********************************/
00315 
00316 #define USE_HARDWARE_I2C y
00317 #include <linux/module.h>
00318 #include <linux/sched.h>
00319 #include <linux/slab.h>
00320 #include <linux/errno.h>
00321 #include <linux/kernel.h>
00322 #include <linux/fs.h>
00323 #include <linux/string.h>
00324 #include <linux/init.h>
00325 #include <linux/autoconf.h>
00326 //#include <linux/poll.h>
00327 #include <linux/interrupt.h>
00328 #include <linux/time.h>
00329 
00330 #include <asm/system.h>
00331 //#include <asm/svinto.h> obsolete
00332 
00333 //#include <asm/arch/hwregs/reg_map.h>
00334 //#include <asm/arch/hwregs/reg_rdwr.h>
00335 #include <asm/arch/hwregs/intr_vect.h> // EXT_INTR_VECT
00336 //#include <asm/arch/hwregs/intr_vect_defs.h>
00337 #include <asm/arch/hwregs/intr_vect_defs.h>
00338 
00339 
00340 #include <asm/io.h>
00341 
00342 #include <asm/irq.h>
00343 
00344 #include <asm/delay.h>
00345 #include <asm/uaccess.h>
00346 
00347 #include <asm/arch/cache.h> 
00348 
00349 
00350 
00351 #include <asm/elphel/c313a.h>
00352 #include <asm/elphel/exifa.h>
00353 
00354 #include "fpgactrl.h"  // defines port_csp0_addr, port_csp4_addr 
00355 #include "fpga_sdram.h" // use a single fpga_initSDRAM(void)
00356 
00357 
00358 #include "x3x3.h"
00359 #include "cc3x3.h"
00360 #include "cxsdram.h"
00361 #include "cci2c.h"
00362 #include "cxdma.h"
00363 #include "circbuf.h"
00364 
00365 #include "fpgaconfi2c.h"  //to control clocks
00366 
00367 #include "hist.h"
00368 #include "exif353.h"
00369 
00370 // make conditional later
00371 #ifdef CONFIG_ETRAX_323
00372 #include "sensorfpgajtag.h"
00373 #endif
00374 #ifdef CONFIG_ETRAX_ELPHEL_MCP
00375  #include "ccmcp.h"
00376 #else
00377  #define MCPpresent() 0
00378  #define MCP_open(inode,filp) -1
00379  #define MCP_lseek(file,offset,orig) 0
00380  #define MCP_read(file,buf,count,off) 0
00381 
00382 
00383  #define MCP_write(file,buf,count,off) 0
00384 #endif
00385 
00386 #ifdef CONFIG_ETRAX_ELPHEL_ZR32112
00387  #include "cczr32112.h"
00388 #endif
00389 
00390 #ifdef CONFIG_ETRAX_ELPHEL_ZR32212
00391  #include "cczr32212.h"
00392 #endif
00393 
00394 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
00395  #include "cckac1310.h"
00396 //temporary with KAC will be CONFIG_ETRAX_ELPHEL_MI1300
00397 #endif
00398 // still supports image flipping needed for 1.3Mpix cameras
00399 /*
00400 #ifdef CONFIG_ETRAX_ELPHEL_MI1300
00401  #include "ccmi1300.h"
00402 #endif
00403 */
00404 // unified driver for 1.3-2.0-3.0Mpixel sensors (no flipping)
00405 #ifdef CONFIG_ETRAX_ELPHEL_MT9X001
00406  #include "mt9x001.h"
00407 #endif
00408 #ifdef CONFIG_ETRAX_ELPHEL_IBIS51300
00409  #include "ccibis51300.h"
00410 #endif
00411 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
00412  #include "kac5000.h"
00413 #endif
00414 
00415 
00416 #if ELPHEL_DEBUG
00417   #define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00418   //#define MD1(x)
00419   #define MD12(x) printk("%s:%d:",__FILE__,__LINE__);x
00420   //#define MD12(x)
00421   #define MD13(x) printk("%s:%d:",__FILE__,__LINE__);x
00422   //#define MD13(x)
00423   #define MD20(x) printk("%s:%d:",__FILE__,__LINE__);x
00424 #else
00425   #define MD1(x)
00426   #define MD12(x)
00427   #define MD13(x)
00428   #define MD20(x)
00429 #endif
00430 
00431 
00432 
00434 //#define MD11(x) printk("%s:%d:",__FILE__,__LINE__);x
00435 #define MD11(x)
00436 
00437 //#define MD10(x) printk("%s:%d:",__FILE__,__LINE__);x
00438 #define MD10(x)
00439 //#define MD9(x) printk("%s:%d:",__FILE__,__LINE__);x
00440 #define MD9(x)
00441 
00442 //MD8 - about i2c
00443 //#define MD8(x) printk("%s:%d:",__FILE__,__LINE__);x
00444 #define MD8(x)
00445 
00447 //#define MD7(x) printk("%s:%d:",__FILE__,__LINE__);x
00448 #define MD7(x)
00449 
00450 //#define MD6(x) printk("%s:%d:",__FILE__,__LINE__);x
00451 #define MD6(x)
00452 
00454 //#define MD2(x) printk("%s:%d:",__FILE__,__LINE__);x
00455 #define MD2(x)
00456 
00457 //#define D(x) x
00458 #define D(x)
00459 #define D1(x)
00460 #define D2(x)
00461 #define D3(x)
00462 #define D4(x)
00463 
00464 #define D5(x) printk("%s:%d:",__FILE__,__LINE__);x
00465 
00466 
00467 #define CMOSCAM_MAJOR 126  /* LOCAL/EXPERIMENTAL */
00468 static const char cmoscam_name[] = "cmoscam353";
00469 
00470 /* Camera revision dependent defines are here */
00471 // Defines for Model 303 revA/M camera
00472 #define MY_MODULE_DESCRIPTION "Elphel model 353  camera driver"
00473 #define CMOSCAM_DRIVER_NAME "CMOS/MCP camera 353 driver\n"
00474 
00475 
00476 #define X313_ACQUIRE_STOP      port_csp0_addr[X313_WA_TRIG]=0
00477 #define X313_ACQUIRE_ONCE      port_csp0_addr[X313_WA_TRIG]=(imageParamsR[P_TRIG] & 1)?6:4
00478 #define X313_ACQUIRE_INTERNAL  port_csp0_addr[X313_WA_TRIG]=4
00479 #define X313_ACQUIRE_EXTERNAL  port_csp0_addr[X313_WA_TRIG]=6
00480 #define X313_ACQUIRE_ON        port_csp0_addr[X313_WA_TRIG]=5
00481 
00482 //  #define   X313_WA_IRQ_RST   0x1c // reset selected interrupt bits
00483 //  #define   X313_WA_IRQ_DIS   0x1d // disable selected interrupt bits (mask)
00484 //  #define   X313_WA_IRQ_ENA   0x1e // enable selected interrupt bits
00485 //  #define   X313_WA_IRQ_WVECT 0x1f // write vector number (in bits [0:7], [11:8] - interrupt number (0..15)
00486 // intm_shadow not used, disable and reset as was before (only 8 interrupts - does not touch USB
00487 #ifdef CONFIG_ETRAX_ELPHEL353
00488     #define EN_INTERRUPT(x)  port_csp0_addr[X313_WA_IRQ_ENA]= (1<< x )
00489     #define DIS_INTERRUPT(x) {port_csp0_addr[X313_WA_IRQ_DIS]= (1<< x ); port_csp0_addr[X313_WA_IRQ_RST]= (1<< x );}
00490     #define DIS_INTERRUPTS   {port_csp0_addr[X313_WA_IRQ_DIS]= 0xff; port_csp0_addr[X313_WA_IRQ_RST]= 0xff;}
00491 #else
00492   #ifdef CONFIG_ETRAX_333
00493     #define EN_INTERRUPT(x)  port_csp0_addr[X313_WA_IRQ_ENA]= (1<< x )
00494     #define DIS_INTERRUPT(x) {port_csp0_addr[X313_WA_IRQ_DIS]= (1<< x ); port_csp0_addr[X313_WA_IRQ_RST]= (1<< x );}
00495     #define DIS_INTERRUPTS   {port_csp0_addr[X313_WA_IRQ_DIS]= 0xff; port_csp0_addr[X313_WA_IRQ_RST]= 0xff;}
00496   #else
00497     #define EN_INTERRUPT(x)  port_csp0_addr[X313_WA_IRQM]= (intm_shadow |=  (1<< x ))
00498     #define DIS_INTERRUPT(x) port_csp0_addr[X313_WA_IRQM]= (intm_shadow &= ~(1<< x ))
00499     #define DIS_INTERRUPTS   port_csp0_addr[X313_WA_IRQM]= (intm_shadow = 0)
00500   #endif
00501 #endif
00502 
00503 // t - test (0,1), s - subtract mode (0-3), m - multiply mode (0-3), d - depth (0 - 8, 1 - 16), l - left shift (8 bit only)
00504 
00505 /*#define PROGRAM_FPN(t,s,m,d,l)      port_csp0_addr[X313_WA_SENSFPN]=    \
00506                                         (((t) & 1) << 7) | \
00507                                         (((s) & 3) << 5) | \
00508                                         (((m) & 3) << 3) | \
00509                                         (((d) & 1) << 2) | \
00510                                         (((l) & 3) << 0)  */
00511 // t - test (0,1), s - subtract mode (0-7), m - multiply mode (0-7), d - depth (0 - 8, 1 - 16), l - left shift (8 bit only)
00512 #define PROGRAM_FPN(t,s,m,d,l)      port_csp0_addr[X313_WA_SENSFPN]=    \
00513                                         (((t) & 1) << 10) | \
00514                                         (((s) & 7) << 7) | \
00515                                         (((m) & 7) << 4) | \
00516                                         (((d) & 1) << 3) | \
00517                                         (((l) & 7) << 0)
00518 // saving glogbal parameters combine all (but width) in one
00519 // w:  - 0- 8bit,1 - 16 bits
00520 // p: bits 3:0 - shift 
00521 //         6:4 - mpy mode
00522 //         10:8 - sub mode
00523 //         12 - test mode
00524 /*#define PROGRAM_FPNW(p,w)      port_csp0_addr[X313_WA_SENSFPN]=    \
00525                                         (((p) & 0x1000) >> 2) | \
00526                                         (((p) &  0x700) >> 1) | \
00527                                         (((p) &   0x70) >> 0) | \
00528                                         (((w) &      1) << 3) | \
00529                                         (((p) &      7) << 0)*/
00530 
00531 
00532 
00533 
00534 // program DMA block size
00535 //define PROGRAM_BLKSZ(x)  port_csp0_addr[CCAM_WA_WBLKSZ]= x
00536 // program FPGA  mclk - needs to change external clock
00537 //#define PROGRAM_CLK_DIV(x)  CCAM_SETFIELD(CLKDIV, x )
00538 // enable clock to sensor
00539 #define PROGRAM_CLK_EN(x)   X313_SETFIELD(CLKEN,  x )
00540 // program depth - combine with other parameters
00541 // #define PROGRAM_DEPTH(x)     CCAM_SETFIELD(DEPTH,(( x )==4)? 2 :((( x )==8)? 1 : 0))
00542 // program left shift
00543 // #define PROGRAM_SHIFT(x)     CCAM_SETFIELD(SHFT,(( x )==3)? 3 :((( x )==2)? 0 : ((( x )==1)? 1 : 2)))
00544 // program color compressor mode
00545 // #define PROGRAM_COLOR(x)     CCAM_SETFIELD(COLOR, x)
00546 // program aux clock (0/1/20MHz)
00547 // #define PROGRAM_AUXCM(x)     CCAM_SETFIELD(AUXCM, x)
00548 
00549 
00550 // do not use aux connector pins (used to program KAI11000 FPGA)
00551 #define CCAM_DONOTUSEAUX (ccam_cr_shadow & X313_MASK(KAI11000))
00552 
00553 //IS_KAI11000
00554 #define CCAM_ARO_ON \
00555         ccamCROr( X313_BITS(ARO,1) )
00556 #define CCAM_ARO_OFF \
00557         ccamCRAnd(~X313_BITS(ARO,1) )
00558 
00559 // turn clock to sensor on/off (default - on)
00560 #define CCAM_DCLK_OFF \
00561         ccamCROr( X313_BITS(DCLKMODE,1) )
00562 #define CCAM_DCLK_ON \
00563         ccamCRAnd(~X313_BITS(DCLKMODE,1) )
00564 
00565 // ARST is opposite in 303!
00566 #define CCAM_ARST_OFF \
00567         ccamCROr( X313_BITS(ARST,1) )
00568 #define CCAM_ARST_ON \
00569         ccamCRAnd(~X313_BITS(ARST,1) )
00570 
00571 #define CCAM_MRST_OFF \
00572         ccamCROr( X313_BITS(MRST,1) )
00573 #define CCAM_MRST_ON \
00574         ccamCRAnd(~X313_BITS(MRST,1) )
00575   
00576 #define CCAM_NEGRST \
00577         ccamCROr( X313_BITS(NEGRST,1) )
00578 #define CCAM_POSRST \
00579         ccamCRAnd(~X313_BITS(NEGRST,1) )
00580 
00581 // enable power converter control. *** Only if it is not MT9P001 !!! ***
00582 #define CCAM_CNVEN_OFF \
00583    ccamCRAnd(~X313_BITS(CNVEN,1) )
00584 
00586 #define CCAM_TRIG_INT \
00587    ccamCRAnd(~X313_BITS(TRIGSRC,1) )
00588 #define CCAM_TRIG_EXT \
00589    ccamCROr( X313_BITS(TRIGSRC,1) )
00590 
00592 #define CCAM_TIMESTAMP_NORMAL \
00593    ccamCRAnd(~X313_BITS(EARLYTRIG,1) )
00594 #define CCAM_TIMESTAMP_EARLY \
00595    ccamCROr( X313_BITS(EARLYTRIG,1) )
00596 
00597 
00598 
00599 // For sensor where HACT (and VACT, BPF) switches later than PXD
00600 // it is possible to compensate HACT by registering it later by N/4Tpclk (where 0<=N<=3)
00601 // definitely needed for MT5P001 @ 96MHz (3/4)
00602 #define CCAM_SET_HACT_PHASE(x) ccamCRAndOr(~X313_MASK(HACT_PHASE), X313_BITS(HACT_PHASE, (x)))
00603 
00604 
00605 #if 0 // restore that back after playing with 10359 board
00606 #ifdef CONFIG_ETRAX_ELPHEL_FORCE_MT9P001
00607   #define CCAM_CNVEN_ON \
00608    printk ("\r\n*** Turning voltage is disabled in kernel config - CONFIG_ETRAX_ELPHEL_FORCE_MT9P001 ***\r\n")
00609 #else
00610   #define CCAM_CNVEN_ON \
00611    printk ("\r\n*** Maybe fatal for MT9P001 !!! Set CONFIG_ETRAX_ELPHEL_FORCE_MT9P001 if troubleshooting MT9P001 ***\r\n");ccamCROr( X313_BITS(CNVEN,1) )
00612 #endif
00613 #else
00614   #define CCAM_CNVEN_ON \
00615    printk ("\r\n*** Maybe fatal for MT9P001 !!! Set CONFIG_ETRAX_ELPHEL_FORCE_MT9P001 if troubleshooting MT9P001 ***\r\n");ccamCROr( X313_BITS(CNVEN,1) )
00616 #endif
00617 // output "EXPOS" is used to communicate with FPGA on MCP board, else - as external output
00618 // will go to FPGA - later
00619 /*
00620 #define CCAM_EXP_EN \
00621         if (!MCPpresent()) ccamCRAnd(~(X313_BITS(EXP,1) | X313_BITS(EXPPOL,1) ) )
00622 #define CCAM_EXP_DIS \
00623         if (!MCPpresent()) ccamCROr (  X313_BITS(EXP,1) | X313_BITS(EXPPOL,1) )
00624 */
00625 
00626 #define X313_MAXMINOR 15
00627 //extern unsigned long ccam_dma_buf[CCAM_DMA_SIZE + PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
00628 
00629 
00630 
00631 
00632 //extern unsigned long ccam_dma_buf1[CCAM_DMA_SIZE + PAGE_SIZE];
00633 //unsigned long * ccam_dma_buf= ccam_dma_buf1;
00634 
00635 /*
00636  * Initial parameters, common for all for all sensors
00637  */
00638 //static struct sensor_t sensor; // current sensor (will be copied to by sensor driver)
00639 struct sensor_t sensor; // current sensor (will be copied to by sensor driver)
00640 unsigned short gamma_tables_soft[1028];
00641 int gamma_tables_changed=0; // to know that closing tables needs writing FPGA
00642 
00643 static DECLARE_MUTEX(sensor_lock);
00644 
00645 
00646 static unsigned long default_common[]= \
00647    {
00648    P_WOI_WIDTH,       1280,
00649    P_WOI_HEIGHT,      1024,
00650    P_WOI_LEFT,        0,
00651    P_WOI_TOP,         0,
00652    P_SENSOR,    0,
00653    P_TRIG,              2, // enable stopping clip by external input
00654    P_EXPOS,             1,
00655 //   P_DMA_SZ,  0x0f,   // default DMA blok size = 16 words
00656 //   P_DMA_LOOP,        CCAM_DMA_SIZE,  // will be updated
00657    P_PAGE_ACQ,  0,  // Number of image page buffer to acquire to (0.1?)
00658    P_PAGE_READ, 0,  // Number of image page buffer to read from to (0.1?)
00659 
00660 
00661    P_BGFRAME,   0,  // not a background mode
00662    P_OVERLAP,   0,      // (will be overwritten) Rolling Shutter DMA length (number of words to be acquired over frame size)
00663    P_AUXCM,             0,              // 0 on auxclk pin
00664    P_BIN_HOR,   0,              // no binning h
00665    P_BIN_VERT,  0,              // no binning h
00666    P_COLOR,             0,              // monochrome mode
00667 //   P_VIDEO,           0,              // still mode
00668 //   P_TEST,            0,              // normal mode
00669    P_MCLK,              4,              // divide by 4 -- FPGA, divide by 80MHz by P_MCLK
00670 //   P_MCLK_DIS,  0,            // enable MCLK to sensor
00671    P_DCM_HOR,   0,              // 0 - no decimation, 1 - 1/2, 2 - 1/4, 3 - 1/8, etc.
00672    P_DCM_VERT,  0,              // 0 - no decimation, 1 - 1/2, 2 - 1/4, 3 - 1/8, etc.
00673 
00674    P_BITS,         8,           // 8-bit mode
00675    P_SHIFTL,    0,              // no pre-scaling
00676    P_FPNS,       0,      // no FPN correction
00677    P_FPNM,       0,      // no FPN correction
00678 //   P_FPN,       0,      // no FPN correction
00679    P_VEXPOS,    0,
00680 
00681    P_GAINR,             0,
00682    P_GAING,             0,
00683    P_GAINB,             0,
00684    P_GAINGB,    0,
00685    P_FATZERO,   0,
00686    P_VIRTTRIG,  0,
00687    P_QUALITY,   50,
00688    P_COLOR_SATURATION_BLUE, 100,
00689    P_COLOR_SATURATION_RED,  100,
00690    P_GSCALE,                256, // whas not defined before, 256 (1.0 - use the same greens)
00691    
00692    P_GAMMA, 100,
00693    P_PIXEL_LOW, 0,
00694    P_PIXEL_HIGH, 255,
00695    P_FRAMESYNC_DLY, 0,
00696    P_PF_HEIGHT, 0,
00697    P_FPSLM, 0,
00698    P_TASKLET_CTL, 0,
00699    P_SKIP_FRAMES, 1,   
00700    P_I2C_QPERIOD, 100,
00701    P_I2C_BYTES,2,
00702    P_OVERSIZE,0,
00703    P_I2C_BYTES,2,
00704    P_IRQ_SMART,3
00705    };
00706 
00707 #define SCALE_MIN       0x040
00708 #define SCALE_MAX       0x400
00709 extern unsigned long gain_balance(unsigned long *scale, unsigned long gain);
00710 struct gains_t gains = {
00711         .red = 0x100,
00712         .green = 0x100,
00713         .blue = 0x100,
00714 };
00715 
00716 struct frame_params_t frame_params ={
00717 /*00-03 unsigned int */   .exposure=0,       
00718 /*04-05 unsigned short */ .width=0,          
00719 /*06-07 unsigned short */ .height=0,         
00720 /*08-11 unsigned long  */ .colorsat=  DEFAULT_COLOR_SATURATION_BLUE | (DEFAULT_COLOR_SATURATION_RED << 16), 
00721 /*12    unsigned char  */ .color=0,          
00722 /*13    unsigned char  */ .quality=50,       
00723 /*14    unsigned char  */ .gamma=100,        
00724 /*15    unsigned char  */ .black=0,          
00725 /*16-17 unsigned short */ .rscale=0,         
00726 /*18-19 unsigned short */ .bscale=0,         
00727 
00728 /*20    unsigned char  */ .gain_r=0,         
00729 /*21    unsigned char  */ .gain_g=0,         
00730 /*22    unsigned char  */ .gain_b=0,         
00731 /*23    unsigned char  */ .gain_gb=0,        
00732 /*24-25 unsigned short */ .meta_index =0,     
00733 
00734 /*26-27 unsigned short */ .signffff=0xffff,   
00735 
00736 /*28-31 unsigned long  */ {.timestamp_sec=0},  
00737 /*32-35 unsigned long  */ .timestamp_usec=0  
00738 };
00739   unsigned long  * frame_params_ul= (unsigned long *) &frame_params; // fighting caching of circular buffer
00740 //  unsigned short * exif_index=  (unsigned short * ) &frame_params.bindec_hor;
00741   unsigned short * exif_index=  (unsigned short * ) &frame_params.meta_index;
00742   static struct meta_offsets_t { // works like a cache to time save on looking for tags in the directory (forced to recalcualte if does not match)
00743     int Image_DateTime;          // will have offset of the Exif_Image_DateTime data in meta page (Exif_Photo_SubSecTime should go immediately after in meta page)
00744     int Photo_DateTimeOriginal;
00745     int Photo_ExposureTime;
00746     int Image_FrameNumber;
00747   } meta_offsets;
00748 
00749   char * exif_meta_time_string;
00750 void dumpFrameParams(struct frame_params_t * fp, const char * title) {
00751 //  double d1,d2,d3;
00752 //  char   s[1024];
00753   printk ("%s\n",title);
00754   printk (".exposure=          %d * 100usec\n",(int)fp->exposure);
00755   printk (".width=             %d\n", (int)fp->width);
00756   printk (".height=            %d\n",(int)fp->height);
00757   printk (".colorsat=        0x%x (%d / %d)\n",(int)fp->colorsat, (int)((100.0*(fp->colorsat>>16))/DEFAULT_COLOR_SATURATION_RED),   (int) ((100.0*(fp->colorsat & 0xffff))/DEFAULT_COLOR_SATURATION_BLUE));
00758   printk (".color=           0x%x (color=%d, flipX=%d, flipY=%d)\n",(int) fp->color,  (int) fp->color & 0x0f,  (int) (fp->color >> 6) & 1, (int) (fp->color >> 7) & 1);
00759   printk (".quality=           %d\n",(int) fp->quality);
00760   printk (".gamma=             %d\n",(int) fp->gamma);
00761   printk (".black=             %d\n",(int) fp->black);
00762   printk (".rscale=          0x%x (%d)\n",(int) fp->rscale,  (int)((100.0*fp->rscale)/256));
00763   printk (".bscale=          0x%x (%d)\n",(int) fp->bscale,  (int)((100.0*fp->bscale)/256));
00764   printk (".gain_r=          0x%x (%d)\n",(int) fp->gain_r,  (int)((100.0*fp->gain_r)/16));
00765   printk (".gain_g=          0x%x (%d)\n",(int) fp->gain_g,  (int)((100.0*fp->gain_g)/16));
00766   printk (".gain_b=          0x%x (%d)\n",(int) fp->gain_b,  (int)((100.0*fp->gain_b)/16));
00767   printk (".gain_gb=         0x%x (%d)\n",(int) fp->gain_gb, (int)((100.0*fp->gain_gb)/16));
00768 //  printk (".bindec_hor=      0x%x (bin: %d dec: %d)\n",(int) fp->bindec_hor, (int) (fp->bindec_hor >>4)+1, (int) (fp->bindec_hor & 0x0f)+1);
00769 //  printk (".bindec_vert=     0x%x (bin: %d dec: %d)\n",(int) fp->bindec_vert, (int) (fp->bindec_vert >>4)+1,     (int) (fp->bindec_vert & 0x0f)+1);
00770   printk (".meta_index=      0x%x\n",(int) fp->meta_index);
00771   printk (".signffff=        0x%x\n",(int) fp->signffff);
00772   printk (".timestamp_sec=   0x%x\n",(int) fp->timestamp_sec);
00773   printk (".timestamp_usec=  0x%x\n",(int) fp->timestamp_usec);
00774 }
00775 static int minors[X313_MAXMINOR+1];     // each minor can be opened only once
00776 
00777 static unsigned char sensor_i2c_addr;   // 0x60 for ZR32112, ZR32212; 0x66 for KAC1310
00778 
00779 //static unsigned char sensor_i2c_regs[0x200]; // was 0x17 -- only first 32 accessible through ioctl
00780 static unsigned short sensor_i2c_regs16[0x100];
00781 unsigned char * sensor_i2c_regs;
00782 
00783 // migration to read/write instead of IOCTL. First 64 will still be accessible with ioctl, all through read/write.
00784 // first 4096 bytes when written will go to imageParamsW, when read - from imageParamsR. Reading from bytes 4096..8191 will
00785 // return imageParamsW
00786 //#define P_NUMBER         1024   //number of registers (was 64)
00787 static unsigned long imageParamsR[P_NUMBER * 4] __attribute__ ((aligned (PAGE_SIZE)));   // Sensor Parameters (user read)
00788 unsigned long *imageParamsW=&imageParamsR[P_NUMBER]; // sensor parameters (user write) go immediately after read parameters
00789 unsigned long *imageParamsR_PREV=&imageParamsR[2*P_NUMBER]; // (some) sensor parameters delayed by 1 frame
00790 unsigned long *imageParamsR_PREV_PREV=&imageParamsR[3*P_NUMBER]; // (some) sensor parameters delayed by 2 frames
00791 // variables that should be prepared for JPEG control in programSensor()
00792 
00793 
00794 struct autoexp_t * autoexp_state= NULL;
00795 struct autoexp_t * autoexp_set=  NULL;
00796 struct aexp_window_t * aexp_window = NULL;
00797 struct aexp_window_t * aexp_window_set = NULL;
00798 
00799 
00800 static int jpeg_sdram_ctl0;
00801 
00802 volatile unsigned long ccam_cr_shadow=0;
00803 /*
00804  * Functions used in only in this file
00805  */
00806 
00807 static int getCamSeqState(void);
00808 static int getCamSeqCount(void);
00809 static void setCamSeqState(int v);
00810 static void setCamSeqCount(int v);
00811 static  void initCamIRQs(void);
00812 
00813 static int camSeqStart(void);
00814 
00815 //static irqreturn_t camSeq_interrupt(int irq, void *dev_id, struct pt_regs * regs);
00816 static irqreturn_t camSeq_interrupt(int irq, void *dev_id);
00817 static int x313_JPEG_cmd_wrapper(int arg); 
00818 static int ccam_DMA_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg);
00819 
00820 static int cmoscam_open(struct inode *inode, struct file *filp);
00821 
00822 static int cmoscam_release(struct inode *inode, struct file *filp);
00823 static int cmoscam_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
00824 static loff_t cmoscam_lseek(struct file * file, loff_t offset, int orig);
00825 static ssize_t cmoscam_read(struct file * file, char * buf, size_t count, loff_t *off);
00826 static ssize_t cmoscam_write(struct file * file, const char * buf, size_t count, loff_t *off);
00827 static int cmoscam_mmap (struct file *file, struct vm_area_struct *vma);
00828 static unsigned int cmoscam_poll (struct file *file, poll_table *wait);
00829 
00830 static int __init cmoscam_init(void);
00831 static int init_sensor(void);
00832 static int programSensor(int nonstop);
00833 static int init_FPGA(void); //will check FPGA version, init SDRAM (if needed) and sensor
00834 //static void initSDRAM(void); // - use fpga_initSDRAM(void)
00835 static void camSeq_dump (void);
00836 
00837 void adjust_fps_2_compressor(void);
00838 
00839 
00840 //r/w to fpga tables (not all readable) - move to separate file?
00841 void x313_tables_gammainitlinear(void);
00842 loff_t  x313_tables_lseek(struct file * file, loff_t offset, int orig) ;
00843 ssize_t x313_tables_write(struct file * file, const char * buf, size_t count, loff_t *off) ;
00844 ssize_t x313_tables_read(struct file * file, char * buf, size_t count, loff_t *off) ;
00845 loff_t  x313_histogram_lseek(struct file * file, loff_t offset, int orig) ;
00846 ssize_t x313_histogram_read(struct file * file, char * buf, size_t count, loff_t *off) ;
00847 
00848 int write_gamma_fpga (unsigned short gamma_table[1028]);
00849 loff_t  x313_gamma_lseek(struct file * file, loff_t offset, int orig);
00850 ssize_t x313_gamma_read(struct file * file, char * buf, size_t count, loff_t *off) ;
00851 ssize_t x313_gamma_write(struct file * file, const char * buf, size_t count, loff_t *off) ;
00852 
00853 loff_t x313_senspars_lseek(struct file * file, loff_t offset, int orig);
00854 ssize_t x313_senspars_read(struct file * file, char * buf, size_t count, loff_t *off);
00855 ssize_t x313_senspars_write(struct file * file, const char * buf, size_t count, loff_t *off);
00856 int     x313_senspars_mmap (struct file *file, struct vm_area_struct *vma);
00857 
00858 void x313_program_focus(int totalwidth);
00859 
00860 
00861 static struct file_operations cmoscam_fops = {
00862         owner:    THIS_MODULE,
00863         llseek:   cmoscam_lseek,
00864         read:     cmoscam_read,
00865         write:    cmoscam_write,
00866         ioctl:    cmoscam_ioctl,
00867         open:     cmoscam_open,
00868         mmap:     cmoscam_mmap,
00869         poll:     cmoscam_poll,
00870 
00871         release:  cmoscam_release
00872 };
00873 
00874 /* ++++++++++++++++++++++++++++ IRQ/camseq related stuff +++++++++++++++++++++++++++++++++++ */
00875 // parameters, copied from Verilog file "emultasks.v"
00876 // define interrupt numbers
00877 #define nint_vact       0 // start of VACT pulse
00878 #define nint_xint               1 // external enterrupt
00879 #define nint_xferovr    2 // DMA xfer over
00880 #define nint_done       3 // DMA xfer over, persistent till reset through...
00881 
00882 #define nint_eot        4
00883 #define nint_overrun    5     // persistent till compressor reset
00884 #define nint_done_input 6     // persistent till compressor reset/restarted
00885 #define nint_done_compress 7  // persistent till compressor reset/restarted
00886 #define nint_smart      8  // Single cycle, does not need restart, configurable to wait for VACT, always at VACT if no compression is underway
00887 
00888 
00889 #define MAXEXPOSURE     60000   //60 sec, in 1ms increments
00890 //static        volatile int camSeqState;
00891 /*
00892 #define CAMSEQ_OFF       0 // off, not programmed (Video mode off on Zoran sensors)
00893 #define CAMSEQ_READY     1 // sensor programmed may acquire at will (programSensor sets number of frames to skip (if any)
00894 #define CAMSEQ_SKIP      2 // skipping specified number of frames, interrupt service routine counts and will start acquisition
00895 #define CAMSEQ_WAIT_F    3 // set by "start exposure" or interrupt service routine. WAIT_F/WAIT_T/acquire/done differs by hardware register
00896 #define CAMSEQ_WAIT_T    4 // set by "start exposure" or interrupt service routine. Wait/acquire/done differs by hardware register
00897 #define CAMSEQ_ACQUIRE   5 // acquisition in progress (camSeqState is still CAMSEQ_WAIT)
00898 #define CAMSEQ_DONE      6 // acquisition over  (camSeqState is still CAMSEQ_WAIT)
00899 #define CAMSEQ_JPEG      7 // waiting for JPEG done interrupt, acquiring/compressing some frames
00900 
00901 #define CAMSEQ_RUN       8 // compressor is constantly running (or skipping "bad" frames)
00902 #define CAMSEQ_STOP      9 // compressor is constantly running but will stop after next "compressor ready"
00903 
00904 Status CAMSEQ_OFF may be changed to CAMSEQ_READY only by programSensor, it will also stop sensor (if needed)
00905   and set camSeqCount (if needed) to skip certain number of frames before actual acquisition
00906   camSeqStart (called mostly through ioctl) will return error if state was not "CAMSEQ_READY" or "CAMSEQ_DONE".
00907   If called from correct states will either start ISR-based waiting for specified number of frames  or just acquisition.
00908   In the first case ISR will start acquisition itself
00909   State "CAMSEQ_WAIT" is set at the same time as starting acquisition (by either camSeqStart() or ISR),
00910   States CAMSEQ_ACQUIRE, CAMSEQ_DONE are returned after testing the hardware register in FPGA if camSeqState==CAMSEQ_WAIT
00911   camSeqStop will terminate any acquisition in progress and set state to CAMSEQ_READY (if it was not CAMSEQ_OFF)
00912 
00913 */
00914 
00915 //static void x313_f_invalidate (void); // to be called when page number is changed. Write should not be in progress
00916 
00917 #ifndef CONFIG_ETRAX_ELPHEL353
00918   #ifdef CONFIG_ETRAX_333
00919   #else
00920     static volatile unsigned long intm_shadow=0;
00921   #endif
00922 #endif
00923 
00924 static volatile int camSeqCount;
00925 static volatile int camSeqState;
00926 static volatile int JPEG_wp;
00927 static volatile int JPEG_rp;
00928 static volatile int JPEG_len;   // current length in buffer;
00929 
00930 
00931 static unsigned long DMA_buf_start;
00932 
00933 static volatile int JPEG_nfr;   // number of frames left to acquire
00934 static volatile int JPEG_lfr;   // total frames length to acquire
00935 
00936 static volatile int dbg_20;   // contents of register 20 at the compression start
00937 static volatile int dbg_28;   // same for 0x28
00938 
00939 
00940 /* x313_wait_queue -- so a reader can sleep while waiting for something
00941 *       to do.
00942 */
00943 wait_queue_head_t x313_wait_queue;
00944 static inline void startAcquire(void) {
00945 //   setCamSeqState(CAMSEQ_WAIT_F);
00946    camSeqState=CAMSEQ_WAIT_F;
00947    camSeqCount=0;
00948    imageParamsR[P_CAMSEQSTATE]=CAMSEQ_WAIT_F;
00949    imageParamsR[P_CAMSEQCOUNT]=0;
00950    if (imageParamsR[P_BGFRAME]) X313_ACQUIRE_INTERNAL ;
00951    else                         X313_ACQUIRE_ONCE ;
00952    EN_INTERRUPT(nint_xferovr);
00953 
00954 }
00955 
00956 // X313_ACQUIRE_ON
00957 // void x313_dma_start(void);
00958 // int  x313_dma_stop(void);
00959 
00960 
00961 // for video(?) compressed images acquisition
00962 
00963 // sensor is assumed running in continuous mode, ETRAX DMA on
00964 // will see if more frames are needed (both in count and memory)
00965 // and (re)start frame compression (live).
00966 
00967 //     i=((((*R_DMA_CH5_BUF) - virt_to_phys (ccam_dma_buf)) & 0x7fffffff) + (( *R_DMA_CH5_STATUS ) & 0x7f))>>2;
00968 // OK, I've got it. Actual data length is the sum of BUF and STATUS
00969 //     if (i>=CCAM_DMA_SIZE) i-=CCAM_DMA_SIZE;
00970 //  #define X313__RA__IRQS      0x11    // read interrupt register
00971 // There should be couple extra lines after the frame, so compressor will have time to finish before
00972 // frame sync IRQ
00973 
00974 /*
00975 extern void hist_irq_done(void);
00976 extern void hist_irq_vact(void);
00977 
00978 void tasklet_done_compress_f(unsigned long arg) {
00979         hist_irq_done();
00980 }
00981 
00982 DECLARE_TASKLET(tasklet_done_compress, tasklet_done_compress_f, 0);
00983 
00984 void tasklet_vact_f(unsigned long arg) {
00985         hist_irq_vact();
00986 }
00987 
00988 DECLARE_TASKLET(tasklet_vact, tasklet_vact_f, 0);
00989 */
00990 
00991 void tasklet_irq_f(unsigned long arg) {
00992         hist_irq(arg);
00993 }
00994 
00995 DECLARE_TASKLET(tasklet_vact, tasklet_irq_f, IRQ_SRC_VACT);
00996 DECLARE_TASKLET(tasklet_done_compress, tasklet_irq_f, IRQ_SRC_DONE_COMPRESS);
00997 //extern unsigned long *ccam_dma;
00998 extern unsigned long ccam_dma_length;
00999 
01000 static int fpga_counter_prev=0;
01001 static int JPEG_wp_prev=0;
01002 
01014 //#define P_COMPRESSOR_CMD 107 // read only - compressor command, last written to FPGA
01015 //  #define COMPRESSOR_CMD_RUN    0x080
01016 //  #define COMPRESSOR_CMD_SINGLE 0x800  
01017 
01018 inline void compressorSingle(void) {
01020      port_csp0_addr[X313_WA_COMP_CMD] = \
01021                 imageParamsR[P_COMPRESSOR_CMD]= \
01022                 (x313_get_JPEG_ctrl() & (~COMPRESSOR_CMD_RUN)) | COMPRESSOR_CMD_SINGLE; 
01023      X313_CHN_EN(2);  
01024 }
01025 inline void compressorRun(void) {
01026      port_csp0_addr[X313_WA_COMP_CMD] = \
01027                 imageParamsR[P_COMPRESSOR_CMD]= \
01028                 x313_get_JPEG_ctrl() | COMPRESSOR_CMD_RUN; 
01029      X313_CHN_EN(2);  
01030 }
01031 inline void compressorStop(void) {
01032      port_csp0_addr[X313_WA_COMP_CMD] = \
01033              imageParamsR[P_COMPRESSOR_CMD]= 0; 
01034      X313_CHN_DIS(2);  
01035      fpga_counter_prev=0; 
01036 }
01038 inline void updateJPEG_wp(void) {
01039      int xferred; 
01040 //     int fpga_cntr=port_csp0_addr[X313__RA__XFERCNTR]; // reducing external accesses - be "green" (lower power)
01042      int fpga_cntr=X313_XFERCNTR; // reducing external accesses - be "green" (lower power)
01043 
01044      xferred=fpga_cntr-fpga_counter_prev; 
01045      fpga_counter_prev=fpga_cntr;
01046      if (xferred <0) xferred+= (1 <<24) ; //rolled over
01047      JPEG_wp_prev=JPEG_wp;
01048      JPEG_wp+= (xferred << 3); 
01049      if (JPEG_wp > CCAM_DMA_SIZE) JPEG_wp-=CCAM_DMA_SIZE;
01050      imageParamsR[P_JPEG_WP] = JPEG_wp; 
01051      imageParamsR[P_CIRCBUFWP]= JPEG_wp<<2; 
01052      imageParamsR[P_FREECIRCBUF] = ((imageParamsR[P_CIRCBUFRP] < imageParamsR[P_CIRCBUFWP])? imageParamsR[P_CIRCBUFSIZE]:0)+ 
01053                                      imageParamsR[P_CIRCBUFRP] - imageParamsR[P_CIRCBUFWP];
01054      imageParamsR[P_FOCUS_VALUE]= X313_HIGHFREQ ; 
01055 }
01056 void resetPointers(void) {
01057       JPEG_wp=0;
01058       imageParamsR[P_JPEG_WP]=JPEG_wp;
01059       imageParamsR[P_CIRCBUFWP]= JPEG_wp<<2;
01060       imageParamsR[P_FREECIRCBUF] = imageParamsR[P_CIRCBUFRP];
01061 //      imageParamsR[P_FRAME]=0;
01062       JPEG_rp=0;
01063       imageParamsR[P_FREECIRCBUF] = 0;
01064       JPEG_len=0;   // current length in buffer;
01065   }
01066 
01067 
01079 inline void advance_imageParamsR(void) { // called to delay exposure to appear in Exif (maybe other parames to be added later), encode exposure to Exif
01080 // done after current Exif page is copied to the buffer, so one more frame delay for exposure
01081    putlong_meta_irq(imageParamsR_PREV[P_EXPOS], &meta_offsets.Photo_ExposureTime,  Exif_Photo_ExposureTime);
01082    putlong_meta_irq(imageParamsR[P_FRAME], &meta_offsets.Image_FrameNumber,  Exif_Image_FrameNumber);
01083    frame_params.exposure=imageParamsR_PREV_PREV[P_EXPOS]; 
01084    imageParamsR_PREV_PREV[P_EXPOS]=imageParamsR_PREV[P_EXPOS] ; // not yet needed
01085    imageParamsR_PREV[P_EXPOS]=     imageParamsR[P_EXPOS] ;
01086    int i2c_frame_number= X3X3_I2C_FRAME ;
01087    imageParamsR[P_FRAME]= (imageParamsR[P_FRAME] & 0xfffffff8) + i2c_frame_number +(((imageParamsR[P_FRAME] & 7) > i2c_frame_number)?8:0);
01088 }
01089 
01090 
01091 inline void add_frame_params(void) {
01092    int alen = JPEG_wp-9; if (alen<0) alen+=CCAM_DMA_SIZE;
01093    int jpeg_len=ccam_dma_buf_ptr[alen] & 0xffffff;
01094    int aframe_params=(alen & 0xfffffff8)- 
01095                      (((jpeg_len + CCAM_MMAP_META + 3) & 0xffffffe0)>>2) // multiple of 32-byte chunks to subtract
01096                      -8; // just size of thestorage area to be filled before the frame
01097    if(aframe_params < 0) aframe_params += CCAM_DMA_SIZE;
01098 
01099 // new Exif handling
01100 
01101    exif_meta_time_string=encode_time(ccam_dma_buf_ptr[alen-2], ccam_dma_buf_ptr[alen-1]); // calculates datetime([20] and subsec[7], returns pointer to char[27]
01102    write_meta_irq(exif_meta_time_string, &meta_offsets.Photo_DateTimeOriginal,  Exif_Photo_DateTimeOriginal, 27); // may be split in datetime/subsec - now it will not notice missing subseq field in template
01103    write_meta_irq(exif_meta_time_string, &meta_offsets.Image_DateTime,  Exif_Image_DateTime, 20); // may use 27 if room is provided
01104    *exif_index= store_meta();
01105    memcpy ((void *) &ccam_dma_buf_ptr[aframe_params], &frame_params, 28) ;// !copy just 28 bytes of the current parameters to the circbuf
01106    ccam_dma_buf_ptr[aframe_params+7]=jpeg_len;
01107    advance_imageParamsR();
01108 
01114    wake_up_interruptible(&circbuf_wait_queue);
01115 
01116 
01117 }
01118 
01119 
01120 extern int slock;
01121 extern void ch0_lock(void);
01122 extern wait_queue_head_t vack_wait_queue;
01123 
01124 #define SIMPLE_IRQ y
01125 
01126 static irqreturn_t camSeq_interrupt(int irq, void *dev_id) {
01127         unsigned long irq_state;
01128 
01129         irq_state = X313_IRQSTATE; 
01130 
01131 // with only vact - no lockup, trying to make done compress look the same (only in run mode when no vacts are allowed)
01132 #define CONFIG_ETRAX_ELPHEL_AUTOEXP y
01133 #ifdef CONFIG_ETRAX_ELPHEL_AUTOEXP
01134         if((irq_state & 0x01) && slock == 2) {
01135                 ch0_lock();
01136                 slock = 1;
01137 //              wake_up_interruptible(&vack_wait_queue);
01138 //              printk("sensor_VACK!!!\r\n");
01139         }
01140 //      if((irq_state & 0x00000001) || ((camSeqState == CAMSEQ_RUN) && (irq_state & 0x00000080))) {
01141 //        if ( irq_state & ((camSeqState == CAMSEQ_RUN)? 0x00000080:0x00000001) ) { // does not seem to work - state 7, IRQs are coming - no autoexposure
01142 // but we do not need this - only one IRQ is enabled at a time
01143         if ((imageParamsR[P_TASKLET_CTL] & 1) == 0) tasklet_schedule(&tasklet_vact);
01144 //      }
01145 #warning using autoexposure
01146 #else
01147 #warning not using autoexposure
01148 #endif
01149         // simulate "inta"
01150         DIS_INTERRUPTS; // disable and clear all interrupts
01151 //      #define CAMSEQ_RUN       8 // compressor is constantly running
01152 //      #define CAMSEQ_STOP      9 // compressor is constantly running but will stop after next "compressor ready"
01153 //      #define CAMSEQ_SINGLE   10 // compressor is constantly running to all the buffer
01154 
01155         // in       
01156 #ifndef SIMPLE_IRQ
01157 #warning using wake_up_interruptible
01158 //      wake_up_interruptible(&x313_wait_queue);
01159 #else
01160 #warning no wake_up_interruptible
01161 #endif
01162    if((camSeqState == CAMSEQ_RUN) || (camSeqState == CAMSEQ_SINGLE)) { 
01163       // find where DMA stopped
01164        if(camSeqCount > 0) { 
01165          advance_imageParamsR();
01166          imageParamsR[P_CAMSEQCOUNT]=(--camSeqCount);
01167          EN_INTERRUPT(nint_vact);
01168        } else {
01169          if((camSeqCount) == 0) { 
01170            advance_imageParamsR();
01171            X313_POSTINIT_SDCHAN(2,(jpeg_sdram_ctl0 | 0x2000));   //read, depend, mode=1 (tiles)
01172            compressorRun();
01173            imageParamsR[P_CAMSEQCOUNT]= (--camSeqCount);
01174            EN_INTERRUPT(nint_done_compress);
01175          } else {  
01176             updateJPEG_wp(); 
01177             add_frame_params();
01178             if((camSeqState == CAMSEQ_SINGLE) && (JPEG_wp < JPEG_wp_prev)) {
01179                camSeqState = CAMSEQ_STOP; 
01180                imageParamsR[P_CAMSEQSTATE]=CAMSEQ_STOP;
01181             }
01182             compressorRun();
01183 //            imageParamsR[P_FRAME]++;
01184             EN_INTERRUPT(nint_done_compress); 
01185          }
01186       }
01187    } else { 
01188       if(camSeqState == CAMSEQ_STOP) {
01189          updateJPEG_wp();
01190          add_frame_params();
01191          camSeqState = CAMSEQ_JPEG;
01192          imageParamsR[P_CAMSEQSTATE]=CAMSEQ_JPEG;
01193          JPEG_nfr = 0; // so it will not acquire any more frames
01194          compressorSingle();
01195 //         imageParamsR[P_FRAME]++;
01196          EN_INTERRUPT(nint_done_compress);
01197       } else { 
01198          if(camSeqState == CAMSEQ_JPEG) { 
01199             if(X313_SR(DONE_CMPRS)) { // it is status, not IRQ register . SO it works even after DIS_INTERRUPTS (reset by writing to command register)
01200                updateJPEG_wp();
01201                add_frame_params();
01202                if(JPEG_nfr > 0) 
01203                   JPEG_nfr--;
01204                 compressorStop(); 
01205                // will continue at frame sync interrupt to prevent false start (trying to compress the current frame)
01206                // See if it was not rereading from memory:
01207                if (X313_CHN0_BOUND) {  // was a bug - always started interrupts, even after rereading
01208 //                  imageParamsR[P_FRAME]++;
01209                   EN_INTERRUPT(nint_vact); // no IRQ if it was rereading
01210                }
01211             } else {
01212 
01213                advance_imageParamsR();
01214                JPEG_len = JPEG_wp - JPEG_rp;
01215                if(JPEG_len < 0)
01216                   JPEG_len += CCAM_DMA_SIZE;
01218                if(((camSeqCount--) <= 0) && (JPEG_nfr > 0) && (JPEG_len< JPEG_lfr)) {
01219                   X313_POSTINIT_SDCHAN(2,(jpeg_sdram_ctl0 | 0x2000));   //read, depend, mode=1 (tiles)
01220                   compressorSingle();
01221                   EN_INTERRUPT(nint_done_compress);
01222                } else { // just skip next frame
01223                   compressorStop();  
01224                   EN_INTERRUPT(nint_vact);
01225                }
01226             } // X313_SR(DONE_CMPRS)  - else
01227          } else {
01228             advance_imageParamsR();
01229             if(camSeqState == CAMSEQ_WAIT_F) {
01230                camSeqState = CAMSEQ_DONE;
01231               imageParamsR[P_CAMSEQSTATE]=CAMSEQ_DONE;
01232             } else { 
01233                if((camSeqCount--) <= 0) {
01234                   startAcquire();
01235                } else {
01236                   EN_INTERRUPT(nint_vact);      // re-enable end of frame interrupt
01237                }
01238             }
01239          }
01240       }
01241    }
01242    return IRQ_HANDLED;
01243 }
01244 
01245 static int getCamSeqCount(void) {return camSeqCount;}
01246 static void setCamSeqState(int v) {camSeqState=v;
01247                                    imageParamsR[P_CAMSEQSTATE]=v;
01248                                    imageParamsR[P_CAMSEQCOUNT]=0;
01249 MD (printk ("camSeqState=0x%x\n",v));}
01250 
01251 
01252 static void setCamSeqCount(int v) {camSeqCount=v;
01253                                    imageParamsR[P_CAMSEQCOUNT]=v;
01254 }
01255 
01256 
01257 static  void initCamIRQs(void){ // most moved outside - before FPGA loaded (only once!)
01258     reg_intr_vect_rw_mask intr_mask;
01259     DIS_INTERRUPTS;
01260     setCamSeqState(CAMSEQ_OFF);
01261     camSeqStop();
01262     resetPointers();
01263       JPEG_nfr=0;
01264       JPEG_lfr=0;
01265 
01266 //      *R_IRQ_MASK0_SET = 0x10;        //1 << irq_int_vector_nr
01267     intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
01268     intr_mask.ext = 1;
01269     REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); 
01270 
01271         printk ("Camera interrupts enabled\n");
01272 //      *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, irq_int_vector_nr, set);
01273 }
01274 
01275 static int getCamSeqState(void) {
01276     int res=-1;
01277     unsigned long flags;
01278     if (camSeqState==CAMSEQ_WAIT_F) {
01279       local_irq_save(flags);
01280       if (X313_SR(SENST1)) res=X313_SR(SENST0)?CAMSEQ_ACQUIRE:CAMSEQ_WAIT_T;
01281       else if (X313_SR(SENST0)) res=CAMSEQ_WAIT_F;
01282       else res= ((camSeqState=CAMSEQ_READY));
01283       local_irq_restore(flags);
01284 
01285       return res;
01286     }
01287     return      camSeqState;
01288 }
01289 
01290 
01291 static int camSeqStart(void) { 
01292   int i;
01293   if (((i=getCamSeqState()) != CAMSEQ_READY) && (i!=CAMSEQ_DONE)) {
01294    printk("camSeqStart error - CamSeqState was %d\n",i);
01295    return -1;    // error
01296   }
01297 MD1(printk("camSeqStart:getCamSeqCount()=%x\n",getCamSeqCount())); 
01298   if (getCamSeqCount()) {
01299 
01300     setCamSeqState(CAMSEQ_SKIP);
01301     EN_INTERRUPT(nint_vact);
01302   } else {startAcquire();} 
01303   return 0; // OK
01304 }
01305 
01306 static void camSeq_dump (void) {
01307   printk ("    camSeqCount=  %x\n",camSeqCount);
01308   printk ("    camSeqState=  %x\n",camSeqState);
01309   printk ("    JPEG_wp=      %x\n",JPEG_wp);
01310   printk ("    JPEG_rp=      %x\n",JPEG_rp);
01311   printk ("    JPEG_len=     %x\n",JPEG_len);
01312   printk ("    DMA_buf_start=%lx\n",DMA_buf_start);
01313   printk ("    JPEG_nfr=     %x, (%d)\n",JPEG_nfr,JPEG_nfr);
01314   printk ("    JPEG_lfr=     %x\n",JPEG_lfr);
01315   printk ("    0x20 was=     %x\n",dbg_20);
01316   printk ("    0x28 was=     %x\n",dbg_28);
01317   printk("\n");
01318 }
01319 
01320 
01321 
01322 /*
01323  * Functions used in other files (implementation)
01324  */
01325 
01326 
01327 
01328 
01329 /*
01330 len <0, nfr>0 - acquire nfr frames, no length restrictions
01331 len =0, nfr>0 - acquire nfr frames, unchanged length restriction
01332 len >0, nfr>0 - acquire nfr frames, set new length restriction
01333 len >0, nfr <0 - acquire unlimited number of frames, only total length restriction
01334 len >0, nfr =0 - do not change number of frames to acquire, update total length restriction
01335 len =0, nfr =0 - reread from memory (if was off).
01336 */
01337 int  camSeqGetJPEG_wp(void) {return JPEG_wp;}
01338 int  camSeqGetJPEG_rp(void) {return JPEG_rp;}
01339 void camSeqSetJPEG_rp(int p) {
01340                               JPEG_rp=p;
01341                               imageParamsR[P_CIRCBUFRP] = p<< 2;
01342                               imageParamsR[P_FREECIRCBUF] =
01343                                     ((imageParamsR[P_CIRCBUFRP] < imageParamsR[P_CIRCBUFWP])?
01344                                      imageParamsR[P_CIRCBUFSIZE]:0)+ 
01345                                      imageParamsR[P_CIRCBUFRP] - imageParamsR[P_CIRCBUFWP];
01346                                }
01358 
01359 
01360 int camSeqStartClip(int nfr, int len) { // will start/continue acquisition of a clip to memory (-1 - unlimited)
01361     unsigned long flags;
01362     int res=-1;
01363     MD1(printk("camSeqStartClip nfr=%d, len=%d, getCamSeqState()=%d \n", nfr, len, getCamSeqState()));
01364     MD7(printk("camSeqStartClip nfr=%d, len=%d, getCamSeqState()=%d \n", nfr, len, getCamSeqState()));
01365 
01366     if (((res=getCamSeqState()) != CAMSEQ_READY) && (res!=CAMSEQ_DONE) && (res!=CAMSEQ_JPEG) && (res!=CAMSEQ_RUN)) {
01367       printk("camSeqStartClip error - CamSeqState was %d\n",res);
01368       return -1;    // error
01369     }
01370    MD7(printk("camSeqStartClip nfr=%d, len=%d, getCamSeqState()=%d \n", nfr, len, res));
01371     if ((res==CAMSEQ_RUN)) {  // only "stop constant compression" is allowed
01372       if ((nfr<0) && (len ==0)){ // will work with both nfr == -1 (stop/acquire) and nfr =-2 (stop only)
01373         setCamSeqState(CAMSEQ_STOP);
01374         return 0;
01375       } else {
01376         printk("camSeqStartClip error - CamSeqState was %d\n",res);
01377         return -1;    // error
01378       }  
01379     }
01380     if ((nfr<0) && (len ==0)){ 
01381 //        printk("camSeqStartClip error - tried to stop but CamSeqState was %d\n",res);
01382 //        return -1;    // error
01383       if (nfr<-1) return 0; // just exit (do nothing if was not running) - don't restart
01384       JPEG_wp=0; 
01385       imageParamsR[P_JPEG_WP]=JPEG_wp;
01386       imageParamsR[P_CIRCBUFWP]= JPEG_wp<<2;
01387       imageParamsR[P_FREECIRCBUF] = imageParamsR[P_CIRCBUFRP];
01388 
01389 //      imageParamsR[P_FRAME]=0;
01390       JPEG_rp=-1; 
01391       imageParamsR[P_FREECIRCBUF] = 0xffffffff;
01392 
01393       JPEG_len=0;   // current length in buffer;
01394       x313_dma_reset_chain();
01395       x313_dma_start();
01396       setCamSeqState(CAMSEQ_SINGLE);
01397 //      port_csp0_addr[X313_WA_SD_MODE]= (port_csp0_addr[X313_WA_SD_MODE] & 0x2f); //disable SDRAM channel 2
01398       X313_CHN_DIS(2); //disable SDRAM channel 2
01399       setCamSeqCount(imageParamsR[P_SKIP_FRAMES]); // skip couple frames ****************** Not for CCD
01400       X313_ACQUIRE_ON;  // start constant-on acquisition mode
01401       EN_INTERRUPT(nint_vact);
01402       return 0;
01403     }
01404     if ((nfr==0) && (len == -1)) { 
01405       if (res==CAMSEQ_JPEG) { 
01406         MD1(printk("Restarting RUN\n"));
01407         setCamSeqState(CAMSEQ_RUN);
01408         setCamSeqCount(0); // next IRQ will start
01409         return 0;
01410       } else {
01411         MD1(printk("Starting RUN\n"));
01412         resetPointers();
01413         x313_dma_reset_chain(); 
01414         x313_dma_start();
01415         setCamSeqState(CAMSEQ_RUN);
01416 
01417 
01418         if (IS_KAI11000) {
01419 MD7(printk("camSeqStartClip - using KAI-11002"));
01420            setCamSeqCount(imageParamsR[P_SKIP_FRAMES]); // Not for CCD
01421            X313_ACQUIRE_ON;
01422 //           writeSensorReg16(0x14, 0, 1); // start CCD here
01424            X313_POSTINIT_SDCHAN(2,(jpeg_sdram_ctl0 | 0x2000));   //read, depend, mode=1 (tiles)
01425            compressorRun();
01426            camSeqCount--;
01427            EN_INTERRUPT(nint_done_compress);
01428         } else {
01429            X313_CHN_DIS(2); //disable SDRAM channel 2
01430            setCamSeqCount(imageParamsR[P_SKIP_FRAMES]); // (do not) skip couple frames wait for the first Vsync, then program compressor (1-st will still be wasted)
01431            X313_ACQUIRE_ON;  // start constant-on acquisition mode
01432            EN_INTERRUPT(nint_vact);
01433         }
01434         return 0;
01435       }
01436     }
01437 MD7(printk("camSeqStartClip(0x%x, 0x%x), state=%d\n",nfr,len,res));
01438     if (res==CAMSEQ_JPEG) { 
01439       MD1(printk("Restarting SINGLE\n"));
01440       local_irq_save(flags);
01441       if (nfr<0) JPEG_nfr=0x7fffffff;
01442       else JPEG_nfr+=nfr;
01443       if (len<0) JPEG_lfr=0x7fffffff;
01444       else if (len>0) JPEG_lfr=len; // len ==0 -> no change
01445 
01446       local_irq_restore(flags);
01447       return 0;
01448     }  else { // need to start DMA
01449       MD1(printk("Starting SINGLE\n"));
01450       resetPointers();
01451       x313_dma_reset_chain();
01452       x313_dma_start();
01453       setCamSeqState(CAMSEQ_JPEG);
01454 //      port_csp0_addr[X313_WA_SD_MODE]= (port_csp0_addr[X313_WA_SD_MODE] & 0x2f); //disable SDRAM channel 2
01455       X313_CHN_DIS(2); //disable SDRAM channel 2
01456 
01457       if ((len!=0) || (nfr !=0)) {
01458          if (nfr<0) JPEG_nfr=0x7fffffff;
01459          else JPEG_nfr+=nfr;
01460          if (len<0) JPEG_lfr=0x7fffffff;
01461          else if (len>0) JPEG_lfr=len; // len ==0 -> no change
01462          if (IS_KAI11000) {
01463 MD7(printk("camSeqStartClip - using KAI-11002"));
01464            setCamSeqCount(imageParamsR[P_SKIP_FRAMES]); // Not for CCD
01465 //           X313_ACQUIRE_ONCE?
01466            X313_ACQUIRE_ON;
01467            writeSensorReg16(0x14, 0, 1); // start CCD here
01469            X313_POSTINIT_SDCHAN(2,(jpeg_sdram_ctl0 | 0x2000));   //read, depend, mode=1 (tiles)
01470            compressorRun();
01471 //           compressorSingle(); //! or just single?
01472            camSeqCount--;
01473            EN_INTERRUPT(nint_done_compress);
01474          } else {
01475 // How many frames to skip after parameter change?
01476 //         setCamSeqCount(2); // skip couple frames ****************** Not for CCD
01477          setCamSeqCount(imageParamsR[P_SKIP_FRAMES]); // skip couple frames ****************** Not for CCD
01478          X313_ACQUIRE_ON;  // start constant-on acquisition mode
01479          EN_INTERRUPT(nint_vact);
01480         }
01481       } else { 
01482 // do similar to what is done inside IRQ service, but unconditionally once
01483          JPEG_nfr=1;
01484          JPEG_lfr=0x7fffffff;
01485 
01486          JPEG_len= JPEG_wp-JPEG_rp;
01487          if (JPEG_len<0) JPEG_len+=CCAM_DMA_SIZE;
01488             X313_POSTINIT_SDCHAN(2,jpeg_sdram_ctl0);   //do not wait (depend=0)
01489 // start compressor (Should be started after SDRAM channel programmed)
01490          compressorSingle();
01491          EN_INTERRUPT(nint_done_compress);
01492       }
01493     }
01494     return 0;
01495 }
01496 
01497 //static void camSeqStop(void) {  // Add shutting down DMA/compressor?
01499 
01500 #define OLD_CAMSEQSTOP 0 
01501 
01502 
01503 
01504 
01505 
01506 void camSeqStop(void) {  // Add shutting down DMA/compressor?
01507 //  unsigned long flags;
01508   MD1(printk("camSeqStop:getCamSeqState()=0x%x, imageParamsR[P_COMPRESSOR_CMD]=0x%x\n",getCamSeqState(), (int) imageParamsR[P_COMPRESSOR_CMD])); 
01509   MD12(printk ("camSeqStop: state=%d rp=0x%x, wp=0x%x\r\n", getCamSeqState(), JPEG_rp, JPEG_wp ));
01510   MD11(printk ("camSeqStop: state=%d rp=0x%x, wp=0x%x\r\n", getCamSeqState(), JPEG_rp, JPEG_wp ));
01511   DIS_INTERRUPTS;
01512   X313_ACQUIRE_STOP ;
01514 //  local_irq_save(flags);
01515   if (imageParamsR[P_COMPRESSOR_CMD]) { // yes, it was runnning
01517     compressorStop(); // will immediately stop DMA operations
01518   }
01519 //  local_irq_restore(flags);
01520 
01521 //
01522 #if OLD_CAMSEQSTOP
01524   if (getCamSeqState()>=CAMSEQ_JPEG) { // stop acquisition
01525     x313_dma_stop(); // will stop DMA and prepare data for reading out (?)
01526     setCamSeqState(CAMSEQ_READY);
01527   } else { 
01528 
01529       JPEG_wp=0;
01530       imageParamsR[P_JPEG_WP]=JPEG_wp;
01531       imageParamsR[P_CIRCBUFWP]= JPEG_wp<<2;
01532       imageParamsR[P_FREECIRCBUF] = imageParamsR[P_CIRCBUFRP];
01533 //      imageParamsR[P_FRAME]=0;
01534       JPEG_rp=0;
01535       imageParamsR[P_FREECIRCBUF] = 0;
01536       JPEG_len=0;   // current length in buffer;
01537       JPEG_nfr=0;
01538       JPEG_lfr=0;
01539       x313_dma_reset_chain();
01540   }
01541 #endif
01542   setCamSeqCount(0);
01543 
01544   if (getCamSeqState()!=CAMSEQ_OFF) setCamSeqState(CAMSEQ_READY);
01545   MD11(printk ("camSeqStop-exit: state=%d rp=0x%x, wp=0x%x\r\n", getCamSeqState(), JPEG_rp, JPEG_wp ));
01546 }
01547 
01548 
01549 int           get_sensor_i2c_regs16(int n) {return (((int) (sensor_i2c_regs[n<<1]))<<8)+sensor_i2c_regs[(n<<1)+1] ;}
01550 unsigned char get_sensor_i2c_regs  (int n) {return sensor_i2c_regs[n] ;}
01551 unsigned long get_imageParamsR     (int n) {return imageParamsR[n];}
01552 unsigned long get_imageParamsW     (int n) {return imageParamsW[n];}
01553 unsigned char get_sensor_i2c_addr  (void) {return sensor_i2c_addr ;}
01554 void          set_sensor_i2c_regs  (int n, unsigned char d) {sensor_i2c_regs[n]=d;}
01555 void          set_imageParamsR     (int n, unsigned long d) {imageParamsR[n]=d;}
01556 void          set_imageParamsW     (int n, unsigned long d) {imageParamsW[n]=d;}
01557 void          set_sensor_i2c_addr  (       unsigned char d) {sensor_i2c_addr=d;}
01558 
01559 
01560 
01561 void ccamCRAnd(unsigned long d) {
01562         unsigned long flags;
01563    local_irq_save(flags);
01564         port_csp0_addr[X313_WA_WCTL]= (ccam_cr_shadow &= d);
01565         local_irq_restore(flags);
01566 }
01567 
01568 void ccamCROr(unsigned long d) {
01569         unsigned long flags;
01570    local_irq_save(flags);
01571         port_csp0_addr[X313_WA_WCTL]= (ccam_cr_shadow |= d);
01572         local_irq_restore(flags);
01573 }
01574 
01575 void ccamCRXor(unsigned long d) {
01576         unsigned long flags;
01577    local_irq_save(flags);
01578         port_csp0_addr[X313_WA_WCTL]= (ccam_cr_shadow ^= d);
01579         local_irq_restore(flags);
01580 }
01581 
01582 
01583 void ccamCRAndOr(unsigned long d_and, unsigned long d_or) {
01584         unsigned long flags;
01585    local_irq_save(flags);
01586         ccam_cr_shadow &= d_and;
01587         port_csp0_addr[X313_WA_WCTL]= (ccam_cr_shadow |= d_or);
01588         local_irq_restore(flags);
01589 }
01590 
01591 unsigned long ccamGetCR(void) {return ccam_cr_shadow;}
01592 
01593 void writeSensorDefaults(unsigned long * data, int count) {
01594  int i;
01595 MD7 (printk ("writing sensor defaults to imageParamsW[] (needs update to copy to imageParamsR[]), count=%d (decimal)\r\n",count));
01596  for (i=0;i<count;i++) {
01597    imageParamsW[data[2*i]]=data[2*i+1];
01598    MD7 (printk ("%ld(0x%lx): %ld(0x%lx)\r\n",data[2*i],data[2*i],data[2*i+1],data[2*i+1]));
01599 
01600  }
01601  imageParamsR[P_PARS_CHANGED]=1;
01602 }
01603 
01604 
01605 // readSensorReg and writeSensorReg hacked to accomodate KAC5000 "hidden" registers - the same address can point to multiple registers,
01606 // such as color gains. Now ra will be unsigned int, if > 255 the high word will point to shadow array index (up to 511),
01607 // else - array index is the same as ra
01608 int readSensorReg(unsigned int ra, int mode) { //  mode=0 - shadow, 1 - actual register
01609   int i;
01610   unsigned long flags;
01611   int i1=0;
01612   unsigned char rab=ra & 0xff;
01613   int rindx= (ra>>16) & 0x1ff; if (!rindx) rindx=rab;
01614   if(mode) {
01615 MD7 (printk ("ra= 0x%x, rab=0x%x, shadow was =0x%x - ",ra, (int) rab, (int)sensor_i2c_regs[rindx]));
01616     local_irq_save(flags);
01617     X3X3_I2C_STOP_WAIT ; // stop hardware i2c , wait !busy (guaranteed by hardware to finish)
01618     i= i2c_writeData(0, sensor_i2c_addr & 0xfe, &rab, 1, 0); // no stop
01619     if (!i) i1= i2c_readData(0, sensor_i2c_addr | 0x01, &sensor_i2c_regs[rindx],  1, 0); //restart, not strart
01620     X3X3_I2C_RUN ; // let it continue (should be initialized)
01621     local_irq_restore(flags);
01622     if (i1) return -i1-1000; //error
01623     if (i)  return -i;       //error
01624   }
01625 MD7 (printk (" new x%x\r\n",(int)sensor_i2c_regs[rindx]));
01626 
01627   return (int)sensor_i2c_regs[rindx];
01628 }
01629 
01630 int writeSensorReg(unsigned int ra, unsigned char rd, int uncond) { // returns -1 (error) , 1 - set, 0 - did not have to change
01631    int i, res;
01632    unsigned long flags;
01633    unsigned char rab=ra & 0xff;
01634    int rindx= (ra>>16) & 0x1ff; if (!rindx) rindx=rab;
01635    unsigned char d[2];
01636 
01637    if (!uncond && (sensor_i2c_regs[rindx] == rd)) {
01638           MD8(printk("writeSensorReg(0x%x,0x%x) did not do anything\n",(int) ra,(int) rd)); 
01639           return 0;
01640 
01641         }  
01642    d[0]=rab;
01643    d[1]=rd;
01644    local_irq_save(flags);
01645    X3X3_I2C_STOP_WAIT ; // stop hardware i2c , wait !busy (guaranteed by hardware to finish)
01646    i=i2c_writeData(0, sensor_i2c_addr, &d[0], 2, 1 ); //send stop
01647    X3X3_I2C_RUN ; // let it continue (should be initialized)
01648    local_irq_restore(flags);
01649    if (i) {
01650       i=d[0]; res=d[1];
01651       printk ("\tError writing I2C register %2x with data %2x\r\n",i,res);
01652       return -1;
01653    }
01654         MD8(printk("writeSensorReg(0x%x,0x%x) wrote to sensor (shadow was 0x%x)\r\n",(int) ra,(int) rd, (int) sensor_i2c_regs[rindx])); 
01655    sensor_i2c_regs[rindx] = rd;
01656         return 1;
01657 }
01658 
01659 // 16-bit access for Micron sensor (MT9X001) 16-bit registers
01660 // For shadows use a pair of unsigned char elements (MSB first)
01661 int readSensorReg16(unsigned char ra, int mode) { //  mode=0 - shadow, 1 - actual register
01662   int i,a;
01663   int i1=0;
01664   a=ra;
01665   unsigned long flags;
01666   if(mode) {
01667 MD8 (printk ("ra= 0x%x, shadow was =0x%x - ",(int) ra, get_sensor_i2c_regs16(ra)));
01668     local_irq_save(flags);
01669     X3X3_I2C_STOP_WAIT ; // stop hardware i2c , wait !busy (guaranteed by hardware to finish)
01670     i=          i2c_writeData(0, sensor_i2c_addr & 0xfe, &ra, 1, 0); //no stop
01671     if (!i) i1= i2c_readData(0, sensor_i2c_addr | 0x01, &sensor_i2c_regs[a<<1],  2, 0); //restart, not strart
01672     X3X3_I2C_RUN ; // let it continue (should be initialized)
01673     local_irq_restore(flags);
01674     if (i1) return -i1-1000; //error
01675     if (i)  return -i;       //error
01676   }
01677 MD8 (printk (" new 0x%x\r\n",get_sensor_i2c_regs16(ra)));
01678   return get_sensor_i2c_regs16(ra);
01679 }
01680 
01681 int writeSensorReg16(unsigned char ra, int rd, int uncond) { // returns -1 (error) , 1 - set, 0 - did not have to change
01682   int res, a;
01683   unsigned char d[3];
01684 #ifndef USE_HARDWARE_I2C
01685   unsigned long flags;
01686 #endif
01687   a=ra;
01688   d[0]=ra;
01689   d[1]=(rd>>8) & 0xff;
01690   d[2]= rd     & 0xff;
01691   if (!uncond && (sensor_i2c_regs[(a<<1)] == d[1]) && (sensor_i2c_regs[(a<<1)+1] == d[2]))  return 0;
01692 #ifdef USE_HARDWARE_I2C
01693 //  X313_I2C_ASAP
01694 //  #define X3X3_I2C_SEND2(a,s,r,d) {port_csp0_addr[a] = (s<<24) | ((r & 0xff) << 16) | ((d & 0xff) << 8) | ((d >>8) &  0xff)}
01695   X3X3_I2C_SEND2(X313_I2C_ASAP, sensor_i2c_addr, a, rd);
01696   res=0;
01697 #else
01698   local_irq_save(flags); 
01699   X3X3_I2C_STOP_WAIT ; // stop hardware i2c , wait !busy (guaranteed by hardware to finish)
01700   res=i2c_writeData(0, sensor_i2c_addr, &d[0], 3, 1); //send stop
01701   X3X3_I2C_RUN ; // let it continue (should be initialized)
01702   local_irq_restore(flags);
01703 #endif
01704   if (res) {
01705     printk ("\tError (%x) writing 16-bit I2C register %2x with data %4x, dev_addr=%2x\r\n",res,a,((int) d[1]<<8)+ (int) d[2],sensor_i2c_addr);
01706     return -1;
01707   }
01708   MD8(printk("writeSensorReg(0x%x,0x%x) wrote to sensor (shadow was 0x%x)\r\n",(int) ra,(int) rd,get_sensor_i2c_regs16(a)));
01709   sensor_i2c_regs[(a<<1)  ] = d[1];
01710   sensor_i2c_regs[(a<<1)+1] = d[2];
01711   return 1;
01712 }
01713 // 12-bit access for FillFactory sensor (IBIS5) 12-bit registers
01714 // For shadows use a pair of unsigned char elements (MSB first)
01715 
01716 int writeSensorRegFF(unsigned char ra, int rd, int uncond) { // returns -1 (error) , 1 - set, 0 - did not have to change
01717   int res, a;
01718   unsigned char d[3];
01719   unsigned long flags;
01720 
01721   a=ra;
01722   d[0]=((ra & 0x0f) << 4) | ((rd >> 8) & 0x0f);
01723   d[1]= rd     & 0xff;
01724 //  printk("writeSensorRegFF(0x%x,0x%x)\n",(int) ra,(int) rd);
01725   if (!uncond && (sensor_i2c_regs[(a<<1)] == (d[0] & 0xf)) && (sensor_i2c_regs[(a<<1)+1] == d[1])) {
01726           MD(printk("writeSensorRegFF(0x%x,0x%x) did not do anything\r\n",(int) ra,(int) rd));
01727 // printk("writeSensorRegFF(0x%x,0x%x) did not do anything\n",(int) ra,(int) rd);
01728 
01729 // write to FPGA number of lines in a frame - already done in main driver 
01730 //          if (a==P_IBIS5_NROF_LINES) {
01731 
01732 //            port_csp0_addr[X313_WA_NLINES]= rd;
01733 //          }
01734 
01735           return 0;
01736   }
01737 //  printk ("++++++++ccam_cr_shadow= %x\n", (int) ccam_cr_shadow);
01738 
01739   local_irq_save(flags); 
01740   X3X3_I2C_STOP_WAIT ; // stop hardware i2c , wait !busy (guaranteed by hardware to finish)
01741 
01742   if ((res=i2c_writeData(0, sensor_i2c_addr, &d[0], 2, 1))) { //send stop
01743     printk ("\tError (%x) writing 16-bit I2C register %2x with data %4x\r\n",res,a,((int) d[1]<<8)+ (int) d[2]);
01744     return -1;
01745   }
01746   X3X3_I2C_RUN ; // let it continue (should be initialized)
01747   local_irq_restore(flags);
01748 
01749   MD(printk("writeSensorReg(0x%x,0x%x) wrote to sensor (shadow was 0x%x)\r\n",(int) ra,(int) rd, ((int)sensor_i2c_regs[a<<1])<<8 +((int)sensor_i2c_regs[(a<<1)+1])));
01750   sensor_i2c_regs[(a<<1)  ] = (d[0] & 0x0f);
01751   sensor_i2c_regs[(a<<1)+1] = d[1];
01752   return 1;
01753 }
01754 
01755 
01756 
01757 static int __init 
01758 cmoscam_init(void) {
01759    int res;
01760    ccam_cr_shadow=0;
01761    init_ccam_dma_buf_ptr();
01762    init_autoexp_struct();
01763    sensor_i2c_regs = (char*) sensor_i2c_regs16;
01764 
01765    res = register_chrdev(CMOSCAM_MAJOR, cmoscam_name, &cmoscam_fops);
01766    if(res < 0) {
01767      printk(KERN_ERR "ccam: couldn't get a major number.\n");
01768      return res;
01769    }
01770    if(request_irq(EXT_INTR_VECT,
01771                   camSeq_interrupt,
01772                   SA_INTERRUPT, // SA_SHIRQ | SA_INTERRUPT if it is a shared one.
01773                   "Elphel FPGA interrupts",
01774                   NULL)) {
01775                printk(KERN_ERR "Can't allocate Elphel FPGA interrupts");
01776                return -EBUSY;
01777     }
01778     printk("CMOS/MCP camera interrupts initialized\n");
01779     init_waitqueue_head(&x313_wait_queue);
01780     DMA_buf_start=x313_dma_init();
01781     printk(CMOSCAM_DRIVER_NAME);
01782     return 0;
01783 }
01784 
01785 
01786 static int init_FPGA(void) { //will check FPGA version, init SDRAM (if needed) and sensor
01787   int i;
01788   int f1,f2;
01789    // Should be initial
01790   if ((i=port_csp0_addr[X313__RA__MODEL]) < X313_MINMODREV) {
01791    printk ("too old fpga rev - found %x, software wants >= %x\n",i,X313_MINMODREV);
01792    return -1;   // too old FPGA
01793   } 
01794   if (i > X313_MAXMODREV) {
01795      printk ("too new fpga rev - found %x, software wants <= %x\n",i,X313_MAXMODREV);
01796      return -1;    // too new FPGA
01797   }
01798 //  D5(printk("(27)=%x, ccam_cr_shadow=%x\r\n",(int)port_csp0_addr[X313_WA_SD_MODE], (int)ccam_cr_shadow));
01799 //  if ((port_csp0_addr[X313_WA_SD_MODE] & 3)!=3) fpga_initSDRAM();
01800   if (!X313_IS_SDRAM_ON)  fpga_initSDRAM();
01801 // Was sensor initialized? (What if SDRAM was initialized by some application?)
01802 //  D5(printk("port_csp0_addr[X313_WA_SDCH0_CTL1]=%x, port_csp0_addr[X313_WA_SDCH0_CTL2]=%x\r\n",(int)port_csp0_addr[X313_WA_SDCH0_CTL1],(int)port_csp0_addr[X313_WA_SDCH0_CTL2]));
01803 //  if ((port_csp0_addr[X313_WA_SDCH0_CTL1]& 0xffff) !=0) return 0; // channel 0 was programmed (will set dummy bit 15) - model 333
01804 //  if ((port_csp0_addr[X313_WA_SDCH0_CTL2]& 0xffff) !=0) return 0; // channel 0 was programmed (will set dummy bit 15) - model 313
01805   if (X313_CHN0_USED!=0) return 0;
01806   D5(printk ("FPGA/Sensor need initialization. Wait 1 sec for troubleshooting\n");    udelay (1000000));
01807 
01808 //  imageParamsR[P_CLK_SENSOR]=20000000; setClockFreq(1, imageParamsR[P_CLK_SENSOR]);
01809 //  imageParamsR[P_CLK_FPGA]=120000000;  setClockFreq(0, imageParamsR[P_CLK_FPGA]);
01810 //#define       X313__DCLKMODE__WIDTH            1
01811 
01812   f1=imageParamsR[P_CLK_SENSOR]=20000000; setClockFreq(1, imageParamsR[P_CLK_SENSOR]); X3X3_RSTSENSDCM;
01813 
01814 //  f2=imageParamsR[P_CLK_FPGA]=120000000;  setClockFreq(0, imageParamsR[P_CLK_FPGA]);
01815   f2=imageParamsR[P_CLK_FPGA]=getClockFreq(0); // will not change clocks here - it needs restarting FPGA DCM in Spartan 3E
01816   D5(printk("clock1=%d,clck0=%d\r\n",f1,f2));
01817   
01818 // needs phase adjustment too ! *****************************************************************8         
01819   
01820   udelay (50000);// 0.05 sec to stabilize clocks
01821   fpga_initSDRAM(); // force reinitializing SDRAM after clock change
01822   D5(printk ("------init_FPGA\n"));
01823   init_sensor();
01824   D5(printk ("init_sensor() finished\n"));
01825   udelay (1000000); // TODO: remnove this or move to condition (above)
01826 
01827 // Init MCP here
01828 #ifdef CONFIG_ETRAX_ELPHEL_MCP
01829         if (MCP_initmodule()== 0) printk ("MCP module initialized\r\n");
01830         else                      printk ("no MCP module detected\r\n");
01831 #endif
01832 
01833   printk("FPGA rev %x\n", (unsigned int) port_csp0_addr[X313__RA__MODEL]);
01834   x313_tables_gammainitlinear();
01835   printk("Programmed linear intensity table (gamma=1.0)\n");
01836 
01837 // printk ("Will init IRQs after 1 sec delay...\n");    udelay (1000000);
01838 
01839 
01840 
01841   initCamIRQs();
01842 //printk ("initCamIRQs() Done, waiting 1 sec...\n");    udelay (1000000);
01843 
01844 
01845   return 1;
01846 
01847 }
01848 
01849 struct sensor_t kai11002={
01850 // sensor constants
01851    .imageWidth  = 4008,    //nominal image width for final images
01852    .imageHeight = 2672,    //nominal image height for final images
01853    .clearWidth  = 4032,    //maximal clear image width
01854    .clearHeight = 2688,    //maximal clear image height;
01855    .clearTop    = 16,       //top margin to the first clear pixel
01856    .clearLeft   = 20,      //left margin to the first clear pixel
01857    .arrayWidth  = 4072,    //total image array width (including black and boundary)
01858    .arrayHeight = 2720,    //total image array height (including black and boundary)
01859    .minWidth    = 4,       // minimal WOI width
01860    .minHeight   = 3,       // minimal WOI height
01861    .minHorBlank = 999,     // minimal horizontal blanking, in pixels in no-decimation, no-binning mode.
01862    .minLineDur  = 999,     // minimal total line duration, in pixels in no-decimation, no-binning mode.
01863    .maxHorBlank = 9999,    // maximal horizontal blanking/Virtual frame width (depends on sensor type)
01864    .minVertBlank= 99,      // minimal vertical blanking
01865    .maxVertBlank= 9999,    // maximal vertical blanking/Virtual frame height (depends on sensor type)
01866    .maxShutter  = 0x3fff,  // Maximal shutter duration (in lines)
01867    .flips       = 3,       // bit mask bit 0 - flipX, 1 - flipY
01868    .dcmHor      = 0x1,    // 1,2,4,8
01869    .dcmVert     = 0x1,    // 1,2,4,8
01870    .binHor      = 0x1,    // 1
01871    .binVert     = 0x1,    // 1
01872    .maxGain256  = 4032,    // (15.75) maximal analog gain times 0x100
01873    .maxClockFreq= 48000000, // Maximal clock frequency
01874    .nomClockFreq= 48000000, //nominal clock frequency
01875    .sensorType  = SENSOR_KAI11000,     // sensor type (for Elphel cameras)
01876    .i2c_addr    = 0x10,
01877    .i2c_period  = 2500,     // SCL period in ns, (standard i2c - 2500)
01878    .i2c_bytes   = 2,        // number of bytes/ register
01879    .margins     = 0,        // actually - property of FPGA code, not the sensor. Will be set in common sensor code
01880 // dynamic variables
01881    .pixelWidth  = 0,       // number of the pixels output in a line (including margins, decimation)
01882    .pixelHeight = 0        // number of the lines output in a frame (including margins, decimation)
01883 };
01884 
01885 int init_sensor(void) {
01886  int i;
01887 // currently relies on the init script (/etc/init.d/fpga) to set 14-bit mode bit in control register. It will be used to branch to 10347/10342 here.
01888 // edit initscript for 10359 board that will be detected as if 10347 - later we'll add JTAG reading of the FPGA pins to distinguish between 10347 and 10359
01889    MD10(dumpFrameParams(&frame_params,"\nframe parameters before init_sensor:"));
01891    program_i2c();
01892    X3X3_I2C_RESET_WAIT ;
01893 
01894   if (IS_KAI11000) {
01895     printk("------------------ using KAI-11000 ---------------------- \n");
01896     // use KAI-11000
01897     memcpy(&sensor, &kai11002, sizeof(kai11002));
01898     imageParamsR[P_SENSOR_WIDTH]=sensor.imageWidth;
01899     imageParamsR[P_SENSOR_HEIGHT]=sensor.imageHeight;
01900     imageParamsW[P_WOI_WIDTH]=sensor.imageWidth; //needed?
01901     imageParamsW[P_WOI_HEIGHT]=sensor.imageHeight;//needed?
01902     imageParamsR[P_SENSOR]= sensor.sensorType;
01903     imageParamsW[P_CLK_SENSOR]=sensor.nomClockFreq;
01904     imageParamsR[P_VIDEO]=0;
01905     imageParamsW[P_VIDEO]=0;
01906     imageParamsW[P_SKIP_FRAMES]=imageParamsR[P_SKIP_FRAMES]=0;
01907     sensor.margins     =X313_MARGINS; 
01908     writeSensorDefaults(&default_common[0],sizeof(default_common)/sizeof(default_common[0])/2); // set common defaults
01909     MD7(printk ("sensorType=%ld,sensor.imageWidth=%ld,sensor.imageHeight=%ld\r\n", sensor.sensorType,sensor.imageWidth,sensor.imageHeight));
01910     set_sensor_i2c_addr(0x20); //10347 primary page i2c address
01911     imageParamsW[P_IRQ_SMART] &= 2; // disaable waiting for VACT after compressor_done
01912     program_smart_irq();
01913     X3X3_RSTSENSDCM;    // start generating pclk2x
01914     printk ("pclk2x DCM is reset\r\n");
01915     i=programSensor(0); 
01916     udelay (1000); // needs time for DCM?
01917     X3X3_I2C_RUN ;
01918     return i;
01919   }
01920 
01921 // moving here detection of MT9P001 - before programming DC-DC power that will need those pins as outputs (input for 12-bit sensors).
01922 // a problem (bus conflict) can happen if the sensor is not recognized and FPGA outputs are anabled.
01923  printk("removing MRST from the sensor, setting DMA burst size, setting MCLK to 20MHz\r\n");
01924 
01925       ccamCRAndOr(0,0x80000000);  // just clear control register
01926       PROGRAM_CLK_EN(1);
01927       udelay (100); // apply clock before removing MRST
01928 
01929 //printk ("Done, CCAM_MRST_OFF after 1 sec delay...\n");    udelay (1000000);
01930 
01931       CCAM_NEGRST;  //set negative MRST polarity
01932       CCAM_MRST_OFF;
01933       CCAM_ARST_OFF;
01934        writeSensorDefaults(&default_common[0],sizeof(default_common)/sizeof(default_common[0])/2); // set common defaults
01935       program_smart_irq();
01936 // printk ("Trying sensors - again after 1 sec delay...\n");    udelay (1000000);
01937     imageParamsR[P_SENSOR]=0;
01938     for (i=0;i<256;i++) sensor_i2c_regs[i]=0; // shadow registers
01939 
01940 #ifdef CONFIG_ETRAX_ELPHEL_MT9X001
01941  printk("trying MT9X001\r\n");
01942  if (imageParamsR[P_SENSOR]==0) init_mt9x001();  // try Micron 5.0 Mpixel
01943 #endif
01944 
01945 //for now - disable all but 5MPix
01946 #define ENABLE_OLD_SENSORS 1
01947 #ifdef ENABLE_OLD_SENSORS
01948  if (imageParamsR[P_SENSOR]==0) { // no - it is not MT9P001)
01949    CCAM_CNVEN_ON;
01950 // enable output for power converter signals
01951 
01952 // printk("removing MRST from the sensor, setting DMA burst size, setting MCLK to 20MHz\n");
01953 // This should be done first!!!
01954 // printk ("Will Turn DC power for the sensor after 1 sec delay...\n");  udelay (1000000);
01955 
01956 // turning on DC-DC converter may cause system to reboot because of a power spike, so start slow
01957         port_csp0_addr[X313_WA_DCDC] = 0x44;    // 48 - enough, 41 - ok - was 0x61;     //
01958         printk ("sensor power set low\r\n ");
01959         udelay (10000); // Wait voltage to come up (~10 ms)
01960         
01961           printk ("will set to 0x41\r\n");
01962   udelay (10000); // to find the problem
01963         port_csp0_addr[X313_WA_DCDC] = 0x41;    // 
01964           printk ("will set to 0x30\r\n");
01965   udelay (10000); // to find the problem
01966         port_csp0_addr[X313_WA_DCDC] = 0x30;    //
01967           printk ("will set to 0x28\r\n");
01968   udelay (10000); // to find the problem
01969         port_csp0_addr[X313_WA_DCDC] = 0x28;    //
01970           printk ("will set to 0x24\r\n");
01971   udelay (10000); // to find the problem
01972         port_csp0_addr[X313_WA_DCDC] = 0x24;    //
01973           printk ("will set to 0x22\r\n");
01974   udelay (10000); // to find the problem
01975         port_csp0_addr[X313_WA_DCDC] = 0x22;    //
01976 
01977   udelay (100000); // to find the problem
01978         port_csp0_addr[X313_WA_DCDC] = 0x10;    // now - full frequency (same as 0x21). Slow that down if the sensor clock is above 20MHz (i.e.0x22 for 40MHz)
01979         printk (".. full\r\n");
01980 
01981         udelay (10000); // Wait voltage to stabilize
01982         ccamCRAndOr(0,0x80000800);      // just clear control register and re-enble outputs for converter
01983       CCAM_CNVEN_ON; //just in case, better mnemonic
01984                 PROGRAM_CLK_EN(1);
01985                 udelay (100); // apply clock before removing MRST
01986 
01987     CCAM_POSRST;  //set positive MRST polarity (default)
01988       udelay (100); // apply clock before removing MRST
01989                 CCAM_MRST_OFF;
01990  }
01991 
01992 // writeSensorDefaults(&default_common[0],sizeof(default_common)/sizeof(default_common[0])/2); // set common defaults
01993 
01994 // printk ("Trying sensors - again after 1 sec delay...\n");    udelay (1000000);
01995 // imageParamsR[P_SENSOR]=0;
01996 // for (i=0;i<256;i++) sensor_i2c_regs[i]=0; // shadow registers
01997 
01998 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
01999  if (imageParamsR[P_SENSOR]==0) init_KAC1310();  // try KAC-1310
02000 #endif
02001 #ifdef CONFIG_ETRAX_ELPHEL_IBIS51300
02002  if (imageParamsR[P_SENSOR]==0) init_IBIS51300();  // try IBIS5-1300
02003 #endif
02004 /* invert MRST for other sensors */
02005 if (imageParamsR[P_SENSOR]==0) {
02006     CCAM_NEGRST;  //set negative MRST polarity
02007 printk ("Inverted MRST, ccam_cr_shadow= %x\n", (int) ccam_cr_shadow);
02008                 udelay (100);
02009     }    
02010 #ifdef CONFIG_ETRAX_ELPHEL_MT9X001
02011  printk("trying MT9X001\n");
02012  if (imageParamsR[P_SENSOR]==0) init_mt9x001();  // try Micron 1.3/2.0/3.0 Mpixel
02013 #endif
02014 
02015 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
02016  if (imageParamsR[P_SENSOR]==0) init_KAC5000();  // try KAC-5000
02017 #endif
02018 
02019 #ifdef CONFIG_ETRAX_ELPHEL_ZR32112
02020  if (imageParamsR[P_SENSOR]==0) init_ZR32112(); // try ZR32112
02021 #endif
02022 
02023 #ifdef CONFIG_ETRAX_ELPHEL_ZR32212
02024  if (imageParamsR[P_SENSOR]==0) init_ZR32212(); // try ZR32212
02025 #endif
02026 
02027 #endif // *************** temporary disabling other sensors ********************
02028 
02029  if (imageParamsR[P_SENSOR]==0) {
02030    sensor.sensorType=SENSOR_NONE;
02031    imageParamsR[P_SENSOR]=SENSOR_NONE; // to prevent from initializing again
02032    printk("No image sensor found\r\n");
02033 //   return -1;
02034  }
02035  imageParamsR[P_SENSOR_WIDTH]=sensor.imageWidth;
02036  imageParamsR[P_SENSOR_HEIGHT]=sensor.imageHeight;
02037  imageParamsW[P_WOI_WIDTH]=sensor.imageWidth; //needed?
02038  imageParamsW[P_WOI_HEIGHT]=sensor.imageHeight;//needed?
02039  imageParamsR[P_SENSOR]= sensor.sensorType;
02040  imageParamsW[P_CLK_SENSOR]=sensor.nomClockFreq;
02041  imageParamsR[P_VIDEO]=1;
02042  imageParamsW[P_VIDEO]=1;
02043  sensor.margins     =X313_MARGINS; 
02045 
02046   imageParamsW[P_I2C_QPERIOD]= (sensor.i2c_period * (imageParamsR[P_CLK_FPGA]/1000))/4000000;
02047   imageParamsW[P_I2C_BYTES]=sensor.i2c_bytes;
02048   program_i2c();
02049   X3X3_I2C_RESET_WAIT ;
02050   X3X3_I2C_RUN ;
02051   imageParamsR[P_FRAME]=0 ; // when sensor is reset;
02052 
02053 MD7(printk ("sensorType=%ld,sensor.imageWidth=%ld,sensor.imageHeight=%ld,sensor.margins=%ld\r\n", sensor.sensorType,sensor.imageWidth,sensor.imageHeight,sensor.margins));
02054 
02055  return programSensor(0); 
02056 }
02057 
02058 
02060 //#define CX313_FPGA_TABLES_FOCUSPARS 0xbc0 //block of focus-related parameters: left[11:0],right[11:0],top[11:0],bottom[11:0],full_width[11:0],filter_sel[3:0]
02061 //#define P_FOCUS_SHOW     93 // show focus information instead of/combined with the image:
02062 //                            // 0 - regular image, 1 - block focus instead of Y DC (AC=0), 2 - image Y DC combined all frame, 3 combined in WOI
02063 //#define P_FOCUS_SHOW1    94 // Additional parameter that modifies visualization mode. Currently just a single bit (how much to add)
02064 //#define P_FOCUS_VALUE    95 // (readonly) - sum of all blocks focus values inside focus WOI
02065 //#define P_FOCUS_LEFT     96 // focus WOI left margin, inclusive (3 LSB will be zeroed as it should be multiple of 8x8 block width) 
02066 //#define P_FOCUS_WIDTH    97 // focus WOI width (3 LSB will be zeroed as it should be multiple of 8x8 block width) 
02067 //#define P_FOCUS_TOP      98 // focus WOI top margin, inclusive (3 LSB will be zeroed as it should be multiple of 8x8 block height) 
02068 //#define P_FOCUS_HEIGHT   99 // focus WOI height (3 LSB will be zeroed as it should be multiple of 8x8 block height) 
02069 //#define P_FOCUS_TOTWIDTH 100 // (readonly) - total width of the image frame in pixels
02070 //#define P_FOCUS_FILTER  101 // select 8x8 filter used for the focus calculation (same order as quantization coefficients), 0..14
02071 void x313_program_focus(int totalwidth) {
02072   unsigned long flags;
02073   totalwidth&= 0xfff0;
02074   int left, right, top, bottom, filter_no,show1;
02075   show1=imageParamsW[P_FOCUS_SHOW1];
02076   left=imageParamsW[P_FOCUS_LEFT] & 0xff8;
02077   right=(left+imageParamsW[P_FOCUS_WIDTH] -8);
02078   if (right<0) {
02079     right=0;
02080     left=8;
02081   }
02082   else if (right >  0xfff) right = 0xfff;
02083   right &=0xff8;
02084 
02085   top=imageParamsW[P_FOCUS_TOP] & 0xff8;
02086   bottom=(top+imageParamsW[P_FOCUS_HEIGHT] -8);
02087   if (bottom<0) {
02088    bottom=0;
02089    top=8;
02090   }
02091   else if (bottom >  0xfff) bottom = 0xfff;
02092   bottom &=0xff8;
02093 
02094   filter_no=imageParamsW[P_FOCUS_FILTER];
02095   if   (filter_no > 14) filter_no=14;
02096 
02097   if ((totalwidth!=imageParamsR[P_FOCUS_TOTWIDTH]) ||
02098       (left   != imageParamsR[P_FOCUS_LEFT]) ||
02099       (right  != (left+imageParamsR[P_FOCUS_WIDTH] -8)) ||
02100       (top    != imageParamsR[P_FOCUS_TOP]) ||
02101       (bottom != (top+imageParamsR[P_FOCUS_HEIGHT] -8)) ||
02102       (filter_no != imageParamsR[P_FOCUS_FILTER]) ||
02103       (show1  != imageParamsR[P_FOCUS_SHOW1])) {
02104       imageParamsR[P_FOCUS_SHOW1]=   show1;
02105       imageParamsR[P_FOCUS_TOTWIDTH]=totalwidth;
02106       imageParamsR[P_FOCUS_LEFT]=    left;
02107       imageParamsR[P_FOCUS_WIDTH]=   right-left+8;
02108       imageParamsR[P_FOCUS_TOP]=     top;
02109       imageParamsR[P_FOCUS_HEIGHT]=  bottom-top+8;
02110       imageParamsR[P_FOCUS_FILTER]=  filter_no;
02111       local_irq_save(flags);
02112       //local_irq_disable();
02113       port_csp0_addr[X313_WA_COMP_TA]=CX313_FPGA_TABLES_FOCUSPARS; 
02114       port_csp0_addr[X313_WA_COMP_TD]=left;     
02115       port_csp0_addr[X313_WA_COMP_TD]=right;
02116       port_csp0_addr[X313_WA_COMP_TD]=top;
02117       port_csp0_addr[X313_WA_COMP_TD]=bottom;
02118       port_csp0_addr[X313_WA_COMP_TD]=totalwidth-1;
02119       port_csp0_addr[X313_WA_COMP_TD]=filter_no;
02120       port_csp0_addr[X313_WA_COMP_TD]=show1;
02121       port_csp0_addr[X313_WA_COMP_TA]=CX313_FPGA_TABLES_FOCUSPARS; 
02122       local_irq_restore(flags);
02123   } 
02124 //HACK?: Set focus display mode (TODO: remove fixed bit locations)
02125   imageParamsR[P_FOCUS_SHOW]=imageParamsW[P_FOCUS_SHOW] & 3;
02126   x313_JPEG_ctrl((x313_get_JPEG_ctrl() & 0x9fff) | (imageParamsR[P_FOCUS_SHOW] << 13));
02127 }
02128 
02129 
02130 /* 
02131  * ************************* programSensor ************************
02132  */
02133 static int program_KAI11000(void) {
02134  printk("here programmimbg KAI11000\n");
02135  return 1; // always success
02136 }
02137 #define PROGRAM_SENSOR_DIS_IRQ 0
02138 static int programSensor(int nonstop){   // program appropriate sensor
02139         struct hist_sensor_t *hist_s = NULL;
02140 //      unsigned long scale;
02141     float fscale_r;
02142     float fscale_g;
02143     float fscale_b;
02144     float fscale_g1;
02145     int   hact_shift;    // 0..3 - HACT phase shift
02146     unsigned long scale_r;
02147     unsigned long scale_g;
02148     unsigned long scale_b;
02149     unsigned long scale_g1;
02150     int ntilex,ntiley,padlen,n,sa,i;
02151 // there is a mess here, let's add some more
02152     int ntilex_compressor,ntiley_compressor; // what is actually written to chn 2 memory
02153 
02154     int dh,dv,bh,bv,l,h,t,timestamp_len,pfh,pf_stripes;
02155     int goodEOL=0;
02156         int sensRslt=0;   // sensor specific result
02157 #if PROGRAM_SENSOR_DIS_IRQ
02158         unsigned long flags;
02159 #endif
02160     short * shortP;
02161     int  scales_changed;
02162  MD1(printk("programSensor:, imageParamsR[P_PARS_CHANGED]=%x, nonstop=%d\n", (int) imageParamsR[P_PARS_CHANGED], nonstop));
02163         MD11(printk ("programSensor rp=0x%x, wp=0x%x\r\n", JPEG_rp, JPEG_wp ));
02164 
02165 // Changing frequency of the sensor confuses MT9P031 - it can get 0/1 pixel horizonatl shift, so sensor requires reset+reinitialization
02166 // after frequency change
02167    imageParamsR[P_TASKLET_CTL]=imageParamsW[P_TASKLET_CTL];
02168 
02169   if (imageParamsW[P_CLK_SENSOR]) {
02170      if (setClockFreq(1, imageParamsW[P_CLK_SENSOR])>=0) imageParamsR[P_CLK_SENSOR]=imageParamsW[P_CLK_SENSOR];
02171      imageParamsW[P_CLK_SENSOR]=0;
02172      X3X3_RSTSENSDCM;
02173 //#define CCAM_SET_HACT_PHASE(x) ccamCRAndOr(~X313_MASK(HACT_PHASE), X313_BITS(HACT_PHASE, (x)))
02174 
02175 // set HACT PHASE here
02176 
02177      hact_shift= 0.004 * (sensor.hact_delay/(1000000000.0/imageParamsR[P_CLK_SENSOR])) + 0.5;
02178      MD12(printk ("hact_shift=%d\r\n",hact_shift));
02179      if (hact_shift>3) hact_shift=3;
02180      CCAM_SET_HACT_PHASE(hact_shift) ;
02181 // turn sensor phase here
02182 // TODO need to add finding the correct phase - may be found once for sensor+fpga_image+frequency and saved
02183 // to measure correctly phase you need to give enough time for each measurement (sensor should output some image data, preferrably test pattern
02184 // so bit2 for 12-bit 5MPix (bit 0 for older 10-bit) will have all the combinations of 0 after 1, 1 after 0
02185 // procedure will be:
02186 // 1: set/change phase (may watch DCM state)
02187 // 2: X3X3_SENSDCM_NOP to reset error counters (error is a mismatch between data at strobe and two aux. ones - 1/4Tclk early and 1/4Tclk late)
02188 // 3: wait for some data to pass through (at least one sensor line)
02189 // read X313_SENSOR_PHASE
02190 // if it is <2 (MSB=0) the phase is correct and no changes are needed (with 96MHz and slow outputs that will not be the case at any phase)
02191 // if there is an error, look at the LSB that shows direction to change. Start with 90 degrees until there will be "right" transition,
02192 // i.e. while X3X3_SENSDCM_INC90 the LSB will change from 1 to 0 (don't remember to exit if MSB=0)
02193 // Then reverse direction and go with X3X3_SENSDCM_DEC until the LSB will be 1 again (or MSB=0). That will be the right phase
02194 
02195 //#define P_SENSOR_PHASE  513 // packed, low 16 bit - signed fine phase, bits [18:17] - 90-degrees shift
02196    MD12(printk("imageParamsR[%d]=0x%x imageParamsW[%d]=0x%x\r\n", (int) P_SENSOR_PHASE, (int) imageParamsR[P_SENSOR_PHASE], (int) P_SENSOR_PHASE, (int) imageParamsW[P_SENSOR_PHASE]) );
02197    if (imageParamsW[P_SENSOR_PHASE] !=0 ) { // if needed 0, may set some unused bit
02198      imageParamsR[P_SENSOR_PHASE]=imageParamsW[P_SENSOR_PHASE];
02199      imageParamsW[P_SENSOR_PHASE]=0;
02200    }
02201 
02202    if (imageParamsR[P_SENSOR_PHASE] !=0 ) { // unpack and use instead of the table data
02203      MD12(printk("imageParamsR[%d]=0x%x\r\n", (int) P_SENSOR_PHASE, (int) imageParamsR[P_SENSOR_PHASE]));
02204      shortP= (short * ) &imageParamsR[P_SENSOR_PHASE];
02205      sensor.sensorPhase=  shortP[0];
02206      sensor.sensorPhase90=shortP[1] & 3; //to mark as used
02207      MD12(printk ("sensor.sensorPhase=0x%x, sensor.sensorPhase90=0x%x\r\n",(int) sensor.sensorPhase, (int) sensor.sensorPhase90));
02208    }
02209 // possibly adjust phase here
02210 
02211    for (i=sensor.sensorPhase90;i>0;i--) {
02212       X3X3_SENSDCM_INC90 ;  // (0..3) 90-degree shift (fpcf -w 8 80)
02213    }
02214    if      (sensor.sensorPhase > 0) for (i=sensor.sensorPhase; i > 0; i--) {X3X3_SENSDCM_INC ; udelay(1); }
02215    else if (sensor.sensorPhase < 0) for (i=sensor.sensorPhase; i < 0; i++) {X3X3_SENSDCM_DEC ; udelay(1); }
02216 // write back possibly modified phase
02217    shortP= (short * ) &imageParamsR[P_SENSOR_PHASE];
02218    shortP[0] = sensor.sensorPhase;
02219    shortP[1] = sensor.sensorPhase90 | 4;
02220     MD12(printk("imageParamsR[%d]=0x%x\r\n", (int) P_SENSOR_PHASE, (int) imageParamsW[P_SENSOR_PHASE]));
02221 
02222      switch (imageParamsR[P_SENSOR] & SENSOR_MASK) {
02223 
02224 //#ifdef CONFIG_ETRAX_ELPHEL_KAI11000
02225       case SENSOR_KAI11000: { break;}
02226 //#endif
02227 
02228 
02229 #ifdef CONFIG_ETRAX_ELPHEL_ZR32112
02230       case SENSOR_ZR32112:  { break;}
02231 #endif
02232 #ifdef CONFIG_ETRAX_ELPHEL_ZR32212
02233       case SENSOR_ZR32212:  { break;}
02234 #endif
02235 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
02236       case SENSOR_KAC1310:  { break;}
02237 #endif
02238 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
02239       case SENSOR_KAC5000:  { break;}
02240 #endif
02241 #ifdef CONFIG_ETRAX_ELPHEL_MT9X001
02242       case SENSOR_MT9X001:  // { break;}//0x30..0x33
02243       case SENSOR_MT9Y001: //0x34..0x37
02244           {
02245 // reset/reinitialize MT9P001 sensor;
02246         CCAM_MRST_ON;
02247         udelay (100); // apply clock before removing MRST
02248         CCAM_MRST_OFF;
02249         printk ("Resetting sensor after sensor clock change\n");
02250         init_mt9x001();
02251         sensor.margins     =X313_MARGINS; 
02252 // it seems that something else is still not restored after sensor reset.
02253 // maybe just save/restore registers of the sensor?
02254 
02255         nonstop=0; // can not make nonstop if senosor is reset
02256       break;}
02257 #endif
02258 #ifdef CONFIG_ETRAX_ELPHEL_IBIS51300
02259       case SENSOR_IBIS51300:  { break;}
02260 #endif
02261      } //switch
02262   }
02263 
02264 
02265   if ((imageParamsR[P_SENSOR] & SENSOR_MASK)==SENSOR_NONE) {
02266     printk("can not program unknown/unexistent sensor\r\n");
02267 //    port_csp0_addr[X313_WA_SDCH0_CTL1]=0x8000; // sensor will be considered initialized - model 333
02268 //    port_csp0_addr[X313_WA_SDCH0_CTL2]=0x8000; // sensor will be considered initialized - model 313 ?
02269     X313_CHN0_SET_USED;
02270     return 0; // do nothing if no sensor is present
02271   }
02272 
02273 //   if ((imageParamsR[P_SENSOR] & SENSOR_MASK)==SENSOR_KAI11000) {
02274 //    printk("can not program KAI11000 sensor (yet)\n");
02275 //    return 0; // do nothing if no sensor is present
02276 //  }
02277   if(down_interruptible(&sensor_lock) != 0) return -1;
02278 
02279 
02280 // remove disabling irqs if desired
02281    MD8(printk("nonstop=%d\r\n", nonstop));
02282 
02283    if (!nonstop) {
02284      imageParamsR[P_OVERSIZE]=imageParamsW[P_OVERSIZE]?1:0;
02285 #if PROGRAM_SENSOR_DIS_IRQ
02286      local_irq_save(flags);
02287 #endif
02288      MD11(printk ("program sensor, !nonstop -> ...  "));
02289 
02290      camSeqStop();   // to reset data transefer to SDRAM from sensor - it could disturb pointers if let on
02291 MD6(printk ("programSensor  imageParamsR[P_PARS_CHANGED]=0x%x\r\n",imageParamsR[P_PARS_CHANGED]));
02293      imageParamsR[P_PARS_CHANGED]=1;
02294 
02295    }
02296    if (imageParamsR[P_PARS_CHANGED]) { // Maybe (to make it work faster) do not call program sensor if only some parameters are changed?
02297     imageParamsR[P_EXPOS]= (imageParamsW[P_EXPOS]>0)?imageParamsW[P_EXPOS]:1;
02298     
02299     if ((imageParamsW[P_COLOR_SATURATION_BLUE] != imageParamsR[P_COLOR_SATURATION_BLUE]) ||
02300         (imageParamsW[P_COLOR_SATURATION_RED] != imageParamsR[P_COLOR_SATURATION_RED])) {
02301         if (imageParamsW[P_COLOR_SATURATION_BLUE]<0) imageParamsW[P_COLOR_SATURATION_BLUE]=0;
02302         if (imageParamsW[P_COLOR_SATURATION_RED]<0)  imageParamsW[P_COLOR_SATURATION_RED]=0;
02303         if ((imageParamsW[P_COLOR_SATURATION_BLUE]*DEFAULT_COLOR_SATURATION_BLUE) > 102300)
02304           imageParamsW[P_COLOR_SATURATION_BLUE]=102300/DEFAULT_COLOR_SATURATION_BLUE;
02305         if ((imageParamsW[P_COLOR_SATURATION_RED]*DEFAULT_COLOR_SATURATION_RED) > 102300)
02306           imageParamsW[P_COLOR_SATURATION_RED]=102300/DEFAULT_COLOR_SATURATION_RED;
02307         imageParamsR[P_COLOR_SATURATION_BLUE]=imageParamsW[P_COLOR_SATURATION_BLUE];
02308         imageParamsR[P_COLOR_SATURATION_RED]=imageParamsW[P_COLOR_SATURATION_RED];
02309 //        port_csp0_addr[X313_WA_COLOR_SAT] = ((DEFAULT_COLOR_SATURATION_BLUE*imageParamsR[P_COLOR_SATURATION_BLUE])/100) |
02310 //                                           (((DEFAULT_COLOR_SATURATION_RED *imageParamsR[P_COLOR_SATURATION_RED])/100)<<16);
02311 //TODO:add to Exif
02312        frame_params.colorsat = ((DEFAULT_COLOR_SATURATION_BLUE*imageParamsR[P_COLOR_SATURATION_BLUE])/100) |
02313                                (((DEFAULT_COLOR_SATURATION_RED *imageParamsR[P_COLOR_SATURATION_RED])/100)<<16);
02314        port_csp0_addr[X313_WA_COLOR_SAT]=frame_params.colorsat;
02315     }
02316 
02317 //set fame sync delay
02318       
02319       port_csp0_addr[X313_WA_FRAMESYNC_DLY]= imageParamsR[P_FRAMESYNC_DLY]=  imageParamsW[P_FRAMESYNC_DLY];
02320 //P_FRAMESYNC_DLY     
02321 //X313_WA_FRAMESYNC_DLY    
02322     
02323 // TODO: stop sensor if running before writing parameters ?? probably not needed
02324     if (!nonstop) {
02325       imageParamsR[P_DMA_VALID]=0;
02326 // process common parameters (not sensor specific)
02327       imageParamsR[P_PAGE_ACQ]=imageParamsW[P_PAGE_ACQ]; // number of page for image acquisition
02328       imageParamsR[P_BGFRAME]= imageParamsW[P_BGFRAME]; // number of page for image acquisition
02329       imageParamsR[P_OVERLAP]=imageParamsW[P_OVERLAP];
02330 
02331 //      imageParamsR[P_TRIG]=  imageParamsW[P_TRIG];
02332 // don't touch bit 2 - async trigger mode
02333       imageParamsR[P_TRIG]=  (imageParamsR[P_TRIG] & 4) | (imageParamsW[P_TRIG] & ~4);
02334       imageParamsR[P_VIRTTRIG]=  imageParamsW[P_VIRTTRIG];
02335       imageParamsR[P_BITS]=  (imageParamsW[P_BITS] < 5)? 4 : (imageParamsW[P_BITS] < 9)? 8: 10; // TODO: add DMA size support 
02336       
02337 //      imageParamsR[P_FPN]=   imageParamsW[P_FPN];
02338       imageParamsR[P_SHIFTL]=imageParamsW[P_SHIFTL]& 0x7;
02339       imageParamsR[P_FPNS]=   imageParamsW[P_FPNS] & 0x7;
02340       imageParamsR[P_FPNM]=   imageParamsW[P_FPNM] & 0x7;
02341       imageParamsR[P_AUXCM]=(imageParamsW[P_AUXCM] < 2)? imageParamsW[P_AUXCM] : 2;
02342       imageParamsR[P_MCLK]=  (imageParamsW[P_MCLK]<129)?((imageParamsW[P_MCLK]>1)?imageParamsW[P_MCLK]:((imageParamsW[P_MCLK]>0)?2:0)):129;
02343 //      if ((imageParamsW[P_FPSLM] & ~3) == 0) imageParamsR[P_FPSLM]=  imageParamsW[P_FPSLM] & 0x3; // -1 - don't change
02344 //MD9 (printk ("\r\n============ imageParamsW[P_FPSLM]=0x%08x=== imageParamsR[P_FPSLM]=0x%08x\r\n",imageParamsW[P_FPSLM],imageParamsR[P_FPSLM]));
02345 
02346       PROGRAM_CLK_EN(1);
02347     }
02348 // make it work always? Even in non-stop mode?
02349     if ((imageParamsW[P_FPSLM] & ~3) == 0) imageParamsR[P_FPSLM]=  imageParamsW[P_FPSLM] & 0x3; // -1 - don't change
02350 MD9 (printk ("\r\n============ imageParamsW[P_FPSLM]=0x%08x=== imageParamsR[P_FPSLM]=0x%08x\r\n",imageParamsW[P_FPSLM],imageParamsR[P_FPSLM]));
02351 // set period to 0 - should be updated by sensors specific routines
02352     imageParamsR[P_PERIOD]=0;  // should be calculated even when not stopping
02353 // process  sensor specific parameters
02354     sensRslt=-1;
02355 
02356 /*
02357  * autoexposure: begin
02358  * exposure time correction
02359  */
02360         /* can't sleep process - all ok ! */
02361 //      hist_image_exp(get_imageParamsR(P_EXPOS));
02362         hist_image_exp(get_imageParamsR(P_VEXPOS));
02363         hist_s = hist_sensor_lock();
02364         if(hist_s != NULL) {
02365                 set_imageParamsW(P_VEXPOS, hist_s->exposure);
02366 //              set_imageParamsW(P_EXPOS, hist_s->exposure);
02367                 hist_sensor_unlock();
02368         }
02369 /*
02370  * autoexposure: end
02371  */
02372 //printk("\n\nimageParamsW[P_RSCALE] == 0x%04X; imageParamsR[P_RSCALE] == 0x%04X\n", imageParamsW[P_RSCALE], imageParamsR[P_RSCALE]);
02373 //printk("imageParamsW[P_BSCALE] == 0x%04X; imageParamsR[P_BSCALE] == 0x%04X\n", imageParamsW[P_BSCALE], imageParamsR[P_BSCALE]);
02374 
02376 
02377 //   set_gamma(imageParamsR[P_GAMMA], imageParamsR[P_PIXEL_LOW], scale_r, scale_g, scale_b, scale_g1);
02378  if ((imageParamsW[P_GAMMA]     != imageParamsR[P_GAMMA]) ||
02379      (imageParamsW[P_PIXEL_LOW] != imageParamsR[P_PIXEL_LOW] ) ||
02380      (imageParamsW[P_PIXEL_HIGH]!= imageParamsR[P_PIXEL_HIGH] ) ||
02381      (imageParamsW[P_RSCALE]    != imageParamsR[P_RSCALE] ) ||
02382      (imageParamsW[P_GSCALE]    != imageParamsR[P_GSCALE] ) ||
02383      (imageParamsW[P_BSCALE]    != imageParamsR[P_BSCALE] ))  {
02384 
02385     imageParamsR[P_GAMMA]=imageParamsW[P_GAMMA]; // copy values
02386     imageParamsR[P_PIXEL_LOW]=imageParamsW[P_PIXEL_LOW]; // copy values
02387     imageParamsR[P_PIXEL_HIGH]=imageParamsW[P_PIXEL_HIGH]; // copy values
02388 
02390     scales_changed=0;
02391     scale_g1 = imageParamsW[P_GSCALE]; 
02392     if(scale_g1 > SCALE_MAX)
02393        scale_g1 = SCALE_MAX;
02394     if(scale_g1 < SCALE_MIN)
02395        scale_g1 = SCALE_MIN;
02396     if (imageParamsR[P_GSCALE] != scale_g1 ) { imageParamsR[P_GSCALE]=scale_g1; scales_changed=1; }
02397     fscale_g1 = scale_g1;
02398     fscale_g1 /= 0x100;
02399     scale_r = imageParamsW[P_RSCALE];
02400     if(scale_r > SCALE_MAX)
02401        scale_r = SCALE_MAX;
02402     if(scale_r < SCALE_MIN)
02403        scale_r = SCALE_MIN;
02404     if (imageParamsR[P_RSCALE] != scale_r ) { imageParamsR[P_RSCALE]=scale_r; scales_changed=1; }
02405     fscale_r = scale_r;
02406     fscale_r /= 0x100;
02407     scale_b = imageParamsW[P_BSCALE];
02408     if(scale_b > SCALE_MAX)
02409        scale_b = SCALE_MAX;
02410     if(scale_b < SCALE_MIN)
02411        scale_b = SCALE_MIN;
02412     if (imageParamsR[P_BSCALE] != scale_b ) { imageParamsR[P_BSCALE]=scale_b; scales_changed=1; }
02413     if (scales_changed){
02414 MD13(printk("imageParamsW[P_GAMMA]=      0x%x, imageParamsR[P_GAMMA]=      0x%x\n" \
02415             "imageParamsW[P_PIXEL_LOW]=  0x%x, imageParamsR[P_PIXEL_LOW]=  0x%x\n" \
02416             "imageParamsW[P_PIXEL_HIGH]= 0x%x, imageParamsR[P_PIXEL_HIGH]= 0x%x\n" \
02417             "imageParamsW[P_RSCALE]=     0x%x, imageParamsR[P_RSCALE]=     0x%x\n" \
02418             "imageParamsW[P_GSCALE]=     0x%x, imageParamsR[P_GSCALE]=     0x%x\n" \
02419             "imageParamsW[P_BSCALE]=     0x%x, imageParamsR[P_BSCALE]=     0x%x\n", \
02420              (int) imageParamsW[P_GAMMA],      (int) imageParamsR[P_GAMMA], \
02421              (int) imageParamsW[P_PIXEL_LOW],  (int) imageParamsR[P_PIXEL_LOW], \
02422              (int) imageParamsW[P_PIXEL_HIGH], (int) imageParamsR[P_PIXEL_HIGH], \
02423              (int) imageParamsW[P_RSCALE],     (int) imageParamsR[P_RSCALE], \
02424              (int) imageParamsW[P_GSCALE],     (int) imageParamsR[P_GSCALE], \
02425              (int) imageParamsW[P_BSCALE],     (int) imageParamsR[P_BSCALE]));
02426 
02427       fscale_b = scale_b;
02428       fscale_b /= 0x100;
02429       fscale_g = 1.0;
02430 //    set_imageParamsR(P_GAINB, imageParamsW[P_GAINB]);
02431     /* normalize scale */
02432       if((fscale_r < fscale_g) || (fscale_b < fscale_g) || (fscale_g1 < fscale_g)) {
02433        if((fscale_r < fscale_b) && (fscale_r < fscale_g1)) {
02434           fscale_g1 /= fscale_r;
02435           fscale_g  /= fscale_r;
02436           fscale_b  /= fscale_r;
02437           fscale_r = 1.0; //AF:-)
02438        } else {
02439           if(fscale_b < fscale_g1) {
02440             fscale_r  /= fscale_b;
02441             fscale_g  /= fscale_b;
02442             fscale_g1 /= fscale_b;
02443             fscale_b = 1.0;  //AF:-)
02444           } else {
02445             fscale_r /= fscale_g1;
02446             fscale_g /= fscale_g1;
02447             fscale_b /= fscale_g1;
02448             fscale_g1 = 1.0;
02449           }
02450        }
02451       }
02452       scale_r  = fscale_r  * 0x100;
02453       scale_g  = fscale_g  * 0x100;
02454       scale_b  = fscale_b  * 0x100;
02455       scale_g1 = fscale_g1 * 0x100;
02456       gains.used = 1;
02457 
02458 // TODO: move above gain calculations outside   
02459    
02460    
02461         /* apply gamma */
02462           set_gamma(imageParamsR[P_GAMMA], imageParamsR[P_PIXEL_LOW], scale_r, scale_g, scale_b, scale_g1);
02463   } 
02464 } 
02465 
02466 //TODO:add to Exif
02467     frame_params.gamma=imageParamsR[P_GAMMA];
02468     frame_params.black=imageParamsR[P_PIXEL_LOW]; // no support for P_PIXEL_HIGH in the data stored in circbuf
02469 //TODO:add to Exif
02470     frame_params.rscale=imageParamsR[P_RSCALE];
02471     frame_params.bscale=imageParamsR[P_BSCALE];
02472 
02473 
02474 
02475    imageParamsR[P_COLOR]=imageParamsW[P_COLOR];
02476 
02477 // common part of decimation/binning calculation
02478    if (!nonstop) {
02479  // copy enabled bits from imageParamsW[P_FLIP] to imageParamsR[P_FLIP]
02480      if (sensor.flips & 1) imageParamsR[P_FLIP]=((imageParamsR[P_FLIP] ^ imageParamsW[P_FLIP]) & (sensor.flips & 3)) ^ imageParamsR[P_FLIP];
02481      dh = imageParamsW[P_DCM_HOR];
02482      dv = imageParamsW[P_DCM_VERT];
02483      if (dh<1) dh=1; else if (dh>32) dh=32;
02484      if (dv<1) dv=1; else if (dv>32) dv=32;
02485     MD8(printk("dv=%d, dh=%d\r\n", dv,dh));
02486 
02487      while ((dh>1) && !(sensor.dcmHor  & (1 << (dh-1)))) dh--;
02488      while ((dv>1) && !(sensor.dcmVert & (1 << (dv-1)))) dv--;
02489      bh = imageParamsW[P_BIN_HOR]; if (bh<1) bh=1; else if (bh>dh) bh=dh;
02490      bv = imageParamsW[P_BIN_VERT];if (bv<1) bv=1; else if (bv>dv) bv=dv;
02491      while ((bh>1) && !(sensor.dcmHor  & (1 << (bh-1)))) bh--;
02492      while ((bv>1) && !(sensor.dcmVert & (1 << (bv-1)))) bv--;
02493      imageParamsR[P_DCM_HOR] = dh;
02494      imageParamsR[P_DCM_VERT]= dv;
02495      imageParamsR[P_BIN_HOR] = bh;
02496      imageParamsR[P_BIN_VERT]= bv;
02497 //TODO:add to Exif
02498 
02499 //     frame_params.bindec_hor= ((bh-1)<<4) | ((dh-1) & 0xf);     // (binning/decimation horizontal, 1..16 for each)
02500 //     frame_params.bindec_vert=((bv-1)<<4) | ((dv-1) & 0xf);     // (binning/decimation vertical  , 1..16 for each)
02501 
02502     MD8(printk("dv=%d, dh=%d\r\n", dv,dh));
02503 // sensor-specific binning adjustment (not all combinations are valid)   
02504      switch (imageParamsR[P_SENSOR] & SENSOR_MASK) {
02505 #ifdef CONFIG_ETRAX_ELPHEL_MT9X001
02506       case SENSOR_MT9X001: //0x30..0x33
02507       case SENSOR_MT9Y001: //0x34..0x37
02508       adjustBinning_mt9x001();
02509       break;
02510 #endif
02511      } //switch, sensor-specific decim/bin
02512 // adjust WOI width (will be less in timestamp mode 2)
02513      timestamp_len = (((imageParamsW[P_PF_HEIGHT] >> 16) & 3)==2)? X313_TIMESTAMPLEN*dh : 0;
02514 // adjust width/height first, then adjust left top
02515      l=imageParamsW[P_WOI_WIDTH];
02516      if (!imageParamsR[P_OVERSIZE]) {
02517        if ((l-timestamp_len) > sensor.imageWidth) l = sensor.imageWidth+timestamp_len;
02518      } 
02519      l=l/dh/X313_TILEHOR;
02520      l*=X313_TILEHOR;
02521 // suppose minimal width refers to decimated output      
02522      while (l < sensor.minWidth) l+=X313_TILEHOR;
02523      imageParamsR[P_ACTUAL_WIDTH]=l;
02524      sensor.pixelWidth=l+sensor.margins-timestamp_len;
02525      MD8(printk("sensor.pixelWidth=0x%x, sensor.margins=0x%x\r\n", sensor.pixelWidth,sensor.margins));
02526      l*=dh;
02527 //     l-=timestamp_len; // normally - 0, else X313_TIMESTAMPLEN*dh
02528      imageParamsR[P_WOI_WIDTH]=l; // decreased for time stamp if any
02529 // adjust WOI height (will be less in timestamp mode 2)
02530 //     pfh = (imageParamsW[P_PF_HEIGHT] & 0xffff) * dv; // corrected to decimation
02531      pfh = (imageParamsW[P_PF_HEIGHT] & 0xffff);
02532      h=imageParamsW[P_WOI_HEIGHT];
02533      if(pfh > 0) {
02534        if (pfh < sensor.minHeight)  pfh =  sensor.minHeight;
02535        if (imageParamsR[P_COLOR] && (pfh & 1)) pfh++;
02536        if (h > X313_MAXHEIGHT*dv) h=X313_MAXHEIGHT*dv;
02537        pf_stripes = h / (pfh * dv);
02538        if(pf_stripes < 1) pf_stripes = 1;
02539        sensor.pixelHeight=pfh;
02540 //pfh - output lines, not programmed (they are  *dv)       
02541      } else {
02542        if (!imageParamsR[P_OVERSIZE]) {
02543          if (h > sensor.imageHeight) h=sensor.imageHeight;
02544        }
02545        h=h/dv/X313_TILEVERT;
02546        h*=X313_TILEVERT;
02547 // suppose minimal height refers to decimated output      
02548        while (h < sensor.minHeight) h+=X313_TILEVERT;
02549        sensor.pixelHeight=h+sensor.margins;
02550        h*=dv;        
02551        pf_stripes = 0;
02552        pfh = 0;
02553      }
02554      imageParamsR[P_PF_HEIGHT]=(imageParamsW[P_PF_HEIGHT] & 0xffff0000) | pfh;
02555      imageParamsR[P_WOI_HEIGHT]=h;
02556      imageParamsR[P_ACTUAL_HEIGHT]=h/dv;
02557      MD8(printk("pfh=0x%x, pf_stripes=0x%x, h=%d(0x%x)\r\n", pfh, pf_stripes,h,h));
02558    } else {//(!nondtop)
02559       dh = imageParamsR[P_DCM_HOR];
02560       dv = imageParamsR[P_DCM_VERT];
02561       pfh= imageParamsR[P_PF_HEIGHT] & 0xffff;
02562       timestamp_len = (((imageParamsR[P_PF_HEIGHT] >> 16) & 3)==2)? X313_TIMESTAMPLEN*dh : 0;
02563    }
02564 //#define P_FLIP          30 // bit 0 - horizontal, bit 1 - vertical
02565 //TODO:add to Exif
02566    frame_params.color=(imageParamsR[P_COLOR] & 0x0f) | (imageParamsR[P_FLIP] << 6) ;
02567 
02568    MD8(printk("sensor.pixelWidth=0x%lx, sensor.pixelHeight=0x%lx\r\n", sensor.pixelWidth,sensor.pixelHeight));
02569 
02570 //   unsigned long  pixelWidth;     // number of the pixels output in a line (including margins, decimation)
02571 //   unsigned long  pixelHeight;    // number of the lines output in a frame (including margins, decimation)
02572 
02573 
02574 // adjusted always (for any nonstop)   
02575 // left margin     
02576         l = imageParamsW[P_WOI_LEFT];
02577    if (!imageParamsR[P_OVERSIZE]) {
02578            if(imageParamsR[P_COLOR])
02579                    l &= 0xfffe;
02580            if((l < 0) || (l & 0x8000))
02581                    l = 0;
02582            if ((l + imageParamsR[P_WOI_WIDTH] + sensor.margins) > sensor.clearWidth) { 
02583                    l = sensor.clearWidth - imageParamsR[P_WOI_WIDTH] - sensor.margins;
02584                    if(imageParamsR[P_COLOR])
02585                            l &= 0xfffe;
02586            }
02587            if(l & 0x8000) l = 0;
02588    }
02589         imageParamsR[P_WOI_LEFT] = l; // maybe adjusted later by sensor-specific function
02590 // top margin
02591         t = imageParamsW[P_WOI_TOP];
02592    if (!imageParamsR[P_OVERSIZE]) {
02593         if(imageParamsR[P_COLOR])
02594                 t &= 0xfffe;
02595            if((t < 0) || (t & 0x8000))
02596                    t = 0;
02597            if(pfh > 0) {
02598                    if((t + pfh * dv) > sensor.clearHeight)
02599                         t = sensor.clearHeight - pfh * dv;
02600            } else {
02601                    if((t + imageParamsR[P_WOI_HEIGHT] + sensor.margins) > sensor.clearHeight)
02602                            t = sensor.clearHeight - imageParamsR[P_WOI_HEIGHT] - sensor.margins;
02603            }
02604       if (imageParamsR[P_COLOR]) t &= 0xfffe;
02605    }
02606    imageParamsR[P_WOI_TOP]=t; // maybe adjusted later by sensor-specific function
02607 
02608 if  (imageParamsW[P_CLK_SENSOR]  > sensor.maxClockFreq) imageParamsW[P_CLK_SENSOR] = sensor.maxClockFreq;
02609 imageParamsR[P_FPGA_XTRA]=imageParamsW[P_FPGA_XTRA];
02610    
02611       
02612    switch (imageParamsR[P_SENSOR] & SENSOR_MASK) {
02613 
02614 //#ifdef CONFIG_ETRAX_ELPHEL_KAI11000
02615       case SENSOR_KAI11000: { CCAM_ARST_OFF; sensRslt=program_KAI11000();break;}
02616 //#endif
02617 
02618 
02619 #ifdef CONFIG_ETRAX_ELPHEL_ZR32112
02620       case SENSOR_ZR32112: { CCAM_ARST_OFF; sensRslt=program_ZR32112();break;}
02621 #endif
02622 #ifdef CONFIG_ETRAX_ELPHEL_ZR32212
02623       case SENSOR_ZR32212: {CCAM_ARST_OFF; sensRslt=program_ZR32212();break;}
02624 #endif
02625 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
02626       case SENSOR_KAC1310: {sensRslt=program_KAC1310(nonstop);break;} // add nonstop here too
02627 #endif
02628 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
02629       case SENSOR_KAC5000: {sensRslt=program_KAC5000(nonstop);break;} // add nonstop here too
02630 #endif
02631 #ifdef CONFIG_ETRAX_ELPHEL_MT9X001
02632       case SENSOR_MT9X001: //0x30..0x33
02633       case SENSOR_MT9Y001: //0x34..0x37
02634 //      if ((imageParamsR[P_SENSOR] & 7)!=0) {sensRslt=program_mt9x001(nonstop);break;}
02635       if ((imageParamsR[P_SENSOR] & 7)!=0) {
02636 //         printk("programming mt9p001\r\n");
02637 //sensRslt - number of frames to skip after changing parameters         
02638          sensRslt=program_woi_mt9x001(nonstop);
02639          if (sensRslt>=0) {i=program_gains_mt9x001();    if ((i<0) || (i>sensRslt)) sensRslt=i;} // now - always <= 0 ?
02640 // moved outside individual sensors
02641 //         if (sensRslt>=0) {i=program_exposure_mt9x001(); if ((i<0) || (i>sensRslt)) sensRslt=i;} // now - always <= 0 ?
02642       break;}
02643 #endif
02644 #ifdef CONFIG_ETRAX_ELPHEL_IBIS51300
02645       case SENSOR_IBIS51300: {sensRslt=program_IBIS51300();break;}  // add nonstop here too
02646 #endif
02647    } //switch
02648 
02652 #if 0
02653         if(sensRslt>= 0) {
02654                 i = program_sensor_exposition_just();
02655                 if((i < 0) || (i > sensRslt))
02656                         sensRslt = i;
02657         } // now - always <= 0 ?
02658 #endif
02659 // Sensor might modify sensor.pixelWidth, sensor.pixelHeight
02660 //TODO: adjust P_WOI_WIDTH, P_ACTUAL_WIDTH (and height) accordingly
02661 
02662 
02663 
02664 // restore line length to the full length (above was sensor pixels)   
02665 //   imageParamsR[P_WOI_WIDTH]+=timestamp_len; // normally - 0, else X313_TIMESTAMPLEN*dh
02666 /* refresh histogramm (autoexposure) window */
02667    hist_image_size(get_imageParamsR(P_ACTUAL_WIDTH), get_imageParamsR(P_ACTUAL_HEIGHT));
02668 // Bayer phase will be set in individual driver, but if it was explicitly specified - overwrite it   
02669    if (imageParamsW[P_BAYER]<=3) imageParamsR[P_BAYER]=imageParamsW[P_BAYER];
02670 
02671    if (!nonstop) {
02673      if (imageParamsR[P_TRIG] & 0x4) {CCAM_TRIG_EXT ; program_early_timestamp(); }
02674      else                            CCAM_TRIG_INT ;
02675 // process clocks here - normally just one during initializing
02676      if (imageParamsW[P_CLK_FPGA]) {
02677 
02678 #if 0 // disable changing FPGA clock here - needs readjusting the phase
02679        if (setClockFreq(0, imageParamsW[P_CLK_FPGA])>=0) {
02680          imageParamsR[P_CLK_FPGA]=imageParamsW[P_CLK_FPGA];
02681 // needs phase adjustment too ! *****************************************************************8         
02682          initSDRAM();
02683        }  
02684 #endif
02685        imageParamsW[P_CLK_FPGA]=0; 
02686      }
02687 // Changing frequency of the sensor confuses MT9P031 - it can get 0/1 pixel horizonatl shift, so sensor requires reset+reinitialization
02688 // after frequency change
02689 #if 0
02690      if (imageParamsW[P_CLK_SENSOR]) {
02691        if (setClockFreq(1, imageParamsW[P_CLK_SENSOR])>=0) imageParamsR[P_CLK_SENSOR]=imageParamsW[P_CLK_SENSOR];
02692        imageParamsW[P_CLK_SENSOR]=0;
02693        X3X3_RSTSENSDCM;
02694      }
02695 #endif
02696 //set bayer phase
02697      ccamCRAndOr(~X313_MASK(BAYER_PHASE), X313_BITS(BAYER_PHASE,imageParamsR[P_BAYER]));
02698 // prepare compressor color mode 0 - mono, 1 - color, 2 - jp4/google
02699      if ((imageParamsW[P_COLOR] & 3)==2) { // jp4/google mode
02700        x313_JPEG_ctrl(x313_get_JPEG_ctrl() | JPEG_CTRL_MONOCHROME | JPEG_CTRL_NOMOSAIC);
02701        imageParamsR[P_COLOR] = 2;
02702      } else if ((imageParamsW[P_COLOR] & 3)==1) {
02703        x313_JPEG_ctrl(x313_get_JPEG_ctrl() & ~JPEG_CTRL_MONOCHROME & ~JPEG_CTRL_NOMOSAIC);
02704        imageParamsR[P_COLOR] = 1;
02705      } else {
02706        x313_JPEG_ctrl((x313_get_JPEG_ctrl()  & ~JPEG_CTRL_NOMOSAIC) | JPEG_CTRL_MONOCHROME);
02707        imageParamsR[P_COLOR] = 0;
02708      }
02709 // Set number of frames to skip according to sensor requirements
02710      if (sensRslt>=0) { // no error
02711 // adjust exposure to variable MCLK - obsolete? or still in 313?
02712        if ((imageParamsR[P_MCLK]!=4) && (imageParamsR[P_MCLK]!=0)) imageParamsR[P_EXPOS]= (imageParamsR[P_EXPOS]<<2)/imageParamsR[P_MCLK];
02713        if (imageParamsR[P_EXPOS]<1) imageParamsR[P_EXPOS]=1;
02714 // program FPGA  mclk
02715        PROGRAM_CLK_EN( (imageParamsR[P_MCLK]>0)?1:0);
02716 // Set timestamp mode 
02717 MD8(printk ("set timestamp mode to %lx\r\n", ((imageParamsR[P_PF_HEIGHT] >>16) & 3)));
02718        port_csp0_addr[X313_WA_TIMESTAMP] = (imageParamsR[P_PF_HEIGHT] >>16) & 3;
02719        
02720 // make approximation of the period (in clocks) if it was not set by sensor (should)
02721        if (imageParamsR[P_PERIOD]==0) imageParamsR[P_PERIOD]=(imageParamsR[P_ACTUAL_WIDTH]+20)*(imageParamsR[P_ACTUAL_HEIGHT]+1);
02722 // ***** Put here new parameters programming ******
02723        port_csp0_addr[X313_WA_VIRTTRIG]= imageParamsR[P_VIRTTRIG];
02724        if (imageParamsW[P_COLOR] & 0x300) imageParamsR[P_COLOR] |= 0x200; // sensor does not have test mode
02725        if (imageParamsR[P_BGFRAME]) PROGRAM_FPN(0,0,0,0,0);
02726 //       else  PROGRAM_FPNW(imageParamsR[P_FPN],(imageParamsR[P_BITS]!=8));
02727        else  PROGRAM_FPN(((imageParamsR[P_COLOR]& 0x200)>0), \
02728                          (imageParamsR[P_FPNS]),  \
02729                          (imageParamsR[P_FPNM]),     \
02730                          (imageParamsR[P_BITS]!=8), \
02731                           imageParamsR[P_SHIFTL]);
02732 //programm channel1 (FPN). Will not enable if not needed (imageParamsR[P_FPN]==0)
02733        ntilex=((imageParamsR[P_ACTUAL_WIDTH]+sensor.margins+7)>>3);
02734        if ((imageParamsR[P_PF_HEIGHT] & 0xffff)>0) {
02735           ntiley=imageParamsR[P_ACTUAL_HEIGHT]; // number of lines it the whole frame
02736 // no FPN yet for pf mode       
02737        } else {
02738           ntiley=imageParamsR[P_ACTUAL_HEIGHT]+sensor.margins;
02739 //   printk("ntilex=%x, ntiley= %x\r\n", ntilex,ntiley);
02740           if(!imageParamsR[P_BGFRAME] && ((imageParamsR[P_FPNS]!=0) || (imageParamsR[P_FPNM]!=0))) {
02741            X313_INIT_SDCHAN(1,0,0,0, X313_MAP_FPN, (ntilex-1), (ntiley-1)); // multiple lines - already {}
02742 //       enable channel1 for reading SDRAM
02743            X313_CHN_EN(1);
02744 // wait ready later...
02745          }
02746        }
02747 //       goodEOL=0; // last 8/16 blocks of pixels in each scanline are bad (only 2 are actually written)
02748 // if 8-bit mode we'll need to update ntilex. fpga tries to write 2 bytes more (but not crossing the page boundaries
02749        if ((imageParamsR[P_BITS]==8) && (!imageParamsR[P_BGFRAME])) {
02750            ntilex=((imageParamsR[P_ACTUAL_WIDTH]+sensor.margins+15)>>4);
02751 //           if ((imageParamsR[P_PF_HEIGHT] & 0xf0000)>0) ntilex=((imageParamsR[P_ACTUAL_WIDTH]+X313_MARGINS+15+28)>>4);
02752 //           else                                         ntilex=((imageParamsR[P_ACTUAL_WIDTH]+X313_MARGINS+15)>>4);
02753 
02754            goodEOL=((imageParamsR[P_ACTUAL_WIDTH] & 0x0f) == 0) && ((imageParamsR[P_ACTUAL_WIDTH] & 0x1f0) != 0);
02755            if (goodEOL) ntilex--;
02756        }    
02757        if (imageParamsR[P_OVERLAP]>=(imageParamsR[P_ACTUAL_HEIGHT]+2)) imageParamsR[P_OVERLAP]=imageParamsR[P_ACTUAL_HEIGHT]+1;
02758        if (imageParamsR[P_OVERLAP]>0) ntiley=(ntiley<<1);
02759 // ntiley will be twice bigger for synch. mode)
02760        padlen=((ntilex+31)>>5) << 8;
02761        sa=X313_MAP_FRAME + ((padlen * (imageParamsR[P_ACTUAL_HEIGHT]+sensor.margins) * imageParamsR[P_PAGE_ACQ]) << ((get_imageParamsR(P_TRIG) & 1)?1:0));
02762 MD8(printk ("-->> sa frame = 0x%08X, ntilex=0x%04X, ntiley=0x%04X\r\n", sa, ntilex, ntiley));
02763 //printk("!!! -->> sa frame = 0x%08X\r\n", sa);
02764 //   printk("ntilex=%x, ntiley= %x, padlen=%x, sa=%x\r\n", ntilex,ntiley,padlen,sa);
02765        X313_INIT_SDCHAN(0,0,1,1, \
02766              sa, \
02767              (ntilex-1),(ntiley-1)); // dependency - source
02768        X313_CHN_EN(0);
02769 //programm number of lines to read
02770        if ((imageParamsR[P_PF_HEIGHT] & 0xffff)>0) {
02771          i = (imageParamsR[P_ACTUAL_HEIGHT] & 0xfff) | ((imageParamsR[P_ACTUAL_HEIGHT]/(imageParamsR[P_PF_HEIGHT] & 0xffff))<<16) ;
02772        } else {
02773          i= (imageParamsR[P_ACTUAL_HEIGHT]+sensor.margins+imageParamsR[P_OVERLAP]);
02774        }
02775        port_csp0_addr[X313_WA_NLINES] = i;
02776 MD8(printk ("port_csp0_addr[X313_WA_NLINES] =%d(0x%x)\r\n", i,i));
02777 //prepare data for JPEG compressor (and program partially)
02778 //static int jpeg_sdram_ctl0;
02779 // old code commented out
02780 // X313_INIT_SDCHAN(num,mode,wnr,dep,sa,ntilex,ntiley)
02781 
02782 //    int ntilex_compressor,ntiley_compressor; // what is actually written to chn 2 memory
02783 #if 0
02784        jpeg_sdram_ctl0=X313_PREINIT_SDCHAN(2,1,
02785              ((imageParamsR[P_PF_HEIGHT] & 0xffff)>0)?1:0, // photo-finish mode
02786              0,  // no dependency here
02787              sa,
02788              ntilex - (goodEOL?1:2), 
02789              ((imageParamsR[P_PF_HEIGHT] & 0xffff)>0)?(ntiley-0x10):(ntiley-sensor.margins-0x10) );
02790 #endif
02791        ntilex_compressor=ntilex - (goodEOL?1:2);
02792        ntiley_compressor=((imageParamsR[P_PF_HEIGHT] & 0xffff)>0)?(ntiley-0x10):(ntiley-sensor.margins-0x10);
02793        jpeg_sdram_ctl0=X313_PREINIT_SDCHAN(2,1,
02794              ((imageParamsR[P_PF_HEIGHT] & 0xffff)>0)?1:0, // photo-finish mode
02795              0,  // no dependency here
02796              sa,
02797              ntilex_compressor, 
02798              ntiley_compressor );
02799 //TODO:add to Exif
02800        frame_params.width=(ntilex_compressor+1)<<4; //actual width how compressor sees it, in pixels
02801        frame_params.height=(ntiley_compressor &0xfff0)+0x10; //actual height how compressor sees it, in pixels
02802 
02803 //       x313_program_focus(frame_params.width) ;//!NOTE: (new function)
02804 
02805 MD8(printk ("programSensor ntilex=0x%x, ntiley=0x%x jpeg_sdram_ctl0=0x%x\r\n", ntilex, ntiley,jpeg_sdram_ctl0));
02806 MD8(printk ("programSensor 2ctl1=0x%lx, 2ctl2=0x%lx\r\n", port_csp0_addr[X313_WA_SDCH2_CTL1], port_csp0_addr[X313_WA_SDCH2_CTL2]));
02807 // set number of MCUs to acquire
02808        if (imageParamsR[P_OVERLAP]>0) ntiley=(ntiley>>1);
02809        if ((imageParamsR[P_PF_HEIGHT] & 0xffff)>0) {
02810          n= ((ntilex - (goodEOL?0:1)) & 0x3ff) * ((ntiley)>>4) -1;
02811        } else {
02812          n= ((ntilex - (goodEOL?0:1)) & 0x3ff) * ((ntiley-sensor.margins)>>4) -1;
02813        }
02814        port_csp0_addr[X313_WA_MCUNUM]= n;
02815        imageParamsR[P_TILES]=n+1;
02817 
02818 
02819 MD8(printk ("port_csp0_addr[X313_WA_MCUNUM] =%d (0x%x)\r\n", n,n));
02820 // printk("ntilex=0x%x, ntiley= 0x%x, MCUs=0x%x\r\n", ntilex,ntiley,n);
02821 // printk("actual width=0x%x, actual height= 0x%x\r\n", imageParamsR[P_ACTUAL_WIDTH],imageParamsR[P_ACTUAL_HEIGHT]);
02822 // wait FPN ready (if used)
02823     if ((imageParamsR[P_FPNS]!=0) ||(imageParamsR[P_FPNM]!=0)) {
02824 //       if (imageParamsR[P_FPN]!=0)) { // +++++ Why?
02825          n=1000;
02826          while (((n--)>0) && !X313_SR(CH1RDY)); udelay (1);
02827        }
02828      } else { // error occured while programming sensor
02829        setCamSeqState(CAMSEQ_OFF);
02830     printk("Error programming sensor\n");
02831      } // if sensResult/else
02832     } // if (!nonstop) 
02833 
02835 
02836    if(sensRslt>= 0) {
02837       i = program_sensor_exposition_just();
02838       if((i < 0) || (i > sensRslt))
02839          sensRslt = i;
02840    } // now - always <= 0 ?
02841 
02842 
02843 
02844 
02845     x313_program_focus(frame_params.width) ;
02846 //     start acquisition (granting internal/external) - not here
02847    } // changes/no changes
02848 
02849    imageParamsR[P_UPDATE]=1;  // in sync
02850    imageParamsW[P_UPDATE]=0;  // not needed
02852    imageParamsR[P_PARS_CHANGED]=0;
02853 
02854    if (!nonstop) {
02856      setCamSeqCount(((sensRslt>=0) && ((imageParamsW[P_PF_HEIGHT] & 0xffff)==0))?sensRslt:0);
02857      setCamSeqState((sensRslt>=0)?CAMSEQ_READY:CAMSEQ_OFF);
02858 #if PROGRAM_SENSOR_DIS_IRQ
02859      local_irq_restore(flags); // remove completely?
02860 #endif
02861    }  
02862    MD2(printk("programSensor:, sensRslt=%x,getCamSeqState()=%x\n", (int) sensRslt, (int) getCamSeqState()));
02863    up(&sensor_lock);
02864    MD10(dumpFrameParams(&frame_params,"\nframe parameters after ProgramSensor:"));
02865    MD11(printk ("rp=0x%x, wp=0x%x\r\n", JPEG_rp, JPEG_wp ));
02866    imageParamsR[P_PGMSENSRSLT]=sensRslt;
02867    imageParamsR[P_SKIP_FRAMES]=imageParamsW[P_SKIP_FRAMES];
02868    return sensRslt;
02869 }
02870 // autoexp unlock timing
02871 void exposition_unlock(void) {
02872         set_imageParamsW(P_EXPOS, get_imageParamsR(P_EXPOS));
02873         set_imageParamsW(P_VEXPOS, 0);
02874 }
02875 // autoexoposure program sensor timing
02876 int program_sensor_exposition(void) {
02877         int sensRslt = -1;
02878 //printk ("*************************");
02879         struct hist_sensor_t *hist_s = NULL;
02880         unsigned long exp = 0x00;
02881         if(down_trylock(&sensor_lock) != 0)
02882                 return -1;
02883         /* process can't sleep - all ok !!! */
02884         hist_s = hist_sensor_lock();
02885         if(hist_s != NULL) {
02886                 set_imageParamsW(P_VEXPOS, hist_s->exposure);
02887                 exp = hist_s->exposure;
02888                 hist_sensor_unlock();
02889         } else {
02890                 up(&sensor_lock);
02891                 return -1;
02892         }
02893 
02894         sensRslt = program_sensor_exposition_just();
02895 
02896    up(&sensor_lock);
02897 //printk("\n\nnew exp == %d\n\n", exp);
02898    return sensRslt;
02899 }
02900 // adjust fps limit to compressor capabilities.
02901 // use P_FCLK (fpga clock, HZ)
02902 //     P_COLOR (1 - color, 2,0 - mono) - later, currently not implemented in FPGA
02903 //     P_TILES - number of tiles to process
02904 //     P_FPGA_XTRA - extra cycles (fpga clocks) in frame
02905 
02906 
02907 
02908 
02909 
02910  void adjust_fps_2_compressor(void) {
02911 //    int cycles= imageParamsR[P_TILES]*(((imageParamsR[P_COLOR] &3)==1)?762:512)+imageParamsR[P_FPGA_XTRA];
02912         int cycles = imageParamsR[P_TILES] * 768 + imageParamsR[P_FPGA_XTRA]; // 768 == FPGA clock time for the tile (YCbCr 4:2:0) 16x16 * 1.5
02913         int fp100s = imageParamsR[P_CLK_FPGA] / ((cycles/100) + 1);
02914 // preserve limit mode, set limit if compressor is slower or upper limit mode is not set
02915 // If only "maintain" (lower limit) flag is set exposure will be limited tothe frame time determined from slowest of the sensor and compressor
02916         if(((imageParamsR[P_FPSLM] & 1) == 0) || (imageParamsW[P_FP100S] > fp100s))
02917                 imageParamsW[P_FP100S] = fp100s ;
02918     MD9(printk("\r\n+++++++++ fp100s=0x%08x imageParamsR[P_FPSLM]=0x%01X, imageParamsW[P_FPSLM]=0x%01X, imageParamsR[P_FP100S] = 0x%08X, imageParamsW[P_FP100S] = 0x%08X\r\n",fp100s, imageParamsR[P_FPSLM], imageParamsW[P_FPSLM], imageParamsR[P_FP100S],  imageParamsW[P_FP100S]));
02919 
02920  }
02922 int program_sensor_exposition_just(void) {
02923         int res = -1;
02924         adjust_fps_2_compressor();
02925         switch(imageParamsR[P_SENSOR] & SENSOR_MASK) {
02926 //#ifdef CONFIG_ETRAX_ELPHEL_KAI11000
02927         case SENSOR_KAI11000:
02928         res=1; 
02929         break; // senosor exposition
02930 //#endif
02931 #ifdef CONFIG_ETRAX_ELPHEL_ZR32112
02932         case SENSOR_ZR32112: break;
02933 #endif
02934 #ifdef CONFIG_ETRAX_ELPHEL_ZR32212
02935         case SENSOR_ZR32212: break;
02936 #endif
02937 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
02938         case SENSOR_KAC1310: break; // FIXME
02939 #endif
02940 #ifdef CONFIG_ETRAX_ELPHEL_KAC1310
02941         case SENSOR_KAC5000: break; // FIXME
02942 #endif
02943 #ifdef CONFIG_ETRAX_ELPHEL_MT9X001
02944         case SENSOR_MT9X001: //0x30..0x33
02945         case SENSOR_MT9Y001: //0x34..0x37
02946                 res = program_exposure_mt9x001();
02947                 break;
02948 #endif
02949 #ifdef CONFIG_ETRAX_ELPHEL_IBIS51300
02950         case SENSOR_KAC5000: break; // FIXME
02951 #endif
02952         } //switch
02953 //TODO:add to Exif
02954 //int putlong_meta(unsigned long data, int * indx,  unsigned long ltag); //write data to meta (4 bytes, big endian), from outside IRQ (atomic). Returns index of the written data, -1 if not written
02955 //   write_meta_irq(exif_meta_time_string, &meta_offsets.Image_DateTime,  Exif_Image_DateTime, 20); // may use 27 if room is provided
02956 //        frame_params.exposure=imageParamsR[P_EXPOS];
02957 //        putlong_meta(imageParamsR[P_EXPOS], &meta_offsets.Photo_ExposureTime,  Exif_Photo_ExposureTime);
02958         return res;
02959 }
02960 
02961 
02962 /* ======================================== Top level file operations =================================================================== */
02963 
02964 static int cmoscam_open(struct inode *inode, struct file *filp) {
02965         int p,res;
02966 
02967 
02968         p = MINOR(inode->i_rdev);
02969 //  printk("cmoscam_open: minor=%x\r\n",p);
02970    MD(printk("cmoscam_open: minor=%x\r\n",p));
02971      D1(printk("cmoscam_open: minor=%x\r\n",p) );
02972      D1(printk("filp=%lx\r\n",(unsigned long)filp) );
02973 //     if (init_FPGA()<0) return -EACCES;
02974 
02975         switch ( p ) {
02976         case  CMOSCAM_MINOR_HISTOGRAM :
02977          {
02978               if (minors[p]) {
02979                printk("***** Attemped to open twice CMOSCAM_MINOR_HISTOGRAM *****\n");
02980                return -EACCES;
02981            }
02982            break;
02983          }
02984         case  CMOSCAM_MINOR_RWTABLES :
02985          {
02986               if (minors[p]) {
02987                printk("***** Attemped to open twice CMOSCAM_MINOR_RWTABLES *****\n");
02988                return -EACCES;
02989            }
02990            break;
02991          }
02992         case  CMOSCAM_MINOR_GAMMA :
02993          {
02994               if (minors[p]) {
02995                printk("***** Attemped to open twice CMOSCAM_MINOR_GAMMA *****\n");
02996                return -EACCES;
02997            }
02998            gamma_tables_changed=0;
02999            break;
03000          }
03001 #ifdef CONFIG_ETRAX_323         
03002         case  CMOSCAM_MINOR_SENSORJTAGFPGA :
03003          {
03004 // for KAI11000 development - disable sensor init (that "open" should be before any attemts to find/init sensor)
03005            port_csp0_addr[X313_WA_SDCH0_CTL2]=0x8000; // sensor will be considered initialized
03006            ccamCROr( X313_BITS(KAI11000,1)); //just shadow, no real fpga reg yet
03007            if (minors[p])  {
03008               printk("***** Attemped to open CMOSCAM_MINOR_SENSORJTAGFPGA w/o closing\n");
03009            }
03010            if ((res =sfjtag_open())) return res;
03011            break;
03012          }  
03013 #endif          
03014                 case  CMOSCAM_MINOR_FRAME: {
03015                         if(init_FPGA() < 0)
03016                                 return -EACCES;
03017                         if(minors[p]) {
03018                                 printk("***** Attemped to open CMOSCAM_MINOR_FRAME w/o closing\n");
03019 //                              return -EACCES; // maybe different number - channel in use
03020                         }
03021                         if((res = x313_frame_open(inode, filp)))
03022                                 return res;
03023                         break;      
03024                 }
03025 
03026         case  CMOSCAM_MINOR_LOCK :
03027          {
03028            if (minors[p]) {
03029                printk("***** Attemped to access locked camera *****\n");
03030                return -EACCES;  // maybe different number - channel in use
03031            }
03032            break;      
03033          }
03034 
03035         case  CMOSCAM_MINOR_UNLOCK :
03036          {
03037            minors[CMOSCAM_MINOR_LOCK]=0;
03038            break;      
03039          }
03040 
03041 
03042         case  CMOSCAM_MINOR_FPN :
03043          {
03044            if (minors[p]) {
03045                printk("***** Attemped to open CMOSCAM_MINOR_FPN w/o closing\n");
03046 //               return -EACCES;        // maybe different number - channel in use
03047 
03048            }
03049            if ((res =x313_fpn_open(inode, filp))) return res;
03050           break;      
03051          }
03052         case CMOSCAM_MINOR_I2C :
03053           {
03054            if (minors[p])  return -EACCES;      // maybe different number - channel in use
03055            break;
03056           }
03057         case CMOSCAM_MINOR_DMA :
03058           {
03059 // bypass  cmoscam_open_dma() to avoid calculating chain when compressor is still running in "run" mode
03060             if (((res=getCamSeqState())==CAMSEQ_RUN) || (res == CAMSEQ_STOP)) inode->i_size=0;
03061             else if ((res =cmoscam_open_dma(inode, filp))) return res;
03062             break;      
03063           }
03064         case CMOSCAM_MINOR_MCP :
03065           {
03066             if (init_FPGA()<0) return -EACCES;
03067             if (CCAM_DONOTUSEAUX) return -EACCES;
03068             if ((minors[p]) && ((ccam_cr_shadow & X313_MASK(XRST)) != 0))  return -EACCES;
03069             if ((res =MCP_open(inode, filp))) return res;
03070             break;      
03071           }
03072         case CMOSCAM_MINOR_CIRCBUF :
03073           {
03074  //           if ((res =x313_circbuf_open(inode, filp))) return res;
03075             break;
03076           }
03077         case CMOSCAM_MINOR_JPEAGHEAD :
03078           {
03079 //            if ((res =x313_jpeghead_open(inode, filp))) return res;
03080             break;
03081           }
03082         case CMOSCAM_MINOR_SENSPARS : // for now - no checks, always possible to open
03083           {
03084             break;
03085           }
03086 
03087         default: return -EINVAL;
03088         }
03089 
03090         minors[p]=p;
03091 
03092         filp->private_data = &minors[p];
03093 
03094 
03095 
03096         return 0;
03097 }
03098 static int cmoscam_release(struct inode *inode, struct file *filp) {
03099  int p = MINOR(inode->i_rdev);
03100  int i=0;
03101    MD(printk("cmoscam_release: minor=%x\r\n",p));
03102         switch ( p ) {
03103 #ifdef CONFIG_ETRAX_323
03104         case  CMOSCAM_MINOR_SENSORJTAGFPGA :
03105           {
03106             i=sfjtag_close();
03107             printk("sfjtag_close returned %x\r\n",i);
03108             if (i>0) i=0;
03109             minors[p]=0;
03110             break;
03111           }  
03112 #endif
03113         case  CMOSCAM_MINOR_GAMMA :
03114           if (gamma_tables_changed) write_gamma_fpga (gamma_tables_soft);
03115           gamma_tables_changed=0;
03116           minors[p]=0;
03117           break;
03118         case  CMOSCAM_MINOR_FPN :
03119           x313_fpn_release();
03120         case  CMOSCAM_MINOR_HISTOGRAM :
03121         case  CMOSCAM_MINOR_RWTABLES :
03122         case CMOSCAM_MINOR_I2C :
03123         case CMOSCAM_MINOR_MCP :
03124         case CMOSCAM_MINOR_LOCK :
03125         case CMOSCAM_MINOR_UNLOCK :
03126 //        case CMOSCAM_MINOR_CIRCBUF :      
03127          {
03128            minors[p]=0;
03129            break;
03130          }
03131         case CMOSCAM_MINOR_FRAME: {
03132                         x313_frame_release();
03133                         minors[p]=0;
03134                         break;
03135                 }
03137         case CMOSCAM_MINOR_SENSPARS :
03138         case CMOSCAM_MINOR_DMA :
03139         case CMOSCAM_MINOR_CIRCBUF : 
03140         case CMOSCAM_MINOR_JPEAGHEAD :
03141          {
03142            break;
03143          }
03144         default: return -EINVAL;
03145         }
03146 
03147    D(printk("cmoscam_release:  done\r\n"));
03148    return i;
03149 }
03150 
03151 
03152 
03153 static int cmoscam_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { // switch by minor
03154         int rv;
03155 //   MD(printk("cmoscam_ioctl cmd= %x, arg= %x\n\r",cmd,arg));
03156 //   MD(printk("cmoscam_ioctl:  ((int *)filp->private_data)[0]= %x\n\r",((int *)filp->private_data)[0]));
03157 //   MD(printk("cmoscam_ioctl:   (int)  filp->private_data= %x\n\r",(int)filp->private_data));
03158 
03159           switch (((int *)filp->private_data)[0]) {
03160 
03161           case CMOSCAM_MINOR_I2C : return i2c_ioctl (inode, filp, cmd, arg);
03162           case CMOSCAM_MINOR_DMA :  
03163             if (init_FPGA()<0) return -EACCES; // test if programmed, on first call will init
03164           case  CMOSCAM_MINOR_SENSPARS :
03165           case  CMOSCAM_MINOR_MCP :     // do the same (just to check status)
03166           case  CMOSCAM_MINOR_FPN :     // do the same
03167           case  CMOSCAM_MINOR_FRAME :   // do the same
03168           case  CMOSCAM_MINOR_CIRCBUF :  // do the same
03169           case  CMOSCAM_MINOR_JPEAGHEAD : { // do the same
03170                  rv= ccam_DMA_ioctl(inode, filp, cmd, arg);
03171                  return rv;     
03172                 }
03173           default:return -EINVAL;
03174           }
03175 }
03176 
03177 static loff_t cmoscam_lseek(struct file * file, loff_t offset, int orig) {
03178      int i;
03179      switch (((int *)file->private_data)[0]) {
03180        case CMOSCAM_MINOR_GAMMA     : return  x313_gamma_lseek  (file, offset, orig);
03181        case CMOSCAM_MINOR_HISTOGRAM : return  x313_histogram_lseek  (file, offset, orig);
03182        case CMOSCAM_MINOR_RWTABLES :  return  x313_tables_lseek  (file, offset, orig);
03183        case CMOSCAM_MINOR_MCP :       return  MCP_lseek          (file, offset, orig);
03184        case CMOSCAM_MINOR_FPN :       return  x313_fpn_lseek     (file, offset, orig);
03185        case CMOSCAM_MINOR_FRAME :     return  x313_frame_lseek   (file, offset, orig);
03186        case CMOSCAM_MINOR_DMA :{
03187           if ( (((i=getCamSeqState()))== CAMSEQ_RUN   ) ||
03188                (i                     == CAMSEQ_STOP  ) ||
03189                (i                     == CAMSEQ_SINGLE)) return 0; // for waiting ready
03190           return  x313_dma_lseek     (file, offset, orig);
03191        }   
03192 //       case CMOSCAM_MINOR_CIRCBUF :    return  x313_circbuf_lseek (file, offset, orig);
03193 //       case CMOSCAM_MINOR_JPEAGHEAD :  return  x313_jpeghead_lseek (file, offset, orig);
03194        case CMOSCAM_MINOR_SENSPARS :   return  x313_senspars_lseek (file, offset, orig);
03195        default:                      return -EINVAL;
03196      }
03197 }
03198 
03199 static ssize_t cmoscam_read(struct file * file, char * buf, size_t count, loff_t *off) {
03200 // printk("cmoscam_read: ((int *)file->private_data)[0]= %x\r\n",((int *)file->private_data)[0]);
03201     switch (((int *)file->private_data)[0]) {
03202        case CMOSCAM_MINOR_GAMMA     :    return  x313_gamma_read     (file, buf, count, off);
03203        case CMOSCAM_MINOR_HISTOGRAM:     return  x313_histogram_read (file, buf, count, off);
03204        case CMOSCAM_MINOR_RWTABLES :     return  x313_tables_read    (file, buf, count, off);
03205        case CMOSCAM_MINOR_MCP :          return  MCP_read            (file, buf, count, off);
03206        case CMOSCAM_MINOR_FPN :          return  x313_fpn_read       (file, buf, count, off);
03207        case CMOSCAM_MINOR_FRAME :        return  x313_frame_read     (file, buf, count, off);
03208        case CMOSCAM_MINOR_DMA :          return  x313_dma_read       (file, buf, count, off);
03209 //       case CMOSCAM_MINOR_CIRCBUF :      return  x313_circbuf_read   (file, buf, count, off);
03210 //       case CMOSCAM_MINOR_JPEAGHEAD :    return  x313_jpeghead_read  (file, buf, count, off);
03211        case CMOSCAM_MINOR_SENSPARS :     return  x313_senspars_read  (file, buf, count, off);
03212        default:                          return -EINVAL;
03213     }
03214 }
03215 static ssize_t cmoscam_write(struct file * file, const char * buf, size_t count, loff_t *off) {
03216 // printk("cmoscam_write: ((int *)file->private_data)[0]= %x\r\n",((int *)file->private_data)[0]);
03217     switch (((int *)file->private_data)[0]) {
03218        case CMOSCAM_MINOR_GAMMA:          return  x313_gamma_write   (file, buf, count, off);
03219        case CMOSCAM_MINOR_RWTABLES:       return  x313_tables_write  (file, buf, count, off);
03220 #ifdef CONFIG_ETRAX_323
03221        case CMOSCAM_MINOR_SENSORJTAGFPGA: return  sfjtag_write       (file, buf, count, off);
03222 #endif
03223        case CMOSCAM_MINOR_MCP :           return  MCP_write          (file, buf, count, off);
03224        case CMOSCAM_MINOR_FPN :           return  x313_fpn_write     (file, buf, count, off);
03225        case CMOSCAM_MINOR_DMA :           return  x313_dma_write     (file, buf, count, off);
03226 //       case CMOSCAM_MINOR_CIRCBUF :       return  x313_circbuf_write (file, buf, count, off);
03227        case CMOSCAM_MINOR_JPEAGHEAD :     return  x313_dma_write     (file, buf, count, off); // same as other - write header
03228        case CMOSCAM_MINOR_SENSPARS :      return  x313_senspars_write(file, buf, count, off);
03229        default:                           return -EINVAL;
03230     }
03231 
03232 }
03233 
03234 
03235 static int cmoscam_mmap (struct file *file, struct vm_area_struct *vma) {
03236     switch (((int *)file->private_data)[0]) {
03237        case  CMOSCAM_MINOR_SENSPARS :   return  x313_senspars_mmap   (file, vma);
03238        default:                         return -EINVAL;
03239     }
03240 }
03241 static unsigned int cmoscam_poll (struct file *file, poll_table *wait) {
03242     switch (((int *)file->private_data)[0]) {
03243        case  CMOSCAM_MINOR_DMA :
03244             
03245             break;
03246        case  CMOSCAM_MINOR_CIRCBUF :
03248             if(imageParamsR[P_CIRCBUFWP]==file->f_pos) poll_wait(file, &x313_wait_queue, wait);
03249             if(imageParamsR[P_CIRCBUFWP]==file->f_pos) return 0;
03250     }
03251     return POLLIN | POLLRDNORM;
03252 }
03257 
03258 //#define P_TRIG_CONDITION 102 // trigger condition, 0 - internal, else dibits ((use<<1) | level) for each GPIO[11:0] pin
03259 //#define P_TRIG_DELAY     103 // trigger delay, 32 bits in pixel clocks
03260 //#define P_TRIG_OUT       104 // trigger output to GPIO, dibits ((use << 1) | level_when_active). Bit 24 - test mode, when GPIO[11:10] are controlled by other internal signals
03261 //#define P_TRIG_PERIOD    105 // output sync period (32 bits, in pixel clocks). 0- stop. 1..256 - single, >=256 repetitive with specified period.
03262 //  #define X313_WA_CAMSYNCTRIG 0x78 // trigger condition, 0 - internal, else dibits ((use<<1) | level) for each GPIO[11:0] pin
03263 //  #define X313_WA_CAMSYNCDLY  0x79 // trigger delay, 32 bits in pixel clocks
03264 //  #define X313_WA_CAMSYNCOUT  0x7a // trigger output to GPIO, dibits ((use << 1) | level_when_active). Bit 24 - test mode, when GPIO[11:10] are controlled by other internal signals
03265 //  #define X313_WA_CAMSYNCPER  0x7b // output sync period (32 bits, in pixel clocks). 0- stop. 1..256 - single, >=256 repetitive with specified period.
03266 
03267 void  program_trigger(void) {
03268    port_csp0_addr[X313_WA_CAMSYNCTRIG]=(imageParamsR[P_TRIG_CONDITION]=imageParamsW[P_TRIG_CONDITION]);
03269    port_csp0_addr[X313_WA_CAMSYNCDLY] =(imageParamsR[P_TRIG_DELAY]=    imageParamsW[P_TRIG_DELAY]);
03270    port_csp0_addr[X313_WA_CAMSYNCOUT] =(imageParamsR[P_TRIG_OUT]=      imageParamsW[P_TRIG_OUT]);
03271    port_csp0_addr[X313_WA_CAMSYNCPER] =(imageParamsR[P_TRIG_PERIOD]=   imageParamsW[P_TRIG_PERIOD]);
03272 }
03273 
03274 
03275 void  program_i2c(void) {
03276    if ((imageParamsW[P_I2C_QPERIOD]<256) && (imageParamsW[P_I2C_QPERIOD]> 2)) imageParamsR[P_I2C_QPERIOD]=imageParamsW[P_I2C_QPERIOD];
03277    if ((imageParamsW[P_I2C_BYTES]<3) && (imageParamsW[P_I2C_BYTES]>=0))       imageParamsR[P_I2C_BYTES]=imageParamsW[P_I2C_BYTES];
03278    port_csp0_addr[X313_I2C_CMD]=X3X3_SET_I2C_BYTES(imageParamsR[P_I2C_BYTES]+1) | X3X3_SET_I2C_DLY(imageParamsR[P_I2C_QPERIOD]) ;
03279   MD20(printk ("program_i2c (0x%x)\n",X3X3_SET_I2C_BYTES(imageParamsR[P_I2C_BYTES]+1) | X3X3_SET_I2C_DLY(imageParamsR[P_I2C_QPERIOD])));
03280 }
03281 
03282 void  program_smart_irq(void) {
03283    imageParamsR[P_IRQ_SMART]=imageParamsW[P_IRQ_SMART];
03284    port_csp0_addr[X313_WA_SMART_IRQ]=(2 | ((imageParamsR[P_IRQ_SMART] & 1)?1:0)) | \
03285                                      (8 | ((imageParamsR[P_IRQ_SMART] & 2)?4:0));
03286 }
03287 
03288 void  program_early_timestamp(void) {
03289    imageParamsR[P_EARLY_TIMESTAMP]=imageParamsW[P_EARLY_TIMESTAMP]?1:0;
03290    if (imageParamsR[P_EARLY_TIMESTAMP]) CCAM_TIMESTAMP_EARLY ;
03291    else                                 CCAM_TIMESTAMP_NORMAL ;
03292 }
03293 
03294 
03295 int flush_par_cache(void) {
03296 //P_MAX_PAR
03297   int sum, i;
03298   sum=0;
03299   for (i=0;i<=P_MAX_PAR; i+=8) sum+=ccam_dma_buf_ptr[i]+ccam_dma_buf_ptr[i+P_NUMBER]+ccam_dma_buf_ptr[i+(PAGE_SIZE>>2)]+ccam_dma_buf_ptr[i+P_NUMBER+(PAGE_SIZE>>2)];
03300   return sum;
03301 }
03302 loff_t x313_senspars_lseek(struct file * file, loff_t offset, int orig) {
03303   int l=(P_NUMBER<<3); //4 * P_NUMBER * 2 bytes
03304 
03305   switch (orig)
03306   {
03307    case SEEK_SET:
03308      file->f_pos = offset;
03309      break;
03310    case SEEK_CUR:
03311      file->f_pos += offset;
03312      break;
03313    case SEEK_END:
03314      if (offset <= 0) {
03315         file->f_pos = l + offset;
03316      } else switch (offset) { 
03317 //imageParamsR[P_SENSOR]=0;
03318 //cris_flush_cache()
03320        case LSEEK_RESET_SENSOR:
03321          X313_CHN0_SET_UNUSED;
03322          imageParamsR[P_SENSOR]=0;
03323          return 0; // not fall through to init sensor
03324        case LSEEK_INIT_SENSOR:
03325          if  (imageParamsR[P_SENSOR]) return 0; 
03326          init_FPGA();
03327          return 0;
03328        case LSEEK_CAMSEQSTATE:
03329          return (file->f_pos=camSeqState); 
03330        case LSEEK_GET_FPGA_TIME:
03331          X313_GET_FPGA_TIME( imageParamsR[P_SECONDS] , imageParamsR[P_MICROSECONDS] );
03332          return 0;
03333        case LSEEK_SET_FPGA_TIME:
03334          X313_SET_FPGA_TIME( imageParamsW[P_SECONDS] , imageParamsW[P_MICROSECONDS] );
03335          return 0;
03336        case  LSEEK_FLUSH_CACHE:            
03337          flush_par_cache();
03338          return 0;
03339        case  LSEEK_AUTOEXP_SET:
03340          set_autoexposure_parameters(); 
03341          return 0;
03342        case  LSEEK_AUTOEXP_GET:
03343          get_autoexposure_parameters(); 
03344          return 0;
03345        case  LSEEK_TRIGGER_PGM:
03346          program_trigger();
03347          return 0;
03348        case  LSEEK_I2C_PGM:
03349          program_i2c();
03350          return 0;
03351        case  LSEEK_IRQ_SMART_PGM:
03352          program_smart_irq();
03353          return 0;
03354        case  LSEEK_EARLY_TIMESTAMP_PGM:
03355          program_early_timestamp();
03356          return 0;
03357        default:
03358          return (x313_JPEG_cmd_wrapper(offset)<0)?-EINVAL:0;
03359      }
03360      break;
03361    default:
03362      return -EINVAL;
03363   }
03364   // truncate position
03365   if (file->f_pos < 0) {
03366     file->f_pos = 0;
03367     return(-EOVERFLOW);
03368   }
03369   if (file->f_pos > l) {
03370     file->f_pos = l;
03371   }
03372   return ( file->f_pos );
03373 }
03374 
03375 ssize_t x313_senspars_read(struct file * file, char * buf, size_t count, loff_t *off) {
03376   unsigned long p;
03377   int l=(P_NUMBER<<3); //4 * P_NUMBER * 2 bytes
03378   char *  imageParamsRb= (char *)   imageParamsR;
03379   p = file->f_pos;
03380   if( (p + count) > l) { // truncate count
03381     count = l - p;
03382   }
03383   if (count && (copy_to_user(buf, & imageParamsRb[p], count)))
03384           {printk("copy_to_user1 (0x%x) error\n",(int) count);return -EFAULT;}
03385 
03386   file->f_pos+=count;
03387   return count;
03388 }
03389 // both first and second half will write to imageParamsW (but not in a single call)
03390 ssize_t x313_senspars_write(struct file * file, const char * buf, size_t count, loff_t *off) {
03391   unsigned long flags; 
03392 
03393   unsigned long p,p0;
03394   int l=(P_NUMBER<<2); //4 * P_NUMBER bytes
03395   char *  imageParamsWb= (char *)   imageParamsW;
03396   D(printk("x313_senspars_write, count= %x\n", (int) count));
03397   p = file->f_pos;
03398   if (p >= (l<<1))  p = (l<<1);
03399   p0=p;
03400   if (p0 >= l) p0-=l;
03401   if( (p0 + count) > l) { // truncate count
03402     count = l - p0;
03403   }
03404   D(printk("x313_senspars_write, p=%x, p0=%x, count= %x\n", (int) p, (int) p0, (int) count));
03405 
03406   if (count) {
03407     if (copy_from_user(&imageParamsWb[p0],buf, count)) return -EFAULT;
03408     file->f_pos+=count;
03409                 if ((count==4) && (p0==(P_UPDATE<<2))) { 
03410       local_irq_save(flags);
03411       //local_irq_disable();
03412       if (imageParamsW[P_UPDATE]) imageParamsR[P_UPDATE]=2;     // waiting to be updated
03413       else imageParamsR[P_UPDATE]=0; // will not be updated
03414       local_irq_restore(flags);
03415       if (imageParamsW[P_UPDATE]==1) programSensor(0); 
03416       else if (imageParamsW[P_UPDATE]>=3) programSensor(1); 
03417     }
03418   }
03419   return count;
03420 }
03421 
03422 int x313_senspars_mmap (struct file *file, struct vm_area_struct *vma) {
03423      int rslt;
03424    /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
03425      rslt=remap_pfn_range(vma,
03426              vma->vm_start,
03427 //             ((unsigned long)(&imageParamsR[0])) >> PAGE_SHIFT,
03428              ((unsigned long) virt_to_phys(imageParamsR)) >> PAGE_SHIFT,
03429              vma->vm_end-vma->vm_start,
03430              vma->vm_page_prot);
03431 
03432      MD6(printk("remap_pfn_range returned=%x\r\n",rslt));
03433      if (rslt) return -EAGAIN;
03434 //   vma->vm_ops = &simple_remap_vm_ops;
03435 //   simple_vma_open(vma);
03436      return 0;
03437 }
03438 
03439 static int x313_JPEG_cmd_wrapper(int arg) {
03440                switch (arg) {
03441 MD6(printk("IO_CCAM_JPEG cmd=0x%x arg=0x%x\r\n", cmd,arg)); //never got here???
03442              case PROGRAM_SENSOR_0: imageParamsR[P_PARS_CHANGED]=1; programSensor(0); return 0;
03443              case PROGRAM_SENSOR_1: imageParamsR[P_PARS_CHANGED]=1; programSensor(1); return 0;
03444              case JPEG_CMD_N_DONE: return (JPEG_nfr >0)?0:1;
03445              case JPEG_CMD_L_DONE: return (JPEG_len < JPEG_lfr )?0:1;
03446              case JPEG_CMD_DUMP: camSeq_dump (); // and fall to default
03447              default: {return x313_JPEG_cmd(arg);}
03448           }
03449 }
03450 
03451 static int ccam_DMA_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg) {
03452 //      struct timeval tv;
03453 //  unsigned char i2cdata[2];
03454   unsigned long flags;
03455           int i1,r;
03456 
03457 //MD(printk("_IOC_NR(cmd)=%lx\n", _IOC_NR(cmd)));
03458 //MD1(printk("_IOC_NR(cmd)=%lx, arg=%lx\n", _IOC_NR(cmd),arg));
03459       switch(_IOC_NR(cmd)){
03460       case IO_CCAM_DMA : switch (arg) {
03461                case CCAM_DMA_CMD_STOP:  {x313_dma_stop(); return 0;}
03462                case CCAM_DMA_CMD_START: {x313_dma_start();return 0;}
03463                default:return -EINVAL ;
03464           }
03465       case IO_CCAM_JPEG_QUALITY: {
03466             if (arg <1)   arg=1;
03467             if (arg >100) arg=100;
03468             imageParamsR[P_QUALITY]=arg;
03469             imageParamsW[P_QUALITY]=arg;
03470             return 0;
03471       }
03472       case IO_CCAM_JPEG_GET_N: {
03473             if (getCamSeqState() != CAMSEQ_JPEG) x313_dma_update_jpeg_header(); // needed only first time
03474             return camSeqStartClip(arg, -1); // any length, 1 frame
03475       }
03476       case IO_CCAM_JPEG_GET_L: {
03477             if (getCamSeqState() != CAMSEQ_JPEG) x313_dma_update_jpeg_header(); // needed only first time
03478             return camSeqStartClip(-1, arg); // any numer, this length
03479       }
03480           case IO_CCAM_JPEG:  return x313_JPEG_cmd_wrapper(arg);
03481 #if 0
03482   switch (arg) {
03483 MD6(printk("IO_CCAM_JPEG cmd=0x%x arg=0x%x\r\n", cmd,arg)); //never got here???
03484              case JPEG_CMD_N_DONE: return (JPEG_nfr >0)?0:1;
03485              case JPEG_CMD_L_DONE: return (JPEG_len < JPEG_lfr )?0:1;
03486              case JPEG_CMD_DUMP: camSeq_dump (); // and fall to default
03487              default: {return x313_JPEG_cmd(arg);}
03488           }
03489 #endif
03490           case IO_CCAM_JPEG_CTRL: { x313_JPEG_ctrl(arg); return 0;}
03491 
03492           case IO_CCAM_MONITOR_SEQ : {
03493 MD( printk("IO_CCAM_MONITOR_SEQ, arg=%x,getCamSeqCount()=%x, getCamSeqState()=%x\r\n",(int) arg, (int) getCamSeqCount(),(int) getCamSeqState()));
03494             if (arg) return  getCamSeqCount();
03495 // update image read page
03496             if (((r=getCamSeqState())==CAMSEQ_DONE) && (imageParamsR[P_PAGE_ACQ]!= imageParamsR[P_PAGE_READ])) {
03497               x313_f_invalidate();  // SDRAM line in buffer is not valid anymore
03498 MD1(printk ("imageParamsR[P_PAGE_READ]=0x%lx, imageParamsR[P_PAGE_ACQ]=0x%lx\n",imageParamsR[P_PAGE_READ],imageParamsR[P_PAGE_ACQ]));
03499               imageParamsR[P_PAGE_READ] = imageParamsR[P_PAGE_ACQ];
03500             }
03501             return r;
03502          }
03503           case IO_CCAM_SET_EXT_EXPOSURE : {
03504     MD1(printk("+OBSOLETE?+IO_CCAM_SET_EXT_EXPOSURE, arg=%x\r\n",(int) arg));
03505          if (arg) camSeqStart(); 
03506          else {camSeqStop();
03507          }
03508              return 0;
03509            }
03510           case IO_CCAM_CR_MODIFY : {
03511       local_irq_save(flags);
03512       //local_irq_disable();
03513                 i1=((ccam_cr_shadow & (1<<(arg>>2)))!=0);
03514                 switch (arg & 3) {
03515                   case 1: {ccam_cr_shadow &= ~(1<<(arg>>2));break;}
03516                   case 2: {ccam_cr_shadow |=  (1<<(arg>>2));break;}
03517                   case 3: {ccam_cr_shadow ^=  (1<<(arg>>2));break;}
03518                 }
03519                 port_csp0_addr[X313_WA_WCTL]= ccam_cr_shadow;
03520                 local_irq_restore(flags);
03521 MD(printk("ccam_cr_shadow=0x%x\n",ccam_cr_shadow));
03522                 return i1;
03523            }
03524           case IO_CCAM_PINS_WRITE : {
03525 //              i1 = arg & 0x3FFF;
03526                 i1 = arg;
03527       local_irq_save(flags);
03528       //local_irq_disable();
03529                 port_csp0_addr[X313_WA_IOPINS] = i1;
03530                 local_irq_restore(flags);
03531 MD(printk("write_iopins=0x%x\n", i1));
03532                 return i1;
03533            }
03534           case IO_CCAM_PINS_READ : {
03535       local_irq_save(flags);
03536       //local_irq_disable();
03537 //              i1=port_csp0_addr[X313__RA__IOPINS] & 0x3F;
03538 //              i1=port_csp0_addr[X313__RA__IOPINS];
03539       i1=X313_IOPINS; 
03540                 local_irq_restore(flags);
03541 MD(printk("read_iopins=0x%x\n", i1));
03542                 return i1;
03543            }
03544         }
03545 MD(printk("CCAM_CTRL(cmd)=%lx\n", CCAM_CTRL(cmd)));
03546 
03547         switch(CCAM_CTRL(cmd)){
03548 // read (abstract) sensor parameters 0..63
03549     case CCAM_RPARS:{
03550 
03551  MD(printk("CCAM_RPARS: imageParamsR[%lx]=%lx\n",CCAM_ADDR(cmd),imageParamsR[CCAM_ADDR(cmd)]));
03552 
03553           return  imageParamsR[CCAM_ADDR(cmd)];
03554         }
03555 
03556 //  write (abstract) sensor parameters 0..63  (if [P_UPDATE] is off)
03557 //      trigger update if necessary
03558     case CCAM_WPARS: {
03559      if (CCAM_ADDR(cmd) == P_UPDATE) {
03560 // MD(printk("CCAM_ADDR(cmd) == P_UPDATE\n"));
03561 //do_gettimeofday(&tv);
03562 //printk("CCAM_ADDR(cmd) == P_UPDATE; %d:%d\r\n", tv.tv_sec, tv.tv_usec);
03563        if (imageParamsR[P_UPDATE] == 3)  return -EINVAL ; // too late to abort... TODO: support waiting, change error code
03564        local_irq_save(flags);
03565        //local_irq_disable();
03566 //       imageParamsW[P_UPDATE]= (arg>2)? 2: arg;
03567        imageParamsW[P_UPDATE]= arg; // now 3 - update "on the fly" - only some parameters
03568        if (imageParamsW[P_UPDATE]) imageParamsR[P_UPDATE]=2;    // waiting to be updated
03569        else imageParamsR[P_UPDATE]=0; // will not be updated
03570        local_irq_restore(flags);
03571        if (imageParamsW[P_UPDATE]==1) return programSensor(0); 
03572        if (imageParamsW[P_UPDATE]>=3) return programSensor(1); 
03573 // add an option with "nonstop" (1)      
03574        return 0;
03575      } else { //P_UPDATE / normal write
03576        if (imageParamsR[P_UPDATE]>1) {
03577  MD(printk("*****No write permitted if update is schedulled\n"));
03578              return -EINVAL ; // no write permitted if update is schedulled. TODO: Change error code
03579        }
03580        imageParamsR[P_PARS_CHANGED] |=  (imageParamsW[CCAM_ADDR(cmd)]!=arg);
03581        imageParamsW[CCAM_ADDR(cmd)]=arg;
03582  MD(printk("writing: imageParamsW[%lx]=%lx\n",CCAM_ADDR(cmd),arg));
03583        return 0;
03584      }
03585    } //CCAM_WPARS
03586 
03587     default:return -EINVAL ;
03588   }
03589 
03590 
03591 }
03592 
03593 // file r/w operations for the FPGA tables - move to a separate file later
03594 
03595 // use static buffer, so will not work with simultaneous accesses (naturally fpga also has just one set of tables)
03596  
03598 //#define CX313_FPGA_TABLES_SIZE 0x800 //=2000 bytes, 32-bit wide, LSB first, some tables use less
03599 //#define CX313_FPGA_TABLES_GAMMA 0x400 //0x400 words gamma-correction (or arbitrary table)
03600 
03601 unsigned long fpga_tables_buffer[CX313_FPGA_TABLES_SIZE];
03602 // now tables will store 257 corner points (currently - 10 bits). FPGA specifics will be calculated by the driver
03603 // and written to fpga when closing the file. The shadow array will be available for reading too.
03604 //unsigned short gamma_tables_soft[1028];
03605 //int gamma_tables_changed;
03606 // called from driver space or when closing (if it was written)
03607 int write_gamma_fpga (unsigned short gamma_table[1028]) {
03608   int i,n,base,diff,d;
03609 printk("\nwrite_gamma_fpga()\n");
03610 
03611   port_csp0_addr[X313_WA_COMP_TA]=CX313_FPGA_TABLES_GAMMA;
03612   for (n=0;n<4;n++) {
03613     for (i=0;i<256;i++) {
03614      base=gamma_table[257*n+i];
03615      diff=gamma_table[257*n+i+1];
03616      diff-=base;
03617      if ((diff>63) || (diff < -64)) {
03618        diff=(diff+8)>>4;
03619        d=(base & 0x3ff) | ((diff & 0x7f) << 10) | (1 << 17);
03620      } else {
03621        d=(base & 0x3ff) | ((diff & 0x7f) << 10);
03622      }
03623      port_csp0_addr[X313_WA_COMP_TD]=d;  // 18-bit data, will autoincrement address
03624     }
03625   }
03626   port_csp0_addr[X313_WA_COMP_TA] = CX313_FPGA_TABLES_GAMMA; // there is a one write pipeline, any write to fpga to actually do the last write to 
03627 
03628   gamma_tables_changed=0;
03629   return 0;
03630 }
03631 
03632 void x313_tables_gammainitlinear(void) {
03633   int i,j;
03634   for (j=0; j<4; j++) {
03635     for (i = 0; i <= 256; i+=1) {
03636       gamma_tables_soft[257*j+i]=4*i;
03637     }  
03638     gamma_tables_soft[257*j+256]=1023;
03639   }  
03640   gamma_tables_changed=1;
03641   write_gamma_fpga(gamma_tables_soft);
03642 
03643 }
03644 
03645 loff_t  x313_gamma_lseek(struct file * file, loff_t offset, int orig){
03646  //  orig 0: position from begning of eeprom
03647  //  orig 1: relative from current position
03648  //  orig 2: position from last eeprom address
03649 // printk("x313_gamma_lseek\n");
03650 
03651   int l;
03652   l=(1028<<1);
03653 
03654   switch (orig)
03655   {
03656    case 0:
03657      file->f_pos = offset;
03658      break;
03659    case 1:
03660      file->f_pos += offset;
03661      break;
03662    case 2:
03663      file->f_pos = l + offset;
03664      break;
03665    default:
03666      return -EINVAL;
03667   }
03668   // truncate position
03669   if (file->f_pos < 0) {
03670     file->f_pos = 0;
03671     return(-EOVERFLOW);
03672   }
03673   if (file->f_pos > l) {
03674     file->f_pos = l;
03675   }
03676   return ( file->f_pos );
03677 }
03678 
03679 //unsigned short gamma_tables_soft[1028];
03680 //int gamma_tables_changed;
03681 // will read just from shadow buffer
03682 ssize_t x313_gamma_read(struct file * file, char * buf, size_t count, loff_t *off) {
03683   unsigned long p;
03684   char *  gamma_tables_char= (char *)   gamma_tables_soft;
03685   D(printk("x313_gamma_read\n"));
03686   p = file->f_pos;
03687   
03688   if( (p + count) > (1028 << 1)) { // truncate count
03689     count = (1028 << 1) - p;
03690   }
03691   if (count && (copy_to_user(buf, &gamma_tables_char[p], count)))
03692           {printk("copy_to_user1 (0x%x) error\n",(int) count);return -EFAULT;}
03693 
03694   file->f_pos+=count;
03695   return count;
03696 }
03697 
03698 ssize_t x313_gamma_write(struct file * file, const char * buf, size_t count, loff_t *off) {
03699   unsigned long p;
03700   char *  gamma_tables_char= (char *)   gamma_tables_soft;
03701   D(printk("x313_gamma_write, count= %x\n", (int) count));
03702   p = file->f_pos;
03703   if (p >= (1028 << 1))  p = (1028 << 1);
03704   if( (p + count) > (1028 << 1)) { // truncate count
03705     count = (1028 << 1) - p;
03706   }
03707   D(printk("x313_gamma_write, p=%x, count= %x\n", (int) p,(int) count));
03708 
03709   if (count) {
03710 
03711     if (copy_from_user(&gamma_tables_char[p],buf, count)) return -EFAULT;
03712     file->f_pos+=count;
03713     gamma_tables_changed=1;
03714   }
03715   return count;
03716 }
03717 
03718 loff_t  x313_tables_lseek(struct file * file, loff_t offset, int orig){
03719  //  orig 0: position from begning of eeprom
03720  //  orig 1: relative from current position
03721  //  orig 2: position from last eeprom address
03722 // make it always stop DMA (needed?)
03723 
03724   int l;
03725   l=(CX313_FPGA_TABLES_SIZE<<2);
03726 
03727   switch (orig)
03728   {
03729    case 0:
03730      file->f_pos = offset;
03731      break;
03732    case 1:
03733      file->f_pos += offset;
03734      break;
03735    case 2:
03736      file->f_pos = l + offset;
03737      break;
03738    default:
03739      return -EINVAL;
03740   }
03741 
03742   // truncate position
03743   if (file->f_pos < 0) {
03744     file->f_pos = 0;
03745     return(-EOVERFLOW);
03746   }
03747 
03748 
03749   if (file->f_pos > l) {
03750     file->f_pos = l;
03751   }
03752   return ( file->f_pos );
03753 }
03754 
03755 
03756 ssize_t x313_tables_write(struct file * file, const char * buf, size_t count, loff_t *off) {
03757   unsigned long flags;
03758   unsigned long p;
03759   char * fpga_tables_char= (char *)  fpga_tables_buffer;
03760   int sa,l,i;
03761   D(printk("x313_tables_write, count= %x\n", (int) count));
03762   p = file->f_pos;
03763   if (p >= (CX313_FPGA_TABLES_SIZE<<2))  p = (CX313_FPGA_TABLES_SIZE<<2);
03764   if( (p + count) > (CX313_FPGA_TABLES_SIZE<<2)) { // truncate count
03765     count = (CX313_FPGA_TABLES_SIZE<<2) - p;
03766   }
03767   D(printk("x313_tables_write, p=%x, count= %x\n", (int) p,(int) count));
03768 
03769   if (count) {
03770 
03771     if (copy_from_user(&fpga_tables_char[p],buf, count)) return -EFAULT;
03772     file->f_pos+=count;
03773     sa= p>>2;
03774     l=count>>2;
03775     local_irq_save(flags);
03776     //local_irq_disable();
03777     port_csp0_addr[X313_WA_COMP_TA]=sa; // open fpga for writing table(s)
03778     for (i = 0; i < l; i++) {
03779         port_csp0_addr[X313_WA_COMP_TD]=fpga_tables_buffer[sa++];       // will autoincrement address
03780     }    
03781     port_csp0_addr[X313_WA_COMP_TA]=sa; // there is a one write pipeline, any write to fpga to actually do the last write to table
03782     local_irq_restore(flags);
03783   }
03784   return count;
03785 }
03786 
03787 
03788 
03789 
03790 ssize_t x313_tables_read(struct file * file, char * buf, size_t count, loff_t *off) {
03791   unsigned long sa,p;
03792 //  unsigned long l,i;
03793   char * fpga_tables_char= (char *)  fpga_tables_buffer;
03794 
03795   D(printk("x313_tables_read\n"));
03796   p = file->f_pos;
03797   sa=p>>2;
03798   
03799   if( (p + count) > (CX313_FPGA_TABLES_SIZE<<2)) { // truncate count
03800     count = (CX313_FPGA_TABLES_SIZE<<2) - p;
03801   }
03802   if (count && (copy_to_user(buf, &fpga_tables_char[p], count)))
03803           {printk("copy_to_user1 (0x%x) error\n",(int) count);return -EFAULT;}
03804 
03805   file->f_pos+=count;
03806   return count;
03807 }
03808 
03809 //---------------------------------------------------------
03810 #define CX313_FPGA_HISTOGRAM_SIZE 0x400 //=0x1000 bytes, 32-bit wide, LSB first
03811 
03812 loff_t  x313_histogram_lseek(struct file * file, loff_t offset, int orig){
03813  //  orig 0: position from begning of eeprom
03814  //  orig 1: relative from current position
03815  //  orig 2: position from last eeprom address
03816 // make it always stop DMA (needed?)
03817 // printk("x313_histogram_lseek\n");
03818 
03819   int l;
03820   l=(CX313_FPGA_HISTOGRAM_SIZE<<2);
03821 
03822   switch (orig)
03823   {
03824    case 0:
03825      file->f_pos = offset;
03826      break;
03827    case 1:
03828      file->f_pos += offset;
03829      break;
03830    case 2:
03831      file->f_pos = l + offset;
03832      break;
03833    default:
03834      return -EINVAL;
03835   }
03836 
03837   // truncate position
03838   if (file->f_pos < 0) {
03839     file->f_pos = 0;
03840     return(-EOVERFLOW);
03841   }
03842 
03843 
03844   if (file->f_pos > l) {
03845     file->f_pos = l;
03846   }
03847   return ( file->f_pos );
03848 }
03849 
03850 //  #define   X313_WA_HIST_POS  0x40
03851 //  #define   X313_WA_HIST_SIZE 0x41
03852 //  #define   X313_WA_HIST_ADDR 0x42
03853 //  #define   X313_RA_HIST_DATA 0x43  // use CSP4 with wait cycles to have a pulse
03854 
03855 
03856 ssize_t x313_histogram_read(struct file * file, char * buf, size_t count, loff_t *off) {
03857   unsigned long sa,p,l,i;
03858   int    histogram_buffer[1024];
03859   char *  histogram_buffer_char= (char *)   histogram_buffer;
03860 
03861   D(printk("x313_histogram_read\n"));
03862 //  printk("x313_histogram_read\n");
03863   p = file->f_pos;
03864   sa=p>>2;
03865   
03866   if( (p + count) > (CX313_FPGA_HISTOGRAM_SIZE<<2)) { // truncate count
03867     count = (CX313_FPGA_HISTOGRAM_SIZE<<2) - p;
03868   }
03869   l=((p+count-1)>>2)-sa+1; // number of 32-bit s to read
03870   port_csp0_addr[X313_WA_COMP_TA]=sa;  
03871   for (i=0;i<l;i++) {
03872     port_csp0_addr[X313_WA_HIST_ADDR]=sa;
03873     X3X3_AFTERWRITE ; 
03874     fpga_tables_buffer[sa++]=port_csp4_addr[X313_RA_HIST_DATA];
03875   }
03876   
03877   if (count && (copy_to_user(buf, &histogram_buffer_char[p], count)))
03878           {printk("copy_to_user1 (0x%x) error\n",(int) count);return -EFAULT;}
03879 
03880   file->f_pos+=count;
03881   return count;
03882 }
03883 
03884 
03885 
03886 void init_autoexp_struct(void) {
03887   autoexp_state = (struct autoexp_t *)      &imageParamsR[P_AUTOEXP];
03888   autoexp_set=    (struct autoexp_t *)      &imageParamsW[P_AUTOEXP];
03889   aexp_window=    (struct aexp_window_t * ) &imageParamsR[P_AEXPWND];
03890   aexp_window_set=(struct aexp_window_t * ) &imageParamsW[P_AEXPWND];
03891 }
03892 
03893 //---------------------------------------------------------
03894 
03895 /* this makes sure that cmoscam_init is called during boot */
03896 
03897 module_init(cmoscam_init);
03898 MODULE_LICENSE("GPL");
03899 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
03900 MODULE_DESCRIPTION(MY_MODULE_DESCRIPTION);
03901 MODULE_DESCRIPTION("Elphel  Model 353 camera driver");
03902 /****************** END OF FILE cc353.c ********************************/
03903 
03904 

Generated on Thu Aug 7 16:18:59 2008 for elphel by  doxygen 1.5.1