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

Go to the documentation of this file.
00001 /*!********************************************************************************
00002 *! FILE NAME  : gamma_tables.c
00003 *! DESCRIPTION: Handles "gamma"tables storage and scaling
00004 *!              exposes device driver to manipulate custom "gamma" tables
00005 *!              "Gamma" tables are calculated in several steps, leaving the
00006 *!              exponent calculation to the application, but handling scaling inside.
00007 *!              Scaling (with saturation if >1.0)is used for color balancing.
00008 *!              Gamma table calulation involves several intermediate tables:
00009 *!              - forward table
00010 *!              - reverse table (for histogram corrections)
00011 *!              - FPGA format
00012 *!              And the driver caches intermediate tables when possible, calculates
00013 *!              them when needed.
00014 *! Copyright (C) 2008 Elphel, Inc.
00015 *! -----------------------------------------------------------------------------**
00016 *!
00017 *!  This program is free software: you can redistribute it and/or modify
00018 *!  it under the terms of the GNU General Public License as published by
00019 *!  the Free Software Foundation, either version 3 of the License, or
00020 *!  (at your option) any later version.
00021 *!
00022 *!  This program is distributed in the hope that it will be useful,
00023 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 *!  GNU General Public License for more details.
00026 *!
00027 *!  You should have received a copy of the GNU General Public License
00028 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00029 *! -----------------------------------------------------------------------------**
00030 *!  $Log: gamma_tables.c,v $
00031 *!  Revision 1.1.1.1  2008/11/27 20:04:01  elphel
00032 *!
00033 *!
00034 *!  Revision 1.19  2008/11/13 05:40:45  elphel
00035 *!  8.0.alpha16 - modified histogram storage, profiling
00036 *!
00037 *!  Revision 1.18  2008/10/29 04:18:28  elphel
00038 *!  v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
00039 *!
00040 *!  Revision 1.17  2008/10/25 19:51:06  elphel
00041 *!  Changed word order in writes to gamma tables driver
00042 *!
00043 *!  Revision 1.16  2008/10/23 08:04:19  elphel
00044 *!  reenabling IRQ in debug mode
00045 *!
00046 *!  Revision 1.15  2008/10/12 16:46:22  elphel
00047 *!  snapshot
00048 *!
00049 *!  Revision 1.14  2008/10/06 08:31:08  elphel
00050 *!  snapshot, first images
00051 *!
00052 *!  Revision 1.13  2008/10/05 05:13:33  elphel
00053 *!  snapshot003
00054 *!
00055 *!  Revision 1.12  2008/10/04 16:10:12  elphel
00056 *!  snapshot
00057 *!
00058 *!  Revision 1.11  2008/09/22 22:55:48  elphel
00059 *!  snapshot
00060 *!
00061 *!  Revision 1.10  2008/09/20 00:29:50  elphel
00062 *!  moved driver major/minor numbers to a single file - include/asm-cris/elphel/driver_numbers.h
00063 *!
00064 *!  Revision 1.9  2008/09/19 04:37:25  elphel
00065 *!  snapshot
00066 *!
00067 *!  Revision 1.8  2008/09/16 00:49:32  elphel
00068 *!  snapshot
00069 *!
00070 *!  Revision 1.7  2008/09/12 00:23:59  elphel
00071 *!  removed cc353.c, cc353.h
00072 *!
00073 *!  Revision 1.6  2008/09/11 01:05:32  elphel
00074 *!  snapshot
00075 *!
00076 *!  Revision 1.5  2008/09/05 23:20:26  elphel
00077 *!  just a snapshot
00078 *!
00079 *!  Revision 1.4  2008/07/27 04:27:49  elphel
00080 *!  next snapshot
00081 *!
00082 *!  Revision 1.3  2008/06/16 06:51:21  elphel
00083 *!  work in progress, intermediate commit
00084 *!
00085 *!  Revision 1.2  2008/06/10 00:02:42  elphel
00086 *!  fast calculation of 8-bit reverse functions for "gamma" tables and histograms
00087 *!
00088 *!  Revision 1.1  2008/06/08 23:46:45  elphel
00089 *!  added drivers files for handling quantization tables, gamma tables and the histograms
00090 *!
00091 *!
00092 */
00093 
00094 //copied from cxi2c.c - TODO:remove unneeded 
00095 
00096 #include <linux/module.h>
00097 #include <linux/mm.h>
00098 #include <linux/sched.h>
00099 #include <linux/slab.h>
00100 #include <linux/errno.h>
00101 #include <linux/kernel.h>
00102 #include <linux/fs.h>
00103 #include <linux/string.h>
00104 #include <linux/init.h>
00105 #include <linux/autoconf.h>
00106 #include <linux/vmalloc.h>
00107 
00108 #include <asm/system.h>
00109 #include <asm/byteorder.h> // endians
00110 #include <asm/io.h>
00111 
00112 #include <asm/irq.h>
00113 
00114 #include <asm/delay.h>
00115 #include <asm/uaccess.h>
00116 #include <asm/elphel/driver_numbers.h>
00117 #include <asm/elphel/c313a.h>
00118 #include <asm/elphel/exifa.h>
00119 #include "fpgactrl.h"  // defines port_csp0_addr, port_csp4_addr 
00120 #include "framepars.h"        // for debug mask
00121 
00122 //#include "fpga_io.h"//fpga_table_write_nice
00123 
00124 //#include "cc3x3.h"
00125 //#include "x3x3.h" // just for FPGA_NQTAB
00126 
00127 //#include "framepars.h"
00128 //#include "quantization_tables.h"
00129 #include "gamma_tables.h"
00133 #if ELPHEL_DEBUG
00134   #define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
00135   #define D10(x) { if (GLOBALPARS(G_DEBUG) & (1 <<10)) { x ;} }
00136 //  #define MDD1(x) printk("%s:%d:",__FILE__,__LINE__); x ; udelay (ELPHEL_DEBUG_DELAY)
00137   #define MDF10(x) { if (GLOBALPARS(G_DEBUG) & (1 <<10)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
00138   #define MDF11(x) { if (GLOBALPARS(G_DEBUG) & (1 <<11)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
00139 
00140 //  #define MDD1(x)
00141   #define D1I(x) x
00142 
00143 #else
00144   #define MDF(x)
00145   #define D10(x)
00146   #define D1I(x) x
00147   #define MDF10(x)
00148   #define MDF11(x)
00149 
00150 
00151 #endif
00152 
00153 #define  X3X3_GAMMAS_DRIVER_NAME "Elphel (R) Model 353 Gamma Tables device driver"
00154 
00158 #define GAMMA_THRESH (GAMMA_CACHE_NUMBER/16)
00159 
00160 static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE)));
00161        struct gamma_stuct_t * gammas_p; 
00162 
00163 struct gammas_pd {
00164     int                minor;
00165     unsigned short     scale;
00166     unsigned short     hash16;
00167     unsigned char      mode;
00168     unsigned char      color;
00170 };
00171 
00172 int        gammas_open   (struct inode *inode, struct file *file);
00173 int        gammas_release(struct inode *inode, struct file *file);
00174 loff_t     gammas_lseek  (struct file * file, loff_t offset, int orig);
00175 ssize_t    gammas_write  (struct file * file, const char * buf, size_t count, loff_t *off);
00176 int        gammas_mmap   (struct file *file, struct vm_area_struct *vma);
00177 static int __init gammas_init(void);
00178 
00179 
00184 inline void remove_from_nonscaled(int index) {
00185     gammas[gammas[index].newer_non_scaled].older_non_scaled=gammas[index].older_non_scaled;
00186     gammas[gammas[index].older_non_scaled].newer_non_scaled=gammas[index].newer_non_scaled;
00187     gammas[0].non_scaled_length--;
00188 }
00189 
00194 inline void remove_from_scaled   (int index) {
00195     if (likely(gammas[index].newer_scaled)) { 
00196      gammas[gammas[index].newer_scaled].older_scaled=gammas[index].older_scaled;
00197      gammas[gammas[index].older_scaled].newer_scaled=gammas[index].newer_scaled;
00198     }
00199 }
00200 
00205 inline void remove_from_all      (int index) { 
00206     gammas[gammas[index].newer_all].older_all=gammas[index].older_all;
00207     gammas[gammas[index].older_all].newer_all=gammas[index].newer_all;
00208 }
00209 
00214 inline void insert_first_nonscaled(int index) {
00215   MDF11(printk("index=%d\n",index));
00216     gammas[gammas[0].newest_non_scaled].newer_non_scaled= index; // 1 ==[0].oldest_non_scaled
00217     gammas[index].older_non_scaled=  gammas[0].newest_non_scaled; // 4
00218     gammas[0].newest_non_scaled=index; // 5
00219     gammas[index].newer_non_scaled=0; // 6
00220     gammas[0].non_scaled_length++;
00221     gammas[index].this_non_scaled=0; // none
00222     gammas[index].newest_scaled=index; 
00223     gammas[index].oldest_scaled=index; 
00224 
00225 }
00226 
00232 inline void insert_first_scaled   (int non_scaled, int index) {
00233   MDF11(printk("non_scaled=%d, index=%d\n",non_scaled, index));
00234     gammas[index].older_scaled=     gammas[non_scaled].newest_scaled; //4
00235     gammas[gammas[non_scaled].newest_scaled].newer_scaled= index; //1
00236 //    gammas[index].older_scaled=     gammas[non_scaled].newest_scaled; //4
00237 
00238     gammas[index].newer_scaled= non_scaled; //6
00239     gammas[non_scaled].newest_scaled=     index; //5
00240 //    gammas[index].newer_scaled= non_scaled; //6
00241     gammas[index].this_non_scaled=non_scaled;
00242 }
00243 
00248 inline void insert_first_all      (int index) {
00249     gammas[gammas[0].newest_all].newer_all= index; //1
00250     gammas[index].older_all=     gammas[0].newest_all; //4
00251     gammas[0].newest_all=         index; //5
00252     gammas[index].newer_all= 0; //6
00253 }
00254 
00258 void init_gammas(void) {
00259   unsigned long flags;
00260   int i;
00261   gammas_p=gammas;
00263   local_irq_save(flags);
00264   gammas[0].oldest_non_scaled=0;
00265   gammas[0].newest_non_scaled=0;
00267   gammas[0].oldest_all=GAMMA_CACHE_NUMBER-1;
00268   gammas[0].newest_all=1;
00269   MDF10(printk("\n"));
00270   for (i=1; i < GAMMA_CACHE_NUMBER;i++) {
00271     gammas[i].this_non_scaled=-1; 
00272 
00273     gammas[i].newer_all=i-1;
00274     gammas[i].older_all= (i==(GAMMA_CACHE_NUMBER-1))? 0: (i+1);
00275     gammas[i].locked=0;
00276     gammas[i].valid=0;
00277   }
00278   gammas[0].non_scaled_length=0;
00279   for (i=1; i < 4;i++) {
00280     gammas[0].locked_color[i]=0;
00281   }
00282   local_irq_restore(flags);
00283 }
00284 
00285 
00293 int is_gamma_current (unsigned short hash16, unsigned short scale, int index) {
00294   return ((gammas[index].hash16 == hash16) && (gammas[index].scale == scale))?1:0;
00295 }
00296 
00304 int is_gamma_valid (unsigned short hash16, unsigned short scale, int index) {
00305   return ((gammas[index].hash16 == hash16) && (gammas[index].scale == scale) && (gammas[index].valid != 0))?1:0;
00306 }
00307 
00308 
00314 unsigned long get_locked_hash32(int color) {
00315   int index=gammas[0].locked_color[color];
00316   return index?gammas[index].hash32:0;
00317 }
00318 
00325 inline void lock_gamma_node (int index, int color) {
00326   int tmp_p;
00327   if (likely((color<4) && (color >=0))) { 
00328     if (((tmp_p=gammas[0].locked_color[color]))!=0) { 
00329       gammas[tmp_p].locked &= ~(1 << color); 
00330     }
00331     gammas[0].locked_color[color]= index;
00332     gammas[index].locked |= (1 << color);
00333   }
00334 }
00341 int unlock_gamma_node (int color) {
00342   unsigned long flags;
00343   int index;
00344   MDF11(printk("color=0x%x\n",color));
00345   if (unlikely((color>= 4) || (color<0))) return -1;
00346   local_irq_save(flags);
00347   index =gammas[0].locked_color[color];
00348   if (index) {
00349     gammas[index].locked &= ~(1 <<  color); 
00350     gammas[0].locked_color[color]=0;
00351   }
00352   local_irq_restore(flags);
00353   return index;
00354 }
00360 unsigned long * get_gamma_fpga(int color) { 
00361   int index;
00362   if (unlikely((color>=4) || (color<0))) return NULL; //
00363   index =gammas[0].locked_color[color];
00364   MDF11(printk(" index=%d(0x%x)\n",index,index));
00365   if (index) return gammas[index].fpga;
00366   else return NULL;
00367 }
00368 
00369 
00377 int gamma_new_node(void) {
00378    int tmp_p;
00379    if ((gammas[0].non_scaled_length > GAMMA_THRESH) && (gammas[gammas[0].oldest_non_scaled].newest_scaled == gammas[0].oldest_non_scaled)) { 
00380 
00381     tmp_p=gammas[0].oldest_non_scaled;
00382      remove_from_nonscaled(tmp_p);
00383    } else { 
00384     tmp_p=gammas[0].oldest_all;
00386     while ((tmp_p!=0) && gammas[tmp_p].locked) tmp_p=gammas[tmp_p].newer_all;
00387     if (tmp_p==0) return 0; // none (unlocked) nodes are found
00389     remove_from_all   (tmp_p);
00391     remove_from_scaled   (tmp_p);
00392    }
00393    gammas[tmp_p].valid=0;
00394    return tmp_p;
00395 }
00396 
00402 void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out) {
00403   int i,base,diff;
00404   MDF11(printk("\n"));
00405   for (i=0;i<256;i++) {
00406     base=(gamma_in[i] >> 6);
00407     diff=(gamma_in[i+1] >> 6);
00408     diff-=base;
00409     if ((diff>63) || (diff < -64)) {
00410       diff=(diff+8)>>4;
00411       gamma_out[i]=(base & 0x3ff) | ((diff & 0x7f) << 10) | (1 << 17);
00412     } else {
00413       gamma_out[i]=(base & 0x3ff) | ((diff & 0x7f) << 10);
00414     }
00415   }
00416 }
00417 
00424 void  gamma_calc_scaled (unsigned short scale,unsigned short * gamma_in, unsigned short * gamma_out) {
00425   int i;
00426   unsigned long d;
00427   unsigned long max_scaled=0xffff << GAMMA_SCALE_SHIFT;
00428   MDF11(printk("\n"));
00429   for (i=0; i<257; i++) {
00430     d= ((unsigned long) scale ) * ((unsigned long) gamma_in[i] ) + (1 <<(GAMMA_SCALE_SHIFT-1)); 
00431     if (d>max_scaled) d=max_scaled;
00432     gamma_out[i]=d >> GAMMA_SCALE_SHIFT;
00433   }
00434 }
00435 
00444 void  gamma_calc_reverse(unsigned short * gamma_in, unsigned char * gamma_out) {
00445   unsigned long gcurr=0; 
00446   int r=0; 
00447   int x=0; 
00448   MDF11(printk("\n"));
00449   while ((r<256) && (x<256)) {
00450     gamma_out[x]=r;
00451 //    if ((r<255) && (( gamma_in[r]<<8) <= gcurr)) {
00452     if ((r<255) && ( gamma_in[r] <= gcurr)) {
00453       r++;
00454     } else {
00455       x++;
00456       gcurr+=256;
00457     }
00458   }
00459 }
00460 
00474 //#define GAMMA_MODE_LOCK         8  // Lock the table for the specified color (used from irq/tasklet - it is needed because all 4 tables in FPGA have to be overwritten at once)
00475 int set_gamma_table (unsigned short hash16, unsigned short scale, unsigned short * gamma_proto,  unsigned char mode, int color) {
00476   D1I(unsigned long flags);
00477   int tmp_p, tmp_p1; //,tmp_p0;
00478   unsigned short gamma_linear[257]=
00479       {0x0000,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00,
00480        0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x0600,0x1700,0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00,
00481        0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x0600,0x2700,0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00,0x2f00,
00482        0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x0600,0x3700,0x3800,0x3900,0x3a00,0x3b00,0x3c00,0x3d00,0x3e00,0x3f00,
00483        0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x0600,0x4700,0x4800,0x4900,0x4a00,0x4b00,0x4c00,0x4d00,0x4e00,0x4f00,
00484        0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x0600,0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00,
00485        0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x0600,0x6700,0x6800,0x6900,0x6a00,0x6b00,0x6c00,0x6d00,0x6e00,0x6f00,
00486        0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x0600,0x7700,0x7800,0x7900,0x7a00,0x7b00,0x7c00,0x7d00,0x7e00,0x7f00,
00487        0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x0600,0x8700,0x8800,0x8900,0x8a00,0x8b00,0x8c00,0x8d00,0x8e00,0x8f00,
00488        0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x0600,0x9700,0x9800,0x9900,0x9a00,0x9b00,0x9c00,0x9d00,0x9e00,0x9f00,
00489        0xa000,0xa100,0xa200,0xa300,0xa400,0xa500,0x0600,0xa700,0xa800,0xa900,0xaa00,0xab00,0xac00,0xad00,0xae00,0xaf00,
00490        0xb000,0xb100,0xb200,0xb300,0xb400,0xb500,0x0600,0xb700,0xb800,0xb900,0xba00,0xbb00,0xbc00,0xbd00,0xbe00,0xbf00,
00491        0xc000,0xc100,0xc200,0xc300,0xc400,0xc500,0x0600,0xc700,0xc800,0xc900,0xca00,0xcb00,0xcc00,0xcd00,0xce00,0xcf00,
00492        0xf000,0xd100,0xd200,0xd300,0xd400,0xd500,0x0600,0xd700,0xd800,0xd900,0xda00,0xdb00,0xdc00,0xdd00,0xde00,0xdf00,
00493        0xe000,0xe100,0xe200,0xe300,0xe400,0xe500,0x0600,0xe700,0xe800,0xe900,0xea00,0xeb00,0xec00,0xed00,0xee00,0xef00,
00494        0xf000,0xf100,0xf200,0xf300,0xf400,0xf500,0x0600,0xf700,0xf800,0xf900,0xfa00,0xfb00,0xfc00,0xfd00,0xfe00,0xff00,
00495        0xffff};
00496   MDF10(printk("hash16=0x%x scale=0x%x gamma_proto=0x%x mode =0x%x color=%x\n", (int) hash16, (int) scale, (int) gamma_proto,  (int) mode,  color));
00497 
00498   if (!gamma_proto & (hash16==0)) {
00499     gamma_proto=gamma_linear;
00500     MDF10(printk("Using linear table\n"));
00501   } else {
00502     MDF10(printk("Using non-linear table\n")); 
00503   }
00505   D1I(local_irq_save(flags));
00507   tmp_p=gammas[0].newest_non_scaled;
00510 
00511   MDF10(printk("gammas[0].oldest_all=%d\n", gammas[0].oldest_all)); 
00512 
00513   MDF10(printk("gammas[0].newest_all=%d\n", gammas[0].newest_all));
00514   MDF10(printk("tmp_p=0x%x gammas[tmp_p].hash16=0x%x hash16=0x%x\n", tmp_p, (int) gammas[tmp_p].hash16, (int) hash16 ));
00515   while ((tmp_p!=0) && (gammas[tmp_p].hash16 != hash16)) {
00516     D10(printk(" --tmp_p=0x%x\n", tmp_p)); 
00517     tmp_p=gammas[tmp_p].older_non_scaled;
00518   }
00519   MDF10(printk("tmp_p=0x%x\n", tmp_p)); 
00520 
00521   if (tmp_p == 0) { 
00522     MDF10(printk("Need new table\n")); 
00523     if (!gamma_proto) { //
00524       D1I(local_irq_restore(flags));
00525       MDF10(printk("matching hash not found, new table is not provided\n")); 
00526       return 0;   
00527     }
00529     tmp_p=gamma_new_node();
00530     MDF10(printk("tmp_p=0x%x\n gamma_proto= 0x%x 0x%x 0x%x 0x%x\n", tmp_p, (int) gamma_proto[0], (int) gamma_proto[1], (int) gamma_proto[2], (int) gamma_proto[3]));
00531     if (unlikely(!tmp_p)) { 
00532       D1I(local_irq_restore(flags));
00533       return 0;   
00534     }
00536     gammas[tmp_p].hash16=hash16;
00537     gammas[tmp_p].scale=0;
00538     gammas[tmp_p].oldest_scaled=tmp_p;  
00539     gammas[tmp_p].newest_scaled=tmp_p;  
00540     if ((mode & GAMMA_MODE_NOT_NICE)==0) {
00542       D1I(local_irq_restore(flags));
00543       MDF10(printk("Interrupts reenabled, tmp_p=0x%x\n", tmp_p));
00544       D1I(local_irq_save(flags));
00546       if (unlikely(!is_gamma_current (hash16, 0, tmp_p))) {
00547         D1I(local_irq_restore(flags));
00548         return 0;   
00549       }
00550     }
00551 //    memcpy ((void *)...
00552     memcpy (gammas[tmp_p].direct, gamma_proto, 257*2) ; 
00553     gammas[tmp_p].valid |= GAMMA_VALID_MASK;
00555     MDF10(printk("insert_first_nonscaled(0x%x)\n", tmp_p));
00556     insert_first_nonscaled(tmp_p);
00557 
00559   } else  if (gammas[tmp_p].newer_non_scaled !=0) { 
00560     MDF10(printk("remove_from_nonscaled (0x%x)\n", tmp_p)); 
00561     remove_from_nonscaled (tmp_p);
00562     MDF10(printk("insert_first_nonscaled (0x%x)\n", tmp_p));
00563     insert_first_nonscaled(tmp_p);
00564   }
00565   MDF10(printk("0x%x\n", tmp_p)); 
00566 
00567 
00569   if (scale==0) {
00570     D1I(local_irq_restore(flags));
00571     return tmp_p;   
00572   }
00573   tmp_p1=gammas[tmp_p].newest_scaled;
00574   MDF10(printk("tmp_p1=0x%x\n", tmp_p1));  
00575 //  while ((tmp_p1!=0) && (gammas[tmp_p1].scale != scale)){ ///FIXME: got stuck here
00576   while ((tmp_p1!=tmp_p) && (gammas[tmp_p1].scale != scale)){ 
00577     D10(printk(" >>tmp_p1=0x%x)\n", tmp_p1));
00578     tmp_p1=gammas[tmp_p1].older_scaled;
00579   }
00581 //  if (tmp_p1 == 0) { /// no luck
00582   if (tmp_p1 == tmp_p) { 
00583     MDF10(printk("create new scaled table\n"));
00585     tmp_p1=gamma_new_node();
00586     if (unlikely(!tmp_p1)) { 
00587       D1I(local_irq_restore(flags));
00588       return 0;   
00589     }
00591     gammas[tmp_p1].hash16=hash16;
00592     gammas[tmp_p1].scale= scale;
00594     insert_first_scaled   (tmp_p, tmp_p1);
00596     insert_first_all (tmp_p1);
00597     if ((mode & GAMMA_MODE_NOT_NICE)==0) {
00599       D1I(local_irq_restore(flags));
00600       D1I(local_irq_save(flags));
00602       if (unlikely(!is_gamma_current (hash16, scale, tmp_p1))) {
00603         D1I(local_irq_restore(flags));
00604         return 0;   
00605       }
00606     }
00607   } else { 
00608     MDF10(printk("reuse scaled table\n"));
00611     if (gammas[tmp_p1].newer_scaled != tmp_p) { 
00612       remove_from_scaled    (tmp_p1);
00613       insert_first_scaled   (tmp_p, tmp_p1);
00614     }
00616     if (gammas[tmp_p1].newer_all != 0) { 
00617       remove_from_all       (tmp_p1);
00618       insert_first_all      (tmp_p1);
00619     }
00620   }
00622   if ((gammas[tmp_p1].valid & GAMMA_VALID_MASK) == 0) {
00624     gamma_calc_scaled (scale, gammas[tmp_p].direct, gammas[tmp_p1].direct);
00625     gammas[tmp_p1].valid |= GAMMA_VALID_MASK;
00626   }
00627   if (mode & GAMMA_MODE_HARDWARE) {
00629     if ((gammas[tmp_p1].valid & GAMMA_FPGA_MASK)==0) {
00630       gamma_encode_fpga(gammas[tmp_p1].direct, gammas[tmp_p1].fpga);
00631       gammas[tmp_p1].valid |= GAMMA_FPGA_MASK;
00632     }
00633   }
00634   if (mode & GAMMA_MODE_LOCK) {
00636     lock_gamma_node (tmp_p1, color);
00637   }
00638   if (mode & GAMMA_MODE_NEED_REVERSE) {
00639     if ((gammas[tmp_p1].valid & GAMMA_VALID_REVERSE)==0) {
00640       if ((mode & GAMMA_MODE_NOT_NICE)==0) {
00642         D1I(local_irq_restore(flags));
00643         D1I(local_irq_save(flags));
00645         if (unlikely(!is_gamma_current (hash16, 0, tmp_p))) {
00646           D1I(local_irq_restore(flags));
00647           return 0;   
00648         }
00649       }
00650       gamma_calc_reverse(gammas[tmp_p1].direct, gammas[tmp_p1].reverse);
00651       gammas[tmp_p1].valid |= GAMMA_VALID_REVERSE;
00652     }
00653   }
00654   D1I(local_irq_restore(flags));
00655   MDF10(printk("- return %d\n",tmp_p1));
00656   return tmp_p1;
00657 }
00658 
00659 
00671 
00681 //#define LSEEK_GAMMA_INIT        1 // SEEK_END LSEEK_GAMMA_INIT to initialize all the gamma data structures
00682 //#define LSEEK_GAMMA_ISCURRENT   2 // SEEK_END to check if the selected node(pointed by file pointer) is current - returns 0 if not, otherwise - node index
00686 #define GAMMA_FILE_SIZE GAMMA_CACHE_NUMBER
00687 static struct file_operations gammas_fops = {
00688    owner:    THIS_MODULE,
00689    llseek:   gammas_lseek,
00690    write:    gammas_write,
00691    open:     gammas_open,
00692    mmap:     gammas_mmap,
00693    release:  gammas_release
00694 };
00701 int gammas_open(struct inode *inode, struct file *file) {
00702    int res;
00703    struct gammas_pd * privData;
00704    privData= (struct gammas_pd *) kmalloc(sizeof(struct gammas_pd),GFP_KERNEL);
00705   MDF10(printk("gammas[0].oldest_all=%d\n", gammas[0].oldest_all));
00706   MDF10(printk("gammas[0].newest_all=%d\n", gammas[0].newest_all));
00707    if (!privData) return -ENOMEM;
00708    file->private_data = privData;
00709    privData-> minor=MINOR(inode->i_rdev);
00710    MDF10(printk("gammas_open, minor=0x%x\n",privData-> minor));
00711    switch (privData-> minor) {
00712      case CMOSCAM_MINOR_GAMMAS :
00713         inode->i_size = GAMMA_FILE_SIZE;
00714         privData-> scale= 0;
00715         privData-> hash16=0;
00716         privData-> mode= 0;
00717         return 0;
00718      default:
00719        kfree(file->private_data); 
00720        return -EINVAL;
00721    }
00722    file->f_pos = 0;
00723    return res;
00724 }
00725 
00732 int gammas_release(struct inode *inode, struct file *file) {
00733   int res=0;
00734   int p = MINOR(inode->i_rdev);
00735   MDF10(printk("gammas_release, minor=0x%x\n",p));
00736   switch ( p ) {
00737     case  CMOSCAM_MINOR_GAMMAS :
00738         break;
00739     default:
00740         return -EINVAL; 
00741     }
00742   kfree(file->private_data);
00743   return res;
00744 }
00745 
00746 
00762 loff_t gammas_lseek (struct file * file, loff_t offset, int orig) {
00763    struct gammas_pd * privData = (struct gammas_pd *) file->private_data;
00764    MDF10(printk("offset=0x%x, orig=0x%x, file->f_pos=0x%x\n",(int) offset, (int) orig, (int) file->f_pos));
00765    switch (privData->minor) {
00766        case CMOSCAM_MINOR_GAMMAS :
00767          switch(orig) {
00768          case SEEK_SET:
00769            file->f_pos = offset;
00770            break;
00771          case SEEK_CUR:
00772 //     file->f_pos = getThisFrameNumber() + offset;
00773            break;
00774          case SEEK_END:
00775            if (offset < 0) {
00776               break;
00777            } else if (offset == 0) {
00778               file->f_pos=GAMMA_CACHE_NUMBER;
00779               break;
00780            } else {
00781              switch (offset) {
00782              case LSEEK_GAMMA_INIT:
00783                 init_gammas();
00784                 file->f_pos=0;
00785                 break;
00786              case LSEEK_GAMMA_ISCURRENT:
00787                if (file->f_pos==0) break; 
00788                if (!is_gamma_current (privData->hash16, privData->scale, (int) file->f_pos)) file->f_pos=0;
00789                break;
00790              default: 
00791                return -EINVAL;
00792              }
00793            break;
00794            }
00795          default:  
00796             return -EINVAL;
00797          } 
00798    MDF10(printk("file->f_pos=0x%x\n",(int) file->f_pos));
00799          return  file->f_pos ;
00800        default: 
00801          return -EINVAL;
00802   }
00803 }
00804 
00821 ssize_t gammas_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00822    struct gammas_pd * privData = (struct gammas_pd *) file->private_data;
00823    struct {
00824      unsigned short scale;
00825      unsigned short hash16;
00826      unsigned char  mode;
00827      unsigned char  color;
00828      unsigned short gamma[257];
00829    } data;
00830 
00831    int     head,   result;
00833    unsigned short * gamma= data.gamma;
00834    MDF10(printk(" file->f_pos=0x%x, *off=0x%x\n", (int) file->f_pos, (int) *off));
00835    switch (privData->minor) {
00836        case CMOSCAM_MINOR_GAMMAS :
00837          if (count>sizeof (data)) count = sizeof (data);
00838          if(count) {
00839            if(copy_from_user((char *) &data, buf, count))  return -EFAULT;
00840            head=6;
00841            if ((count-head) < (2 * 257)) gamma=NULL; 
00842            if (head>count) head=count;
00843            memcpy (&(privData->scale),&(data.scale),head);
00844   MDF10(printk("count=%d, head=%d, hash16=0x%x scale=0x%x mode=0x%x color=%x\n", count, head, (int) data.hash16, (int) data.scale,  (int) data.mode,  (int) data.color));
00845   MDF10(printk("count=%d, head=%d, hash16=0x%x scale=0x%x mode=0x%x color=%x\n", count, head, (int) privData->hash16, (int) privData->scale,  (int) privData->mode,  (int) privData->color));
00846            result=set_gamma_table (privData->hash16, privData->scale, gamma,  privData->mode, ( privData->color >> 3) & 3);
00847            *off= (result>0)?result:0;
00848          } else *off=0;
00849    MDF10(printk("file->f_pos=0x%x\n", (int) *off));
00850          return (*off) ? count: 0; 
00851        default:                           return -EINVAL;
00852   }
00853 }
00854 
00861 int gammas_mmap (struct file *file, struct vm_area_struct *vma) {
00862   int result;
00863   struct gammas_pd * privData = (struct gammas_pd *) file->private_data;
00864   MDF10(printk("gammas_all_mmap, minor=0x%x\n",privData-> minor));
00865      switch (privData->minor) {
00866        case  CMOSCAM_MINOR_GAMMAS :
00867            result=remap_pfn_range(vma,
00868                   vma->vm_start,
00869                  ((unsigned long) virt_to_phys(gammas_p)) >> PAGE_SHIFT, // Should be page-aligned
00870                   vma->vm_end-vma->vm_start,
00871                   vma->vm_page_prot);
00872            MDF10(printk("remap_pfn_range returned=%x\r\n",result));
00873            if (result) return -EAGAIN;
00874            return 0;
00875        default: return -EINVAL;
00876   }
00877 }
00878 
00883 static int __init gammas_init(void) {
00884    int res;
00885    printk ("Starting "X3X3_GAMMAS_DRIVER_NAME" - %d \n",GAMMAS_MAJOR);
00886    init_gammas();
00887    MDF10(printk("set_gamma_table (0, GAMMA_SCLALE_1, NULL,  0, 0)\n"); udelay (ELPHEL_DEBUG_DELAY));
00888    set_gamma_table (0, GAMMA_SCLALE_1, NULL,  0, 0); 
00889 
00890 
00891    res = register_chrdev(GAMMAS_MAJOR, "gamma_tables_operations", &gammas_fops);
00892    if(res < 0) {
00893      printk(KERN_ERR "\ngammas_init: couldn't get a major number %d.\n",GAMMAS_MAJOR);
00894      return res;
00895    }
00896 //   init_waitqueue_head(&gammas_wait_queue);
00897    printk(X3X3_GAMMAS_DRIVER_NAME" - %d \n",GAMMAS_MAJOR);
00898    return 0;
00899 }
00900 
00901 
00902 module_init(gammas_init);
00903 MODULE_LICENSE("GPLv3.0");
00904 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00905 MODULE_DESCRIPTION(X3X3_GAMMAS_DRIVER_NAME);
00906 
00907 
00908 
00909 
00910 
00911 
00912 
00913 
00914 
00915 
00916 
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1