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

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : cxdma353.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: cxdma353.c,v $
00021 *!  Revision 1.8  2008/04/20 06:49:40  elphel
00022 *!  cleanup, bug fixes
00023 *!
00024 *!  Revision 1.7  2008/04/16 20:33:23  elphel
00025 *!  driver cleanup, removed some duplicate actions, working on better recovery after parameter modification
00026 *!
00027 *!  Revision 1.6  2008/02/08 16:36:03  spectr_rain
00028 *!  access to quantization tables from the streamer
00029 *!
00030 *!  Revision 1.5  2007/12/09 05:59:13  elphel
00031 *!  added cache_flush fix
00032 *!
00033 *!  Revision 1.4  2007/12/03 08:28:46  elphel
00034 *!  Multiple changes, mostly cleanup
00035 *!
00036 *!  Revision 1.3  2007/11/04 05:39:11  elphel
00037 *!  removed declaration of unused variable
00038 *!
00039 *!  Revision 1.2  2007/10/11 06:40:33  elphel
00040 *!  Added second RESET command with non-zero value to be compatible with lseek (,,SEEK_END)
00041 *!
00042 *!  Revision 1.1.1.1  2007/10/02 19:36:10  elphel
00043 *!  This is a fresh tree based on elphel353-2.10
00044 *!
00045 *!  Revision 1.17  2007/10/02 19:36:10  elphel
00046 *!  removed unneeded debug output
00047 *!
00048 *!  Revision 1.16  2007/09/30 07:07:27  elphel
00049 *!  only disabled debug output
00050 *!
00051 *!  Revision 1.15  2007/09/30 03:19:56  elphel
00052 *!  Cleanup, fixed broken acquisition of individual JPEG images into circbuf (in mode 7)
00053 *!
00054 *!  Revision 1.14  2007/09/29 18:33:29  elphel
00055 *!  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
00056 *!
00057 *!  Revision 1.13  2007/09/23 06:45:10  elphel
00058 *!  Restored ccam_dma.raw character device file - it was broken when EXIF headers were added, so I just returned it to the previous state (no Exif, but works)
00059 *!
00060 *!  Revision 1.12  2007/09/05 10:32:40  spectr_rain
00061 *!  reformatting and debug messages
00062 *!
00063 *!  Revision 1.11  2007/08/31 21:47:01  spectr_rain
00064 *!  *** empty log message ***
00065 *!
00066 *!  Revision 1.10  2007/08/28 21:25:28  spectr_rain
00067 *!  mmap for JPEG files
00068 *!
00069 *!  Revision 1.9  2007/08/17 10:23:18  spectr_rain
00070 *!  switch to GPL3 license
00071 *!
00072 *!  Revision 1.8  2007/08/01 18:56:33  spectr_rain
00073 *!  *** empty log message ***
00074 *!
00075 *!  Revision 1.7  2007/08/01 15:12:45  spectr_rain
00076 *!  *** empty log message ***
00077 *!
00078 *!  Revision 1.6  2007/07/20 10:17:44  spectr_rain
00079 *!  *** empty log message ***
00080 *!
00081 *!  Revision 1.2  2007/03/29 23:38:15  spectr_rain
00082 *!  fix mmap
00083 *!
00084 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00085 *!  initial import into CVS
00086 *!
00087 *!  Revision 1.5  2007/01/08 17:22:39  spectr_rain
00088 *!  *** empty log message ***
00089 *!
00090 *!  Revision 1.4  2006/12/28 15:12:15  spectr_rain
00091 *!  *** empty log message ***
00092 *!
00093 *!  Revision 1.3  2006/08/29 18:06:58  spectr_rain
00094 *!  6.5.2
00095 *!
00096 *!  Revision 1.1.1.1  2006/07/11 19:15:00  spectr_rain
00097 *!  unwork with less than 5MPx Micron sensor, initial branch
00098 *!
00099 *!  Revision 1.4  2006/04/16 00:18:09  elphel
00100 *!  added timestamps to frame data in circbuf (streamers are not yet updated)
00101 *!
00102 *!  Revision 1.3  2006/02/22 09:06:46  elphel
00103 *!  Made ccam.cgi return last image from the buffer when streamer is running. Same as acquiring image, with "-" in the options, i.e. "admin-bin/ccam.cgi?opt=vhcxy-" (all parameters will be ignored)
00104 *!
00105 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00106 *!  *** empty log message ***
00107 *!
00108 */
00109 
00110 /****************** INCLUDE FILES SECTION ***********************************/
00111 
00112 
00113 #include <linux/module.h>
00114 #include <linux/mm.h>
00115 #include <linux/sched.h>
00116 #include <linux/slab.h>
00117 #include <linux/errno.h>
00118 #include <linux/kernel.h>
00119 #include <linux/fs.h>
00120 #include <linux/string.h>
00121 #include <linux/init.h>
00122 #include <linux/autoconf.h>
00123 #include <linux/time.h>
00124 
00125 #include <asm/system.h>
00126 #include <asm/arch/memmap.h>
00127 #include <asm/io.h>
00128 
00129 #include <asm/arch/dma.h>
00130 #include <asm/arch/hwregs/dma_defs.h>
00131 #include <asm/arch/hwregs/dma.h>
00132 #include <asm/arch/hwregs/reg_map.h>
00133 #include <asm/arch/hwregs/bif_dma_defs.h>
00134 
00135 
00136 #include <asm/irq.h>
00137 #include <asm/atomic.h>
00138 
00139 #include <asm/delay.h>
00140 #include <asm/uaccess.h>
00141 #include <asm/arch/cache.h> 
00142 
00143 #include <asm/elphel/c313a.h>
00144 
00145 #include "fpgactrl.h"  // defines port_csp0_addr, port_csp4_addr 
00146 
00147 #include "x3x3.h"
00148 #include "cc3x3.h"
00149 #include "cxdma.h"
00150 #include "circbuf.h"
00151 #include "exif.h"
00152 
00153 #if ELPHEL_DEBUG
00154  #define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00155  #define MD12(x) printk("%s:%d:",__FILE__,__LINE__);x
00156   //#define MD12(x)
00157  #define MD13(x) printk("%s:%d:",__FILE__,__LINE__);x
00158   //#define MD13(x)
00159 #else
00160   #define MD1(x)
00161   #define MD12(x)
00162   #define MD13(x)
00163 #endif
00164 
00165 
00166 
00167 #define D(x)
00168 #define D1(x)
00169 //#define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00170 //#define MD1(x)
00171 #define MD2(x) printk("%s:%d:",__FILE__,__LINE__);x
00172 //#define MD2(x)
00173 
00174 //#define MD5(x) printk("%s:%d:",__FILE__,__LINE__);x
00175 #define MD5(x)
00176 //#define MD6(x) printk("%s:%d:",__FILE__,__LINE__);x
00177 #define MD6(x)
00178 //#define MD7(x) printk("%s:%d:",__FILE__,__LINE__);x
00179 #define MD7(x)
00180 
00181 //#define D0(x) printk("%s:%d:",__FILE__,__LINE__);x
00182 #define D0(x)
00183 
00184 //#define MD8(x) printk("%s:%d:",__FILE__,__LINE__);x
00185 #define MD8(x)
00186 //#define MD9(x) printk("%s:%d:",__FILE__,__LINE__);x
00187 #define MD9(x)
00188 //#define MD10(x) printk("%s:%d:",__FILE__,__LINE__);x
00189 #define MD10(x)
00191 //#define MD11(x) printk("%s:%d:",__FILE__,__LINE__);x
00192 #define MD11(x)
00193 
00194 
00195 //#define PRINTQTAB y
00196 
00197 
00198 #ifdef CONFIG_ETRAX_ELPHEL353
00199   #define EXT_DMA_0_START \
00200    do { reg_bif_dma_rw_ch3_start c = {.run=1};\
00201         REG_WR(bif_dma, regi_bif_dma, rw_ch3_start, (reg_bif_dma_rw_ch3_start) c); } while( 0 )
00202   #define EXT_DMA_0_STOP \
00203    do { reg_bif_dma_rw_ch3_start c = {.run=0};\
00204         REG_WR(bif_dma, regi_bif_dma, rw_ch3_start, (reg_bif_dma_rw_ch3_start) c); } while( 0 )
00205 #else
00206   #define EXT_DMA_0_START \
00207    *R_EXT_DMA_0_CMD = (extdma0_cmd_shadow |=    IO_STATE( R_EXT_DMA_0_CMD, run, start ) )
00208   #define EXT_DMA_0_STOP \
00209    *R_EXT_DMA_0_CMD = (extdma0_cmd_shadow &=    ~IO_MASK( R_EXT_DMA_0_CMD, run ) )
00210 #endif
00211 /*
00212 len <0, nfr>0 - acquire nfr frames, no length restrictions
00213 len =0, nfr>0 - acquire nfr frames, unchanged length restriction
00214 len >0, nfr>0 - acquire nfr frames, set new length restriction
00215 len >0, nfr <0 - acquire unlimited number of frames, only total length restriction
00216 len >0, nfr =0 - do not change number of frames to acquire, update total length restriction
00217 len =0, nfr =0 - reread from memory (if was off)
00218 len <0, nfr =0 - start constant compressing to buffer (only write pointer is updated
00219 len =0, nfr <0 - stop constant compressing to buffer (wait for CAMSEQ_DONE)
00220 
00221 int camSeqStartClip(int nfr, int len);
00222 int  camSeqGetJPEG_wp(void);
00223 int  camSeqGetJPEG_rp(void);
00224 void camSeqSetJPEG_rp(int p);
00225 */
00226 
00227 
00228 
00229 
00230 //#define JPEG_STARTED  (*R_DMA_CH5_CMD)
00231 //#define JPEG_FINISHED ((port_csp0_addr[X313__RA__STATUS] & 0xc0000) == 0xc0000)
00232 //#define JPEG_BUSY     (JPEG_STARTED && !(JPEG_FINISHED))
00233 
00234 //#define UPDATE_JPEG if ((JPEG_STARTED) && (JPEG_FINISHED)) {printk ("status=%x, JPEG_FINISHED=%x\n",(int) port_csp0_addr[X313__RA__STATUS],JPEG_FINISHED);x313_dma_stop(); }
00235 //#define UPDATE_JPEG if ((JPEG_STARTED) && (JPEG_FINISHED)) {x313_dma_stop(); }
00236 
00237 //#define JPEG_HEADER_SIZE    0x26f
00238 #define TRAILER_SIZE        0x02
00239 #define HEADER_YQTABLE      0x19
00240 #define HEADER_CQTABLE      0x5e
00241 
00242 #define HEADER_HEIGHT       0xa3
00243 #define HEADER_WIDTH        0xa5
00244 
00245 /* really huge static DMA buffer (1288+8)*1032/3=445824 long-s */
00246 // DMA_SIZE - in 32-bit words, not bytes
00254 extern struct frame_params_t frame_params; // cc353.c
00255 
00256 
00257 // it seems we could use a single data descriptor (in LX data segment was limited to 16KB), but let's have minimal changes
00258 #ifdef CONFIG_ETRAX_ELPHEL353
00259   #define DMA_CHUNK 0x4000 // 32-bit words - may increase??
00260 //  #define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE >> 14)+1) // number of data descriptors
00261   #define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE  / DMA_CHUNK) +1 ) // number of data descriptors
00262   static dma_descr_data    ccam_dma_descr_data    [CCAM_DESCR_DATA_NUM]  __attribute__ ((__aligned__(16)));
00263   static dma_descr_context ccam_dma_descr_context __attribute__ ((__aligned__(32)));
00264 
00265 #else
00266   #define DMA_CHUNK 0x4000 // 32-bit words
00267 //  #define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE >> 14)+1) // number of data descriptors
00268   #define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE  / DMA_CHUNK) +1 ) // number of data descriptors
00269   static etrax_dma_descr ccam_dma_descr_data[CCAM_DESCR_DATA_NUM];
00270   static unsigned long extdma0_cmd_shadow=0;
00271 
00272 #endif
00273 static unsigned char jpeg_header_sbuffer [JPEG_HEADER_SIZE];
00274 unsigned char *jpeg_header_sbuffer_ptr = NULL; // will be initialized to during DMA init &jpeg_header_sbuffer[0];
00275 static unsigned char trailer[TRAILER_SIZE] = {0xff,0xd9};
00276 static unsigned long DMABufferLength;
00277 
00278 //unsigned long *ccam_dma = &ccam_dma_buf_ptr[0];
00279 unsigned long ccam_dma_length = CCAM_DMA_SIZE << 2;
00280 //extern volatile atomic_t dma_update_mess_dis;
00281 //volatile atomic_t dma_update_mess_dis;
00282 //static        
00283 static   int             use_header=1;
00284 static   int             JPEG_ctrl= 0x2ff;
00285 
00286 int             jpeg_quality= -1;
00287 
00289 int             FPGA_quality=-1;
00291 int             JPEG_header_quality=-1;
00292 
00293 
00294 
00295 
00296 int      soft_rp;       // lower by 2 than the actual JPEG data - room for signature and length copy
00297 static   int     save_rp=-1;   // rp saved for two-pass clip processing
00298 static   int     save_wp=-1;    // to verify there was no acquisition after rp was saved
00299 
00300 
00301 
00302 void           x313_dma_reset_jpeg(void);
00303 int                 x313_dma_forget_jpeg(void);
00304 
00305 
00306 
00307 int  x313_dma_catchup_jpeg(void);
00308 //void           jpeg_set_quality (int quality, int writeFPGA);
00309 void           update_JPEG_quality (int quality);
00310 int            x313_setDMABuffer(void);
00311 unsigned long  x313_DMA_size (void);
00312 //int            x313_dma_start_jpeg(int now);
00313 void           x313_dma_update_jpeg_header(void); // uses channel 0 SDRAM FPGA settings - channel 0 should be programmed earlier
00314 
00315 void           x313_JPEG_dump (void);
00316 int            X313_dma_update(int latest); // new - latest <0 - build the longest chain
00317 void             x313_dma_reset_chain(void);
00318 int              x313_dma_save_jpeg(void);
00319 int              x313_dma_restore_jpeg(void);
00320 
00321 
00322 /*
00323 #define IO_CCAM_JPEG            0x0b // JPEG-compressor related commands
00324 #define      JPEG_CMD_RESET     0x00 // Resets pointers - both acquisition and readout
00325 #define      JPEG_CMD_ARM       0x01 // Prepare compressor to read next frame acquired
00326 #define      JPEG_CMD_GET       0x02 // Read current page (will return empty (and length==0) if not ready
00327 #define      JPEG_CMD_FORGET    0x03 // increment read frame pointer
00328 #define      JPEG_CMD_CATCHUP   0x04 // set read pointer to the last acquisition one
00329 #define      JPEG_CMD_ACQUIRE   0x05 // set read pointer to the last acquisition one
00330 JPEG_CMD_DUMP
00331             if (getCamSeqState() != CAMSEQ_JPEG) 313_dma_update_jpeg_header(); // needed only first time
00332             return camSeqStartClip(arg, -1); // any length, 1 frame
00333 
00334 */
00335 int x313_JPEG_ctrl(int cmd) {
00336         JPEG_ctrl= cmd & 0xffff;
00337         use_header = ((cmd & 0x10000) == 0);
00338         return 0;
00339 }
00340 
00341 int x313_get_JPEG_ctrl(void) {
00342         return JPEG_ctrl;
00343 }
00344 
00345 void prof_msg(const char *msg) {
00346         struct timeval tv;
00347         do_gettimeofday(&tv);
00348         printk("at %d:%06d: %s\n", (int)tv.tv_sec, (int)tv.tv_usec, msg);
00349 }
00350 
00351 int     x313_JPEG_cmd(int cmd) {
00352         MD5(printk ("JPEG_cmd %x: aq=%x,rd=%x, ry=%x\n", cmd, acq_index, read_index, ready_index));
00353         MD6(printk ("JPEG_cmd %x\r\n", cmd));
00354         MD8(printk ("JPEG_cmd %x\r\n", cmd));
00355         MD11(printk ("JPEG_cmd %x, rp=0x%x, wp=0x%x\r\n", cmd,camSeqGetJPEG_rp(),camSeqGetJPEG_wp() ));
00356         switch(cmd) {
00357 //              case JPEG_CMD_ARM:    {return x313_dma_start_jpeg (0);}
00358                 case JPEG_CMD_GET: {
00359                         prof_msg("JPEG_CMD_GET\n");
00360                         camSeqStop(); // just in case, but it should be stopped
00361                         x313_dma_update_jpeg_header();
00362                         return camSeqStartClip(0, 0); // just read frame from memory
00363                 }
00364                 case JPEG_CMD_ACQUIRE: {
00365                         prof_msg("JPEG_CMD_ACQUIRE\n");
00366                         x313_dma_update_jpeg_header();
00367                         return camSeqStartClip(1, -1); // acquire one frame
00368                 }
00369                 case JPEG_CMD_RESET0:  // cmd==0x10
00370                 case JPEG_CMD_RESET:  { // cmd==0
00371                         prof_msg("JPEG_CMD_RESET\n");
00372                         x313_setDMABuffer(); 
00373                         x313_dma_reset_jpeg ();
00374                         return 0;
00375                 }
00376                 case JPEG_CMD_FORGET: {
00377                         prof_msg("JPEG_CMD_FORGET\n");
00378                         return x313_dma_forget_jpeg();
00379                 }
00380                 case JPEG_CMD_CATCHUP: {
00381                         prof_msg("JPEG_CMD_CATCHUP\n");
00382                         return x313_dma_catchup_jpeg();
00383                 }
00384                 case JPEG_CMD_DUMP: {
00385                         prof_msg("JPEG_CMD_DUMP\n");
00386                         x313_JPEG_dump();
00387                         return 0;
00388                 }
00389                 case JPEG_CMD_SAVE_RP:
00390                         prof_msg("JPEG_CMD_SAVE_RP\n");
00391                         return x313_dma_save_jpeg();
00392                 case JPEG_CMD_RESTORE_RP:
00393                         prof_msg("JPEG_CMD_RESTORE_RP\n");
00394                         return x313_dma_restore_jpeg();
00395 //#define      JPEG_CMD_START      0x0a // start constant compression mode
00396 //#define      JPEG_CMD_STOP       0x0b // stop constant compression mode (may want to wait for CAMSEQ_DONE)
00397                 case JPEG_CMD_START: {
00398                         prof_msg("JPEG_CMD_START\n");
00399                         x313_dma_update_jpeg_header();
00400                         return camSeqStartClip(0, -1); // start constant compression mode
00401                 }
00402                 case JPEG_CMD_STOP: {
00403                         prof_msg(" JPEG_CMD_STOP\n");
00404                         x313_dma_update_jpeg_header(); // needed if there was no start
00405                         return camSeqStartClip(-1, 0); // stop constant compression mode
00406                 }
00407                 case JPEG_CMD_JUST_STOP: {
00408                         prof_msg("JPEG_CMD_JUST_STOP\n");
00409                         return camSeqStartClip(-2, 0); // stop constant compression mode
00410                 }
00411                 case JPEG_CMD_FRAMES: {
00412                         prof_msg("JPEG_CMD_FRAMES\n");
00413                         return X313_dma_update(-1); // return number of frames in buffer
00414                 }
00415                 default:
00416                         return -1;
00417         }
00418 }
00419 
00420 // **************************************************************
00421 //#define X313_DMA_DICARD      8  // number of extra 32-bytes word attached to the data to be discarded (FIFO)
00423 #if 0
00424 #define X313_CHAIN_SIGNATURE  0xffffffff
00425 #define X313_CHAIN_SIGNATURE4 0xffff0000
00426 //#define X313_CHAIN_SIGNATURE4 0xffffffff
00427 #define X313_LENGTH_MASK      0xff000000
00428 
00429 #define X313_PADDED_FRAME(x)((((x)+67+CCAM_MMAP_META ) >>2) & 0xfffffff8)
00430 #define X313_BUFFSUB(x,y) (((x)>=(y))? ((x)-(y)) : ((x)+ (CCAM_DMA_SIZE-(y))))
00431 #define X313_BUFFADD(x,y) ((((x) + (y))<=CCAM_DMA_SIZE)? ((x) + (y)) : ((x) - (CCAM_DMA_SIZE-(y))))
00432 #endif
00433 
00445 int     x313_dma_save_jpeg(void) {
00446         save_rp = camSeqGetJPEG_rp();
00447         save_wp = camSeqGetJPEG_wp();
00448         return 0;
00449 }
00450 
00451 int     x313_dma_restore_jpeg(void) {
00452         if(save_wp == camSeqGetJPEG_wp()) {
00453                 camSeqSetJPEG_rp(save_rp);
00454                 soft_rp = X313_BUFFSUB(save_rp, 2);
00455                 return 0;
00456         }
00457         return -1;
00458 }
00462 void x313_dma_reset_chain(void) {
00463         soft_rp = CCAM_DMA_SIZE - 2;
00464         ccam_dma_buf_ptr[soft_rp] |= X313_CHAIN_SIGNATURE4;  // 0xffffxxxx if not overwritten
00465         ccam_dma_buf_ptr[soft_rp + 1] = X313_CHAIN_SIGNATURE;  // Data length (undefined)
00466         save_rp = -1;
00467         save_wp = -1;
00468 }
00469 
00475 void x313_dma_reset_jpeg(void) {
00476         camSeqStop();
00477         camSeqStop(); // if it was running, first one will stop, and second - buffer pointers
00478         x313_dma_reset_chain();
00479 }
00480 
00481 int     x313_dma_forget_jpeg(void) {
00482         int i = 0;
00483         unsigned long rp;
00484         if(((ccam_dma_buf_ptr[soft_rp] & X313_CHAIN_SIGNATURE4)!= X313_CHAIN_SIGNATURE4) || (ccam_dma_buf_ptr[soft_rp + 1] == X313_CHAIN_SIGNATURE)) // check only 2 bytes
00485                 i = X313_dma_update(0); // build length-ahead
00486         if(i == 0) {
00487                 soft_rp += X313_PADDED_FRAME(ccam_dma_buf_ptr[soft_rp + 1]);
00488                 if(soft_rp >= CCAM_DMA_SIZE)
00489                         soft_rp -= CCAM_DMA_SIZE;
00490                 rp = X313_BUFFADD(soft_rp, 2);
00491                 camSeqSetJPEG_rp(rp);
00492                 return rp; 
00493         }
00494         return -1;
00495 }
00496 
00497 //---- CATCHUP ----
00498 int     x313_dma_catchup_jpeg(void) {
00499         int i;
00500         i = X313_dma_update(1);
00501         if(i == 0)
00502                 return 0;
00503         return -1;
00504 }
00505 
00506 // new! (latest<0) - ignore rp and build the longest chain
00507 // new_new instead of (latest<0) - just rp<0!
00520 
00521 
00522 int X313_dma_update(int latest) { // builds forward references in acquired data
00523    int rp,p,p1; //,n;
00524    int nz=1;
00525    int nf=0; // number of frames in chain
00526    int rebuild=(latest<0);
00527    unsigned long l;
00528    unsigned long prev_l=0;
00529    MD1(printk("*** X313_dma_update(latest=%d) - modifies global RP, may interfere with imgsrv or other apps\n",latest));
00530 // MD2(printk("X313_dma_update(latest=%d)\n",latest));
00531    if(rebuild)
00532       rp = -1;
00533    else { // (latest>=0)
00534       rp = camSeqGetJPEG_rp();
00535       rebuild = (rp < 0); 
00536       if ((rebuild == 0) && (!latest)) {  
00537          soft_rp=X313_BUFFSUB(rp, 2);
00538          if(((ccam_dma_buf_ptr[soft_rp] & X313_CHAIN_SIGNATURE4) == X313_CHAIN_SIGNATURE4) &&
00539             (ccam_dma_buf_ptr[soft_rp + 1] != X313_CHAIN_SIGNATURE))
00540             return 0;  
00541       }
00542    }
00543 //Here rebuild (return number) or just rp is invalid - return 0/-error and point the latest/oldest
00544    if((p = camSeqGetJPEG_wp()) == rp)
00545       return -1; 
00546 
00547 // n = 1;
00548    camSeqSetJPEG_rp(p); 
00549    soft_rp = X313_BUFFSUB(p, 2);
00550  MD2(printk("p=0x%x, rp=0x%x, soft_rp=0x%x\n",p,rp,soft_rp));
00551    while(1) {
00552       l = (ccam_dma_buf_ptr[X313_BUFFSUB(p, 9)] ^ X313_LENGTH_MASK); 
00553       if (!prev_l) { 
00554          if((l & X313_LENGTH_MASK) == 0) { 
00555             p = X313_BUFFSUB(p, X313_PADDED_FRAME(l));
00556             prev_l = l;
00557          } else return  rebuild?0:-1; 
00558       } else { //not the WP
00559         if ((ccam_dma_buf_ptr[X313_BUFFSUB(p, 2)] & X313_CHAIN_SIGNATURE4) == X313_CHAIN_SIGNATURE4) { 
00560            camSeqSetJPEG_rp(p);
00561            soft_rp = X313_BUFFSUB(p, 2);
00562            nf++;
00563            if((latest > 0) || 
00564               (p == rp))  
00565               return 0;
00566            if((l & X313_LENGTH_MASK) == 0) { 
00567              p1 = p;
00568              p = X313_BUFFSUB(p, X313_PADDED_FRAME(l));
00569              if(p >= p1) {
00570                if((nz--) <= 0) { // twice went through circular buffer, - should not happen, just in case...
00571                   printk(" X313_dma_update: twice went through zero - overwritten p=%x, p1=%x\n", p, p1);
00572                   return rebuild ? nf : -1; // only software mark is present - head of frames chain
00573                }
00574              }
00575              prev_l = l;
00576            } else {
00577             return rebuild ? nf : (nf? 0 :-1); // only software mark is present - head of frames chain
00578            }
00579         } else { 
00580             return rebuild? nf : (nf? 0:-2); 
00581         }
00582      } // not the WP
00583   }
00584 }
00585 
00586 
00587 
00588 
00589 unsigned long t_sign = 0;
00590 
00591 // Here attempt to get size of "bad" buffer will rebuild the chain, but if it will still be empty - will stick forever
00592 unsigned long x313_DMA_size(void) {     // will return 0 if DMA is enabled and not over. If over, will flush and stop it
00593         int i = 0;
00594         // trying to prevent getting old frame from the buffer if it address accidentally is the same as current write pointer  
00595 //      if((camSeqGetJPEG_rp() == camSeqGetJPEG_wp()) || (ccam_dma_buf_ptr[soft_rp] != X313_CHAIN_SIGNATURE) || (ccam_dma_buf_ptr[soft_rp + 1] == X313_CHAIN_SIGNATURE))
00596         if((camSeqGetJPEG_rp() == camSeqGetJPEG_wp()) || ((ccam_dma_buf_ptr[soft_rp] & X313_CHAIN_SIGNATURE4) != X313_CHAIN_SIGNATURE4) || (ccam_dma_buf_ptr[soft_rp + 1] == X313_CHAIN_SIGNATURE))
00597                 i = X313_dma_update(0); // build length-ahead
00598 //      printk("x313_DMA_size: X313_dma_update(0)returned 0x%x\n", i);
00599         if((i >= 0) && (ccam_dma_buf_ptr[soft_rp + 1] != X313_CHAIN_SIGNATURE)) {
00600                 t_sign = ccam_dma_buf_ptr[soft_rp + 1] + 0xFF000000;
00601                 return ccam_dma_buf_ptr[soft_rp + 1];
00602         }
00603 //      printk("x313_DMA_size got X313_dma_update(0) = %x\n", i); 
00604         return 0;
00605 }
00606 
00607 int x313_dma_stop(void) {
00608  MD12(printk("==========x313_dma_stop\n"));
00609         port_csp0_addr[X313_WA_DMACR] = 0;
00610         EXT_DMA_0_STOP ; // for testing - no reset DMA after acquisition
00611         udelay(10) ; //?
00612         DMA_RESET( regi_dma9 );
00613         // put here restoring of the .after pointer ?
00614         return 0;
00615 }
00616 
00617 void x313_dma_start(void) {
00618         unsigned long dai;
00619         int i = 0;
00620 
00621 //x313_dma_stop(); ///  testing if that will help
00622 
00623 
00624  MD12(printk("----------x313_dma_start\n"));
00625 
00626         DMA_RESET(regi_dma9);
00627         // need to restore pointers after previous stop DMA - maybe later move there?
00628         for(dai = 0; dai < CCAM_DMA_SIZE; dai += DMA_CHUNK) { // DMA_CHUNK==0x4000
00629                 if(dai + DMA_CHUNK >= CCAM_DMA_SIZE)  //last descriptor
00630                         ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[CCAM_DMA_SIZE]);
00631                 else  // not the last one
00632                         ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[dai + DMA_CHUNK]);
00634 //     flush_dma_descr((dma_descr_data*) & ccam_dma_descr_data[i], 0); //!We do not need dma descriptors, just reusing code Axis made already to fix a similar bug
00635        flush_dma_descr( & ccam_dma_descr_data[i], 0);
00636 
00637                 i++;
00638         }
00639         DMA_ENABLE(regi_dma9);
00640         port_csp0_addr[X313_WA_DMACR] = 0;
00641         // NOTE: needs to be here (not in x313_dma_init) - word width is reset by channel reset !!!
00642         DMA_WR_CMD(regi_dma9, regk_dma_set_w_size4);  //32-bit transfers
00643         // point to the beginning of the buffer?
00644         ccam_dma_descr_context.saved_data = (dma_descr_data*)virt_to_phys(&ccam_dma_descr_data[0]);
00645         ccam_dma_descr_context.saved_data_buf = ccam_dma_descr_data[0].buf;
00647    flush_dma_descr((dma_descr_data*) & ccam_dma_descr_context, 0);
00648 
00649         DMA_START_CONTEXT(regi_dma9, virt_to_phys(&ccam_dma_descr_context));
00650         EXT_DMA_0_START ;// updated
00651         port_csp0_addr[X313_WA_DMACR] = 0x30000;
00652         // enable DMA in JPEG mode - now it is always JPEG (no raw DMA mode) 
00653 }
00654 
00655 //Using external dma 3 (input) with dma channel 9 
00656 unsigned long x313_dma_init(void) {
00657         int rslt;
00659         jpeg_header_sbuffer_ptr = &jpeg_header_sbuffer[0];
00660         reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; //  if disabled - will be busy and hang on attemt of DMA_WR_CMD
00661         reg_bif_dma_rw_ch3_ctrl exdma_ctrl = {
00662                 .bw          = regk_bif_dma_bw32,
00663                 .burst_len   = regk_bif_dma_burst8, // changed - updated FPGA to use 8-word bursts
00664                 .cont        = 1,                   // continuous transfer mode (probably - don't care)
00665                 .end_discard = 0,                   // discard end of burst date (don't care)
00666                 .cnt         = 0,                   // transfer counter ignored
00667                 .dreq_pin    = 0,                   // use hsh0
00668                 .dreq_mode   = regk_bif_dma_norm,   // normal - active high DREQ from pin (see above)
00669                 .tc_in_pin   = 0,                   // don't care - tc pin number
00670                 .tc_in_mode  = 0,                   // no tc pin
00671                 .bus_mode    = regk_bif_dma_master, // bus mode - master
00672                 .rate_en     = 0                    // no rate limiting
00673         };
00674         reg_bif_dma_rw_ch3_addr exdma_addr = {.addr = MEM_CSR0_START | MEM_NON_CACHEABLE};
00675         reg_bif_dma_rw_pin0_cfg exdma_pin0 = {
00676                 .master_ch   = 0,                   // don't care
00677                 .master_mode = regk_bif_dma_off,    // off
00678                 .slave_ch    = 0,                   // don't care
00679                 .slave_mode  = regk_bif_dma_off     // off
00680         };
00681         reg_bif_dma_rw_pin1_cfg exdma_pin1 = {
00682                 .master_ch   = 3,                   // ext DMA channel #
00683                 .master_mode = regk_bif_dma_dack,   // use DACK, active high
00684                 .slave_ch    = 3,                   // don't care
00685                 .slave_mode  = regk_bif_dma_off     // off
00686         };
00687 //      atomic_set(&dma_update_mess_dis, 0); // atomic_set with value==0???
00688         // just in case - free DMA channel (we are only using it here)
00689         crisv32_free_dma(EXTDMA3_RX_DMA_NBR);
00690         printk("Initializing DMA registers for EXTDMA3 - ");
00691         MD7(printk("x313_dma_init(void)"));
00692 
00693         D0(printk ("before crisv32_request_dma\n");
00694         udelay (500000));
00695         rslt = crisv32_request_dma(EXTDMA3_RX_DMA_NBR,
00696                 "compressed data in from fpga",
00697                 DMA_VERBOSE_ON_ERROR,
00698                 0,
00699                 dma_ext3);
00700         D0(printk ("after crisv32_request_dma - result=%d\n",rslt);
00701         udelay(500000));
00702 
00703         if(rslt) {
00704                 printk("failed\n");
00705                 crisv32_free_dma(EXTDMA3_RX_DMA_NBR);
00706                 printk(KERN_CRIT "Can't allocate external dma port for compressed data in from fpga");
00707         } else { // dma channel 9 allocated for ext dma 3
00708                 // setup source of hsh0, shs1
00709                 REG_WR(bif_dma, regi_bif_dma, rw_pin0_cfg, exdma_pin0); // just in case - turn hsh0 off
00710                 REG_WR(bif_dma, regi_bif_dma, rw_pin1_cfg, exdma_pin1); // make hsh1 DACK
00711                 // Configure ext DMA 3
00712                 REG_WR(bif_dma, regi_bif_dma, rw_ch3_ctrl, exdma_ctrl);
00713                 REG_WR(bif_dma, regi_bif_dma, rw_ch3_addr, exdma_addr);
00714                 REG_WR(dma, regi_dma9, rw_cfg, cfg);    //  DMA configuration (bit 0 - enable, bit 1 - stop) - stopped
00715 /*
00716 #define DMA_WR_CMD( inst, cmd_par ) \
00717    do { reg_dma_rw_stream_cmd r = {0}; \
00718         do { r = REG_RD( dma, inst, rw_stream_cmd ); } while( r.busy ); \
00719         r.cmd = (cmd_par); \
00720         REG_WR( dma, inst, rw_stream_cmd, r ); \
00721       } while( 0 )
00722 */
00723 //   D0(do {reg_dma_rw_stream_cmd rr = REG_RD( dma, regi_dma9, rw_stream_cmd ); printk ("rr=0x%x\n", ((int *) &rr)[0]);} while (0); udelay (500000));
00724 // Not a safe command - if always busy - will silently hang forever ...
00725          // Set up wordsize = 4 bytes for DMAs.
00726 //     MD7(printk("Set up wordsize = 4 bytes for DMAs\n");
00727 //         DMA_WR_CMD (regi_dma9, regk_dma_set_w_size4);  //32-bit transfers
00728    // initialize static DMA descriptor list
00729 }
00730         DMABufferLength = 0;
00731         x313_setDMABuffer();
00732         x313_dma_reset_jpeg();
00733         return ((unsigned long)virt_to_phys(ccam_dma_buf_ptr)) | 0x80000000;
00734 }
00735 
00736 int x313_setDMABuffer(void) {
00737         unsigned long dai;
00738         int i = 0;
00739         // Stop DMA (just in case)
00740         EXT_DMA_0_STOP;
00741 //      ccam_dma_length = 0;
00742         for(dai = 0; dai < CCAM_DMA_SIZE; dai += DMA_CHUNK) { // DMA_CHUNK==0x4000
00743                 ccam_dma_descr_data[i].buf = (char *)virt_to_phys(&ccam_dma_buf_ptr[dai]);
00744 //              ((unsigned long) virt_to_phys (&ccam_dma_buf_ptr[dai]))   | 0x80000000;
00745                 ccam_dma_descr_data[i].intr = 0;
00746                 ccam_dma_descr_data[i].wait = 0;
00747                 ccam_dma_descr_data[i].eol = 0; // we probably do not need to use eol as the descriptors are linked in a loop anyway
00748                 if(dai + DMA_CHUNK >= CCAM_DMA_SIZE) { //last descriptor
00749                         ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[CCAM_DMA_SIZE]);
00750                         ccam_dma_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma_descr_data[0]);
00751                 } else { // not the last one
00752                         ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[dai + DMA_CHUNK]);
00753                         ccam_dma_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma_descr_data[i + 1]);
00754 //                      ccam_dma_length += 0x10000;
00755                 }
00756       flush_dma_descr( & ccam_dma_descr_data[i], 0);
00757                 i++;
00758         }
00759     set_imageParamsR(P_CIRCBUFSIZE,CCAM_DMA_SIZE<<2);
00760 // moved next 2 lines to x313_dma_start(void) 
00761 //  ccam_dma_descr_context.saved_data = (dma_descr_data*)virt_to_phys(&ccam_dma_descr_data[0]);
00762 //  ccam_dma_descr_context.saved_data_buf = ccam_dma_descr_data[0].buf;
00763 //*********************** TEMPORARY ********************************       
00764         MD8(printk ("filling DMA buffer with natural numbers - just test \n"));
00765         for(dai = 0; dai < CCAM_DMA_SIZE; dai++)
00766                 ccam_dma_buf_ptr[dai] = dai;
00767         return 0;
00768 }
00769 
00770 void x313_JPEG_dump(void) {
00771 //      int i;
00772         printk("port_csp0_addr[X313__RA__STATUS] = 0x%x\n", (int)port_csp0_addr[X313__RA__STATUS]);
00773 #if 0
00774    printk ("(*R_DMA_CH5_HWSW)=0x%x\n", (int) *R_DMA_CH5_HWSW);
00775    printk ("(*R_DMA_CH5_DESCR)=0x%x\n", (int) *R_DMA_CH5_DESCR);
00776    printk ("(*R_DMA_CH5_NEXT)=0x%x\n", (int) *R_DMA_CH5_NEXT);
00777    printk ("(*R_DMA_CH5_BUF)=0x%x\n", (int) *R_DMA_CH5_BUF);
00778    printk ("(*R_DMA_CH5_FIRST)=0x%x\n", (int) *R_DMA_CH5_FIRST);
00779    printk ("(*R_DMA_CH5_CMD)=0x%x\n", (int) *R_DMA_CH5_CMD);
00780    printk ("(*R_DMA_CH5_STATUS)=0x%x\n", (int) *R_DMA_CH5_STATUS);
00781 #endif
00782 #if 0
00783 typedef struct dma_descr_data {
00784   struct dma_descr_data        *next;
00785   char                         *buf;
00786   unsigned                      eol        : 1;
00787   unsigned                                 : 2;
00788   unsigned                      out_eop    : 1;
00789   unsigned                      intr       : 1;
00790   unsigned                      wait       : 1;
00791   unsigned                                 : 2;
00792   unsigned                                 : 3;
00793   unsigned                      in_eop     : 1;
00794   unsigned                                 : 4;
00795   unsigned                      md         : 16;
00796   char                         *after;
00797 } dma_descr_data;
00798 #endif
00799 #if 0
00800         printk("\nDMA desriptor table (buf,after,next\n");
00801         for(i=0; i < CCAM_DESCR_DATA_NUM; i++)
00802                 printk("%3x: %8x %8x %8x\n", i, (int)ccam_dma_descr_data[i].buf,
00803                         (int)ccam_dma_descr_data[i].after, 
00804                         (int)ccam_dma_descr_data[i].next);
00805 #endif
00806         printk("    use_header=  %x\n", use_header);
00807         printk("    JPEG_ctrl=   %x\n", JPEG_ctrl);
00808         printk("    jpeg_quality=%x\n", jpeg_quality);
00809         printk("    soft_rp=     %x\n", soft_rp);
00810         printk("    ccam_dma_buf_ptr[soft_rp]= %lx\n", ccam_dma_buf_ptr[soft_rp]);
00811         printk("    ccam_dma_buf_ptr[soft_rp+1]= %lx\n", ccam_dma_buf_ptr[soft_rp + 1]);
00812 }
00813 
00814 //  return (l<<2)+(use_header? (JPEG_HEADER_SIZE+TRAILER_SIZE)  : 0 );
00815 
00816 int cmoscam_open_dma(struct inode *inode, struct file *filp) { // set filesize
00817         int exif_len = exif_header_length();
00818         int exif_off = exif_len - EXIF_OFFSET;
00819         int header_size = JPEG_HEADER_SIZE + exif_off;
00820         int l;
00821         // avoid calculating size while compressor is running in constant mode (return 0) - do it in cc313.c
00822         l = x313_DMA_size();
00823 //      if ((l>0) && use_header) l += (JPEG_HEADER_SIZE + TRAILER_SIZE);
00824         if((l > 0) && use_header)
00825                 l += (header_size + TRAILER_SIZE);
00826         inode->i_size = l;
00827 //      inode->i_atime=0x7ffffff;
00828 //      inode->i_mtime=0x7ffffff;
00829 //      inode->i_ctime=0x7ffffff;
00830         return 0;
00831 }
00832 
00833 loff_t x313_dma_lseek(struct file * file, loff_t offset, int orig) {
00834         //  orig 0: position from begning of eeprom
00835         //  orig 1: relative from current position
00836         //  orig 2: position from last  address
00837         // make it always stop DMA (needed?)
00838         int exif_len = exif_header_length();
00839         int exif_off = exif_len - EXIF_OFFSET;
00840         int header_size = JPEG_HEADER_SIZE + exif_off;
00841 
00842         int l;
00843         l = x313_DMA_size();
00844 //      printk("from x313_dma_lseek: l == %d, ", l);
00845 //      if ((l>0) && use_header) l += (JPEG_HEADER_SIZE + TRAILER_SIZE);
00846         if((l > 0) && use_header)
00847                 l += (header_size + TRAILER_SIZE);
00848 //      printk("and with EXIF l == %d\r\n", l);
00849         switch(orig) {
00850         case 0:
00851                 file->f_pos = offset;
00852                 break;
00853         case 1:
00854                 file->f_pos += offset;
00855                 break;
00856         case 2:
00857                 file->f_pos = l + offset;
00858                 break;
00859         default:
00860                 return -EINVAL;
00861         }
00862 
00863         // truncate position
00864         if(file->f_pos < 0) {
00865                 printk("x313_dma_lseek: file->fpose - negative! l=%d\n",l);
00866                 printk("x313_dma_lseek orig=%d\n",orig);
00867                 file->f_pos = 0;
00868                 return(-EOVERFLOW);
00869         }
00870   
00871         if(file->f_pos > l) {
00872                 file->f_pos = l;
00873         }
00874         return( file->f_pos );
00875 }
00876 
00877 unsigned long cpu_to_le(unsigned long in) {
00878         unsigned long r = (in & 0xFF) << 24;
00879         r += (in & 0xFF00) << 8;
00880         r += (in & 0xFF0000) >> 8;
00881         r += (in & 0xFF00) >> 24;
00882         return r;
00883 }
00884 
00885 void get_image_exp(unsigned long *e) {
00886         *e = get_imageParamsR(P_EXPOS);
00887 //      printk("--==--> exposition time:\r\n");
00888 //      printk("get_imageParamsR(P_EXPOS) == %d\r\n", get_imageParamsR(P_EXPOS));
00889 //      printk("get_imageParamsW(P_EXPOS) == %d\r\n", get_imageParamsW(P_EXPOS));
00890 }
00891 
00892 static unsigned char ext_mjpeg_header[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
00893 
00894 /*
00895  * EXT_JPEG_MMAP
00896  */
00897 // mmap'ing functions
00898 /*
00899 unsigned long ext_jpeg_buf_ptr(void) {
00900         return (unsigned long)ccam_dma_buf_ptr;
00901 }
00902 
00903 unsigned long ext_jpeg_buf_length(void) {
00904         return CCAM_DMA_SIZE;
00905 }
00906 */
00907 unsigned long ext_make_jpeg_header(void);
00908 
00909 void ext_fill_jpeg_mmap_desc(struct ext_jpeg_mmap_desc_t *mdesc) {
00910 //      mdesc->jpeg_addr = PAGE_SIZE + ((X313_BUFFADD(soft_rp, 2)) << 2);
00911 //      mdesc->jpeg_addr = (unsigned long)((X313_BUFFADD(soft_rp, 2)) << 2) - (unsigned long)ccam_dma_buf_ptr;
00912         mdesc->jpeg_addr = ((X313_BUFFADD(soft_rp, 2)) << 2);
00913 //      mdesc->jpeg_addr = ((X313_BUFFADD(soft_rp, 2) - CCAM_DMA_SIZE) << 2);
00914 //      mdesc->jpeg_addr = 0;
00915 //printk("jpeg_addr (start offset) == 0x%08X, soft_rp == 0x%08X, offset == 0x%08X, offset_2 = 0x%08X\r\n", mdesc->jpeg_addr, soft_rp, (soft_rp + 2) << 2, (soft_rp + 2 - CCAM_DMA_SIZE) << 2);
00916         mdesc->jpeg_length = x313_DMA_size();
00917         mdesc->exif_length = ext_make_jpeg_header();
00918         mdesc->mmap_start = 0;
00919         mdesc->mmap_exif_length = PAGE_SIZE;
00920         mdesc->mmap_jpeg_length = CCAM_DMA_SIZE << 2;
00921 //printk("mmap: mmap_start: 0x%08X, mmap_exif_length: 0x%08X, mmap_jpeg_length: 0x%08X\n", mdesc->mmap_start, mdesc->mmap_exif_length, mdesc->mmap_jpeg_length);
00922 }
00923 
00924 void ext_fill_jpeg_mmap_desc_(struct _ext_jpeg_mmap_desc_t *mdesc) {
00925         mdesc->exif_start = (void *)&ext_mjpeg_header[0];
00926         mdesc->exif_length = PAGE_SIZE;
00927         mdesc->jpeg_start = (unsigned long *) ccam_dma_buf_ptr;
00928         mdesc->jpeg_length = CCAM_DMA_SIZE << 2;
00929 //printk("mmap: exif_start: 0x%08X, exif_length: 0x%08X, jpeg_start: 0x%08X, jpeg_length: 0x%08X\n", mdesc->exif_start, mdesc->exif_length, mdesc->jpeg_start, mdesc->jpeg_length);
00930 }
00931 
00932 // Create JPEG header (in mmap'ed area) with current EXIF fields and return length of JPEG header
00933 unsigned long ext_make_jpeg_header(void) {
00934         unsigned char *jpeg_header = ext_mjpeg_header;
00935         int exif_len = exif_header_length();
00936         int exif_off = exif_len - EXIF_OFFSET;
00937 //      int header_size = JPEG_HEADER_SIZE + exif_off + TRAILER_SIZE;
00938         int header_size = JPEG_HEADER_SIZE + exif_off;// + TRAILER_SIZE;
00939 
00940         unsigned long ne_exp[2];
00941         /* fill EXIF with current data */
00942         // get the length and pointer to memory
00943         memcpy(jpeg_header + exif_off, jpeg_header_sbuffer, JPEG_HEADER_SIZE);
00944         memcpy(jpeg_header, exif_header, exif_len);
00945         unsigned char *exif = jpeg_header;
00946         /* install EXIF items */
00947         memcpy(exif + EXIF_FIRMWARE, exif_desc.firmware, EXIF_FIRMWARE_LEN);
00948         memcpy(exif + EXIF_ARTIST, exif_desc.artist, EXIF_ARTIST_LEN);
00949         memcpy(exif + EXIF_DATE_TIME, exif_desc.date_time, EXIF_DATE_TIME_LEN);
00950         memcpy(exif + EXIF_DATE_TIME_OR, exif_desc.date_time_or, EXIF_DATE_TIME_OR_LEN);
00951         memcpy(exif + EXIF_SUBSEC_OR, exif_desc.subsec, EXIF_SUBSEC_OR_LEN);
00952         get_image_exp(&exif_desc.exp[0]);
00953         ne_exp[0] = cpu_to_le(exif_desc.exp[0]);
00954         ne_exp[1] = cpu_to_le(exif_desc.exp[1]);
00955         memcpy(exif + EXIF_EXP, ne_exp, EXIF_EXP_LEN);
00956 
00957         return header_size;
00958 }
00959 //#define EXIF y
00960 #ifdef EXIF
00961 ssize_t x313_dma_read(struct file * file, char * buf, size_t count, loff_t *off) {
00962         unsigned long p, l, i, left, l1;
00963         int rp;
00964         char *bp = buf;
00965 
00966         unsigned char jpeg_header[2048];
00967         int exif_len = exif_header_length();
00968         int exif_off = exif_len - EXIF_OFFSET;
00969         int header_size = JPEG_HEADER_SIZE + exif_off;
00970 //      unsigned char exif_desc.date_time[EXIF_DATE_TIME_LEN];
00971 
00972         D(printk("x313_dma_read\n"));
00973 //  x313_dma_stop();
00974 //      p = file->f_pos;
00975         p = *off;
00976 //      if((p + count) > ((l = x313_DMA_size()) + (use_header ? (JPEG_HEADER_SIZE + TRAILER_SIZE) : 0))) { // truncate count 
00977 //              count = l + (use_header ? (JPEG_HEADER_SIZE + TRAILER_SIZE) : 0) - p;
00978         if((p + count) > ((l = x313_DMA_size()) + (use_header ? (header_size + TRAILER_SIZE) : 0))) { // truncate count 
00979                 count = l + (use_header ? (header_size + TRAILER_SIZE) : 0) - p;
00980         }
00981         left = count;
00982 // read header (if needed)
00983         if(use_header) {
00984                 unsigned long ne_exp[2];
00985                 /* fill EXIF with current data */
00986                 // get the length and pointer to memory
00987                 memcpy(jpeg_header + exif_off, jpeg_header_sbuffer, JPEG_HEADER_SIZE);
00988                 memcpy(jpeg_header, exif_header, exif_len);
00989                 unsigned char *exif = jpeg_header;
00990                 /* install EXIF items */
00991                 memcpy(exif + EXIF_FIRMWARE, exif_desc.firmware, EXIF_FIRMWARE_LEN);
00992                 memcpy(exif + EXIF_ARTIST, exif_desc.artist, EXIF_ARTIST_LEN);
00993                 memcpy(exif + EXIF_DATE_TIME, exif_desc.date_time, EXIF_DATE_TIME_LEN);
00994                 memcpy(exif + EXIF_DATE_TIME_OR, exif_desc.date_time_or, EXIF_DATE_TIME_OR_LEN);
00995                 memcpy(exif + EXIF_SUBSEC_OR, exif_desc.subsec, EXIF_SUBSEC_OR_LEN);
00996                 get_image_exp(&exif_desc.exp[0]);
00997                 ne_exp[0] = cpu_to_le(exif_desc.exp[0]);
00998                 ne_exp[1] = cpu_to_le(exif_desc.exp[1]);
00999                 memcpy(exif + EXIF_EXP, ne_exp, EXIF_EXP_LEN);
01000 
01001                 if(p < header_size) {
01002                         i = left;
01003                         if(i > (header_size - p))
01004                                 i = header_size - p;
01005                         if(i && (copy_to_user(bp, &jpeg_header[p], i))) {
01006                                 printk("copy_to_user1 (0x%x) error\n",( int)i);
01007                                 return -EFAULT;
01008                         }
01009                         bp += i;
01010                         left -= i;
01011                         p = 0;
01012                 } else
01013                         p -= header_size;
01014         }  // if (use_header)
01015 
01016         if(left == 0) {
01017                 *off += count;
01018                 return count;
01019         }
01020 
01021         // copy image data itself - the buffer may be broken it two parts.
01022         if(p < l) {
01023 //              rp=soft_rp+2;if (rp>=CCAM_DMA_SIZE) rp-=CCAM_DMA_SIZE;
01024                 rp = X313_BUFFADD(soft_rp, 2);
01025                 MD9(printk("rp == 0x%08X; rp << 2 == 0x%08X\r\n", rp, rp << 2));
01026                 // part I - from the beginning read_index up...
01027                 l1 = ((CCAM_DMA_SIZE - rp) << 2);
01028                 if(l1 > l)
01029                         l1 = l;         
01030                 if(p < l1) {
01031                         i = left;
01032                         if(i > (l1 - p))
01033                                 i = l1 - p;
01034                         if(i && (copy_to_user(bp, ((char *) ccam_dma_buf_ptr) + (rp << 2)+ p, i))) {
01035                                 printk("copy_to_user2 (0x%x) error\n",(int) i);
01036                                 return -EFAULT;
01037                         }
01038 //printk("offset == 0x%08X\n", (rp << 2) + p - header_size);
01039                         bp += i;
01040                         left -= i;
01041                         p = 0;
01042                 } else
01043                         p -= l1;
01044                 // Part II - continue from the start of the DMA buffer
01045                 l -= l1;
01046                 if(p < l) {
01047                         i = left;
01048                         if(i > (l - p))
01049                                 i = l - p;
01050 //printk("offset == 0x%08X; 0x%08X\n", p - header_size, p);
01051                         if(i && (copy_to_user(bp, ((char *)ccam_dma_buf_ptr) + p, i))) {
01052                                 printk("copy_to_user3 (0x%x) error\n", (int)i);
01053                                 printk("soft_rp=0x%x\n", (int)soft_rp);
01054                                 printk("*off=0x%x\n", (int) *off);
01055                                 printk("count=0x%x, left=0x%x, l=0x%x, i=0x%x, p=0x%x\n", (int)count, (int)left, (int)l, (int)i, (int)p);
01056                                 return -EFAULT;
01057                         }
01058                         bp += i;
01059                         left -= i;
01060                         p = 0;
01061                 } else
01062                         p -= l;
01063         } else
01064                 p -= l; // pointer got into the trailer
01065         // copy image trailer (EOI marker). 'left' should be already 0 if (use_header==0)
01066         if(left > 0) {
01067                 i = left;
01068 //              if(i > (TRAILER_SIZE - p)) i = TRAILER_SIZE - p;
01069                 if(i > TRAILER_SIZE)
01070                         i = TRAILER_SIZE;
01071                 if(i && (copy_to_user(bp, &trailer[p], i))) {
01072                         // sometimes we get here with 'negative' i
01073                         printk("copy_to_user4 (0x%x) error\n", (int)i);
01074                         printk("soft_rp=0x%x\n", (int)soft_rp);
01075                         printk("*off=0x%x\n", (int)*off);
01076                         printk("count=0x%x, left=0x%x, l=0x%x, i=0x%x, p=0x%x\n", (int)count, (int)left, (int)l, (int)i, (int)p);
01077                         return -EFAULT;
01078                 }
01079         } // if (left>0)
01080 //      file->f_pos += count;
01081         *off += count;
01082         return count;  
01083 }
01084 
01085 #else
01086 // w/o EXIF stuff
01087 ssize_t x313_dma_read(struct file * file, char * buf, size_t count, loff_t *off) {
01088         unsigned long p, l, i, left, l1;
01089         int rp;
01090         char *bp = buf;
01091 
01092         MD9(printk("x313_dma_read\n"));
01093 //  x313_dma_stop();
01094 //      p = file->f_pos;
01095         p = *off;
01096         if((p + count) > ((l = x313_DMA_size()) + (use_header ? (JPEG_HEADER_SIZE + TRAILER_SIZE) : 0))) { // truncate count 
01097                 count = l + (use_header ? (JPEG_HEADER_SIZE + TRAILER_SIZE) : 0) - p;
01098         }
01099         left = count;
01100 // read header (if needed)
01101         if (use_header) {
01102           if (p < JPEG_HEADER_SIZE) {
01103             i=left;
01104             if (i>(JPEG_HEADER_SIZE-p)) i= JPEG_HEADER_SIZE-p;
01105             if (i && (copy_to_user(bp, &jpeg_header_sbuffer[p], i)))
01106                {printk("copy_to_user1 (0x%x) error\n",(int) i);return -EFAULT;}
01107             bp+=i;
01108             left-=i;
01109             p=0;
01110           } else p-=JPEG_HEADER_SIZE;
01111         }  // if (use_header)
01112 
01113         if(left == 0) {
01114                 *off += count;
01115                 return count;
01116         }
01117 
01118         // copy image data itself - the buffer may be broken it two parts.
01119         if(p < l) {
01120 //              rp=soft_rp+2;if (rp>=CCAM_DMA_SIZE) rp-=CCAM_DMA_SIZE;
01121                 rp = X313_BUFFADD(soft_rp, 2);
01122                 MD9(printk("rp == 0x%08X; rp << 2 == 0x%08X\r\n", rp, rp << 2));
01123                 // part I - from the beginning read_index up...
01124                 l1 = ((CCAM_DMA_SIZE - rp) << 2);
01125                 if(l1 > l)
01126                         l1 = l;         
01127                 if(p < l1) {
01128                         i = left;
01129                         if(i > (l1 - p))
01130                                 i = l1 - p;
01131                         if(i && (copy_to_user(bp, ((char *) ccam_dma_buf_ptr) + (rp << 2)+ p, i))) {
01132                                 printk("copy_to_user2 (0x%x) error\n",(int) i);
01133                                 return -EFAULT;
01134                         }
01135                         bp += i;
01136                         left -= i;
01137                         p = 0;
01138                 } else
01139                         p -= l1;
01140                 // Part II - continue from the start of the DMA buffer
01141                 l -= l1;
01142                 if(p < l) {
01143                         i = left;
01144                         if(i > (l - p))
01145                                 i = l - p;
01146                         if(i && (copy_to_user(bp, ((char *)ccam_dma_buf_ptr) + p, i))) {
01147                                 printk("copy_to_user3 (0x%x) error\n", (int)i);
01148                                 printk("soft_rp=0x%x\n", (int)soft_rp);
01149                                 printk("*off=0x%x\n", (int) *off);
01150                                 printk("count=0x%x, left=0x%x, l=0x%x, i=0x%x, p=0x%x\n", (int)count, (int)left, (int)l, (int)i, (int)p);
01151                                 return -EFAULT;
01152                         }
01153                         bp += i;
01154                         left -= i;
01155                         p = 0;
01156                 } else
01157                         p -= l;
01158         } else
01159                 p -= l; // pointer got into the trailer
01160         // copy image trailer (EOI marker). 'left' should be already 0 if (use_header==0)
01161         if(left > 0) {
01162                 i = left;
01163 //              if(i > (TRAILER_SIZE - p)) i = TRAILER_SIZE - p;
01164                 if(i > TRAILER_SIZE)
01165                         i = TRAILER_SIZE;
01166                 if(i && (copy_to_user(bp, &trailer[p], i))) {
01167                         // sometimes we get here with 'negative' i
01168                         printk("copy_to_user4 (0x%x) error\n", (int)i);
01169                         printk("soft_rp=0x%x\n", (int)soft_rp);
01170                         printk("*off=0x%x\n", (int)*off);
01171                         printk("count=0x%x, left=0x%x, l=0x%x, i=0x%x, p=0x%x\n", (int)count, (int)left, (int)l, (int)i, (int)p);
01172                         return -EFAULT;
01173                 }
01174         } // if (left>0)
01175 //      file->f_pos += count;
01176         *off += count;
01177         return count;  
01178 }
01179 
01180 #endif
01181 ssize_t x313_dma_write(struct file * file, const char * buf, size_t count, loff_t *off) {
01182   unsigned long p;
01183 
01184   D(printk("x313_dma_write\n"));
01185 //  p = file->f_pos;
01186   p = *off;
01187   if (p >= JPEG_HEADER_SIZE)  p = JPEG_HEADER_SIZE;
01188   if( (p + count) > JPEG_HEADER_SIZE) { // truncate count 
01189     count = JPEG_HEADER_SIZE - p;
01190   }
01191   if (count) { 
01192     if (copy_from_user(&jpeg_header_sbuffer[p],buf, count)) return -EFAULT;
01193 //    file->f_pos+=count;
01194     *off+=count;
01195   }
01196   return count;  
01197 }
01198 #if 0
01200 int             FPGA_quality=-1;
01202 int             JPEG_header_quality=-1;
01203 int             JPEG_header_width=-1;
01204 int             JPEG_header_height-1;
01205 #endif
01206 
01209 void setJPEGHeader (int quality, int width, int height) {
01210 MD9(printk("setJPEGHeader(quality=%d,width=%d, height=%d)\n",quality, width, height));
01211         jpeg_header_sbuffer[HEADER_HEIGHT    ] = (height >> 8) & 0xff;
01212         jpeg_header_sbuffer[HEADER_HEIGHT + 1] = height & 0xff;
01213         jpeg_header_sbuffer[HEADER_WIDTH     ] = (width >> 8) & 0xff;
01214         jpeg_header_sbuffer[HEADER_WIDTH + 1 ] = width & 0xff;
01215 //   if (quality != JPEG_header_quality) jpeg_set_quality ( quality, 0);
01216    if (quality != JPEG_header_quality) jpeg_set_quality(quality, QTABLES_EXIF, NULL);
01217 }
01218 
01219 void x313_dma_update_jpeg_header(void) { // uses channel 0 SDRAM FPGA settings - channel 0 should be programmed earlier
01220         int x, y;
01221         MD8(printk("x313_dma_update_jpeg_header W(P_QUALITY)=%d,R(P_QUALITY)=%d\n",(int)get_imageParamsW(P_QUALITY),(int)get_imageParamsR(P_QUALITY)));
01222         update_JPEG_quality(get_imageParamsW(P_QUALITY));
01223         // Data should be acquired in 8 bit mode
01224 //      y = ((port_csp0_addr[X313_WA_SDCH0_CTL2] & 0x07f0)>>4)+1;
01225 //      x = ((port_csp0_addr[X313_WA_SDCH0_CTL1] & 0x0ff0)>>4)+1;
01226         // it actually uses channel2, not channel1!!
01227         y = ((port_csp0_addr[X313_WA_SDCH2_CTL2] & 0x0ff0) >> 4) + 1;
01228         x = ((port_csp0_addr[X313_WA_SDCH2_CTL1] & 0x1ff0) >> 4) + 1;
01229         MD6(printk("x313_dma_update_jpeg_header x=0x%x, y=0x%x\r\n",x,y));
01230    MD13(printk("x313_dma_update_jpeg_header x=0x%x, y=0x%x (used SDRAM CHN2)\r\n",x,y));
01231         // set the same size into header area
01232         jpeg_header_sbuffer[HEADER_HEIGHT    ] = (y >> 4) & 0xff;
01233         jpeg_header_sbuffer[HEADER_HEIGHT + 1] = (y << 4) & 0xff;
01234         jpeg_header_sbuffer[HEADER_WIDTH     ] = (x >> 4) & 0xff;
01235         jpeg_header_sbuffer[HEADER_WIDTH + 1 ] = (x << 4) & 0xff;
01236 }
01237 
01238 // set JPEG quantization tables exactly as in standard software compression
01239 #define DCTSIZE2 64
01240 void update_JPEG_quality(int quality) { // compressor quality
01241   if((quality != get_imageParamsR(P_QUALITY)) || (quality != jpeg_quality)) {
01242     set_imageParamsR(P_QUALITY, quality);
01243 //    jpeg_set_quality(quality, 1); // program FPGA too
01244     jpeg_set_quality(quality, QTABLES_FPGA | QTABLES_EXIF, NULL); // program FPGA too
01245     jpeg_quality = quality;
01246     frame_params.quality=quality;
01247   }
01248 }
01261 // add parameter updateFPGA, and header_width, header_height, header_quality
01262 //void jpeg_set_quality (int quality, int writeFPGA){
01263 void jpeg_set_quality (int quality, int target, void *table){
01264   /* These are the sample quantization tables given in JPEG spec section K.1.
01265    * The spec says that the values given produce "good" quality, and
01266    * when divided by 2, "very good" quality.
01267    */
01268         int i, temp;
01269         int prev = 0;// supress warning
01270         unsigned char *qtable = NULL;
01271 //   if (quality == (writeFPGA ? FPGA_quality : JPEG_header_quality)) return; // nothing to do
01272         if((target & QTABLES_FPGA) && quality == FPGA_quality)
01273                 target &= ~QTABLES_FPGA;
01274         if((target & QTABLES_EXIF) && quality == JPEG_header_quality)
01275                 target &= ~QTABLES_EXIF;
01276         if(target & QTABLES_TABLE) {
01277                 if(table == NULL)
01278                         target &= ~QTABLES_TABLE;
01279                 else
01280                         qtable = (unsigned char *)table;
01281         }
01282         if(target == 0)
01283                 return; // nothing to do
01284 
01285 
01286         const unsigned int zig_zag[DCTSIZE2] = {
01287                  0, 1, 5, 6,14,15,27,28,
01288                  2, 4, 7,13,16,26,29,42,
01289                  3, 8,12,17,25,30,41,43,
01290                  9,11,18,24,31,40,44,53,
01291                 10,19,23,32,39,45,52,54,
01292                 20,22,33,38,46,51,55,60,
01293                 21,34,37,47,50,56,59,61,
01294                 35,36,48,49,57,58,62,63   
01295         };
01296   
01297         const unsigned int std_quant_tbls[2 * DCTSIZE2] = {
01298 
01299     16,  11,  10,  16,  24,  40,  51,  61,
01300     12,  12,  14,  19,  26,  58,  60,  55,
01301     14,  13,  16,  24,  40,  57,  69,  56,
01302     14,  17,  22,  29,  51,  87,  80,  62,
01303     18,  22,  37,  56,  68, 109, 103,  77,
01304     24,  35,  55,  64,  81, 104, 113,  92,
01305     49,  64,  78,  87, 103, 121, 120, 101,
01306     72,  92,  95,  98, 112, 100, 103,  99,
01307 
01308     17,  18,  24,  47,  99,  99,  99,  99,
01309     18,  21,  26,  66,  99,  99,  99,  99,
01310     24,  26,  56,  99,  99,  99,  99,  99,
01311     47,  66,  99,  99,  99,  99,  99,  99,
01312     99,  99,  99,  99,  99,  99,  99,  99,
01313     99,  99,  99,  99,  99,  99,  99,  99,
01314     99,  99,  99,  99,  99,  99,  99,  99,
01315     99,  99,  99,  99,  99,  99,  99,  99
01316   };
01317 
01318  /* Convert a user-specified quality rating to a percentage scaling factor
01319  * for an underlying quantization table, using our recommended scaling curve.
01320  * The input 'quality' factor should be 0 (terrible) to 100 (very good).
01321  */
01322   /* Safety limit on quality factor.  Convert 0 to 1 to avoid zero divide. */
01323         if(quality <= 0)
01324                 quality = 1;
01325         if(quality > 100)
01326                 quality = 100;
01327 
01328   /* The basic table is used as-is (scaling 100) for a quality of 50.
01329    * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
01330    * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
01331    * to make all the table entries 1 (hence, minimum quantization loss).
01332    * Qualities 1..50 are converted to scaling percentage 5000/Q.
01333    */
01334         if(quality < 50)
01335             quality = 5000 / quality;
01336         else
01337                 quality = 200 - quality * 2;
01338 
01339 
01340         /* Set up two quantization tables using the specified scaling */
01341 //      if (writeFPGA) port_csp0_addr[X313_WA_COMP_TA] = 0x0; // open fpga for writing Q-table (address 0)
01342 
01343 #ifdef PRINTQTAB
01344         printk ("writing quantization table to FPGA\n");
01345 #endif
01346    MD13(printk ("writing quantization table, target=%x (FPGA=%x,EXIF=%x)\n", (int) target, (int)QTABLES_FPGA, (int) QTABLES_EXIF));
01348    unsigned long flags; 
01349    local_irq_save(flags);
01350    if(target & QTABLES_FPGA) port_csp0_addr[X313_WA_COMP_TA] = 0x0; // open fpga for writing Q-table (address 0)
01351         for(i = 0; i < 2 * DCTSIZE2; i++) {
01352                 temp = (std_quant_tbls[i] * quality + 50) / 100;
01353                 /* limit the values to the valid range */
01354                 if(temp <= 0) temp = 1;
01355                 if(temp > 255) temp = 255; // max quantizer needed for 12 bits
01356                 // fix the tables knowing that FPGA actually multiplies, not divides:
01357                 temp = ((8192/temp) + 1) >> 1;
01358                 if(temp > 4095) temp = 4095;
01359                 if(i & 1) {
01360 //                      if (writeFPGA) port_csp0_addr[X313_WA_COMP_TD] = (temp << 16) | prev;   // will autoincrement address
01361                         if(target & QTABLES_FPGA) port_csp0_addr[X313_WA_COMP_TD] = (temp << 16) | prev;        // will autoincrement address
01362 #ifdef PRINTQTAB
01363                         printk ("%08x ",(temp << 16) | prev);
01364                         if((i & 0x07) == 0x07) printk ("\n");
01365 #endif
01366                 } else
01367                         prev = temp;
01368                 temp = ((8192 / temp) + 1) >> 1;
01369                 if(target & QTABLES_EXIF)
01370                         jpeg_header_sbuffer[((i < DCTSIZE2) ? HEADER_YQTABLE : HEADER_CQTABLE) + zig_zag[i & 0x3f]] = temp;
01371                 if(target & QTABLES_TABLE)
01372                         qtable[((i < DCTSIZE2) ? 0 : 64) + zig_zag[i & 0x3F]] = temp;
01373         }
01374    local_irq_restore(flags);
01375 
01376         if(target & QTABLES_EXIF)
01377                 JPEG_header_quality = quality;
01378         if(target & QTABLES_FPGA)
01379                 FPGA_quality = quality;
01380 //   JPEG_header_quality=quality;
01381 //   if (writeFPGA)  FPGA_quality=quality;
01382 }

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