00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
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>
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"
00120 #include "framepars.h"
00121
00122
00123
00124
00125
00126
00127
00128
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
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
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;
00217 gammas[index].older_non_scaled= gammas[0].newest_non_scaled;
00218 gammas[0].newest_non_scaled=index;
00219 gammas[index].newer_non_scaled=0;
00220 gammas[0].non_scaled_length++;
00221 gammas[index].this_non_scaled=0;
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;
00235 gammas[gammas[non_scaled].newest_scaled].newer_scaled= index;
00236
00237
00238 gammas[index].newer_scaled= non_scaled;
00239 gammas[non_scaled].newest_scaled= index;
00240
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;
00250 gammas[index].older_all= gammas[0].newest_all;
00251 gammas[0].newest_all= index;
00252 gammas[index].newer_all= 0;
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;
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
00452 if ((r<255) && ( gamma_in[r] <= gcurr)) {
00453 r++;
00454 } else {
00455 x++;
00456 gcurr+=256;
00457 }
00458 }
00459 }
00460
00474
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;
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
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
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
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
00682
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
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,
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
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