00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <linux/kernel.h>
00024 #include <linux/sched.h>
00025 #include <linux/mm.h>
00026
00027 #include <linux/wait.h>
00028
00029 #include <asm/unistd.h>
00030 #include <asm/semaphore.h>
00031
00032 #include <asm/atomic.h>
00033
00034 #include <linux/module.h>
00035 #include <linux/slab.h>
00036 #include <linux/errno.h>
00037 #include <linux/fs.h>
00038 #include <linux/string.h>
00039 #include <linux/init.h>
00040 #include <linux/mm.h>
00041
00042
00043 #include <linux/vmalloc.h>
00044 #include <linux/rwsem.h>
00045
00046 #include <linux/netdevice.h>
00047 #include <linux/skbuff.h>
00048 #include <linux/time.h>
00049 #include <linux/wait.h>
00050 #include <asm/io.h>
00051 #include <asm/atomic.h>
00052 #include <asm/page.h>
00053
00054
00055 #include "fpgactrl.h"
00056
00057 #include <asm/elphel/c313a.h>
00058 #include <asm/elphel/hist.h>
00059 #include <asm/elphel/autoexp.h>
00060
00061 #include "cc3x3.h"
00062 #include "cxdma.h"
00063 #include "x3x3.h"
00064 #include "hist.h"
00065 #include "fpga_io.h"
00066
00067
00068
00069 #define HIST_MAJOR 130
00070 #define AUTOEXP_MAJOR 131
00071
00072 #if ELPHEL_DEBUG
00073 #define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00074
00075 #else
00076 #define MD1(x)
00077 #endif
00078
00079
00080
00081
00082 DECLARE_MUTEX(ae_log_lock);
00083 static struct autoexp_log_t ae_log_buf[LOG_C];
00084 static struct autoexp_log_t *ae_log_p = &ae_log_buf[LOG_C - 1];
00085 static unsigned ae_log_c = 0;
00086
00087 DECLARE_MUTEX(sensor_lock);
00088 atomic_t sensor_refresh;
00089 DECLARE_MUTEX(iface_lock);
00090 atomic_t autoexp_on;
00091 atomic_t autoexp_enable;
00092 DECLARE_WAIT_QUEUE_HEAD(wq_hist);
00093 static int first_exp = 0;
00094
00095 DECLARE_MUTEX(autoexp_iface_lock);
00096
00097 #define BUF_C 2
00098
00099 struct gamma_t {
00100 unsigned short *buf;
00101 struct timeval tv;
00102 };
00103 struct gamma_t gamma[BUF_C];
00104
00105
00106 static unsigned short gamma_table_1[256 * 6];
00107 static unsigned short gamma_table_2[256 * 6];
00108
00109 static unsigned long c_gamma = 0;
00110 static unsigned long c_hist = 0;
00111
00112 DECLARE_MUTEX(gamma_lock);
00113 static unsigned short gamma_table[256 * 6] __attribute__ ((aligned (PAGE_SIZE)));
00114 struct timeval tv_gamma;
00115
00116
00117 struct buf_t {
00118 unsigned long *buf;
00119 struct timeval tv;
00120 struct semaphore lock;
00121 };
00122 struct buf_t buf[BUF_C];
00123
00124 DECLARE_MUTEX(hist0_lock);
00125 static struct timeval tv_gamma_hb_0;
00126 static unsigned long hb_0[TABLES_LEN] __attribute__ ((aligned (PAGE_SIZE)));
00127
00128 static unsigned long hb_1[256 * 4 + 256 * 2] __attribute__ ((aligned (PAGE_SIZE)));
00129 static unsigned long hb_2[256 * 4 + 256 * 2] __attribute__ ((aligned (PAGE_SIZE)));
00130
00131 #define HIST_TABLE_SIZE (256 * 4 * sizeof(u32))
00132
00133 #define HIST_EXP_MAX_START 4000
00134 #define HIST_OVEREXP_MAX_START 50
00135 #define HIST_EXP_START 1000
00136
00137 DECLARE_MUTEX(autoexp_conf_lock);
00138 int autoexp_conf_new = 1;
00140 #if 0
00141 struct autoexp_t autoexp_conf = {
00142 .on = 1,
00143 .width = 80,
00144 .height = 80,
00145 .left = 50,
00146 .top = 50,
00147 .exp_max = HIST_EXP_MAX_START,
00148 .overexp_max = HIST_OVEREXP_MAX_START,
00149 .s_index = 0,
00150 .s_percent = 0,
00151 .exp = HIST_EXP_START,
00152 .skip_pmin = 500,
00153 .skip_pmax = 5000,
00154 .skip_t = 2,
00155 };
00156 #endif
00158 #if 0
00159 struct autoexp_t state = {
00160 .on = 1,
00161 .exp_max = HIST_EXP_MAX_START,
00162 .overexp_max = HIST_OVEREXP_MAX_START,
00163 .exp = HIST_EXP_START,
00164 .s_index = 0,
00165 .s_percent = 0,
00166 .skip_pmin = 500,
00167 .skip_pmax = 5000,
00168 .skip_t = 2,
00169 };
00170 #endif
00171 int tv_less(struct timeval *tv_1, struct timeval *tv_2) {
00172 if(tv_1->tv_sec < tv_2->tv_sec)
00173 return 1;
00174 if(tv_1->tv_sec == tv_2->tv_sec)
00175 if(tv_1->tv_usec <= tv_2->tv_usec)
00176 return 1;
00177 return 0;
00178 }
00179
00180 #define GAMMA_COUNT 200
00181
00182 #define GAMMA_TABLE_SIZE 257
00183 #define _GAMMA_TABLE_SIZE 257
00184
00185 static unsigned short gamma_tbl[_GAMMA_TABLE_SIZE * GAMMA_COUNT];
00186
00187 static unsigned short *gamma_ptr = NULL;
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00204 #if 0
00205 struct aexp_window_t window = {
00206 .width = 0,
00207 .height = 0,
00208 .left = 0,
00209 .top = 0,
00210 };
00211 #endif
00212
00213 struct aexp_window_t window_sensor = {
00214 .width = 0,
00215 .height = 0,
00216 };
00218 #if 0
00219
00220 struct aexp_window_t window_set = {
00221 .width = 80,
00222 .height = 80,
00223 .left = 50,
00224 .top = 50,
00225 };
00226 #endif
00227 atomic_t image_new;
00228 atomic_t image_reprogrammed;
00229 DECLARE_MUTEX(image_lock);
00230 atomic_t sensor_window;
00231
00232 struct hist_sensor_t sensor_desc;
00233
00234
00235
00236
00237
00238 static int hist__open(struct inode *inode, struct file *filp);
00239 static int hist__release(struct inode *inode, struct file *filp);
00240 static int hist__ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
00241 static int hist__mmap(struct file *filp, struct vm_area_struct *vma);
00242
00243 static struct file_operations hist__fops = {
00244 owner: THIS_MODULE,
00245 open: hist__open,
00246 release: hist__release,
00247 ioctl: hist__ioctl,
00248 mmap: hist__mmap,
00249 };
00250
00251 static int autoexp__open(struct inode *inode, struct file *filp);
00252 static int autoexp__release(struct inode *inode, struct file *filp);
00253 static ssize_t autoexp__write(struct file *filp, const char *buf, size_t count, loff_t *offp);
00254 static int autoexp__ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
00255 static int autoexp__mmap(struct file *filp, struct vm_area_struct *vma);
00256
00257 static struct file_operations autoexp__fops = {
00258 owner: THIS_MODULE,
00259 open: autoexp__open,
00260 release: autoexp__release,
00261 write: autoexp__write,
00262 ioctl: autoexp__ioctl,
00263 mmap: autoexp__mmap,
00264 };
00265
00266 static int __init hist__init(void) {
00267 int i, j;
00268 int res;
00270 autoexp_set->on = 1;
00271 autoexp_set->width = 80;
00272 autoexp_set->height = 80;
00273 autoexp_set->left = 50;
00274 autoexp_set->top = 50;
00275 autoexp_set->exp_max = HIST_EXP_MAX_START;
00276 autoexp_set->overexp_max = HIST_OVEREXP_MAX_START;
00277 autoexp_set->s_index = 0;
00278 autoexp_set->s_percent = 0;
00279 autoexp_set->exp = HIST_EXP_START;
00280 autoexp_set->skip_pmin = 500;
00281 autoexp_set->skip_pmax = 5000;
00282 autoexp_set->skip_t = 2;
00283
00284 autoexp_state->on = 1;
00285 autoexp_state->exp_max = HIST_EXP_MAX_START;
00286 autoexp_state->overexp_max = HIST_OVEREXP_MAX_START;
00287 autoexp_state->exp = HIST_EXP_START;
00288 autoexp_state->s_index = 0;
00289 autoexp_state->s_percent = 0;
00290 autoexp_state->skip_pmin = 500;
00291 autoexp_state->skip_pmax = 5000;
00292 autoexp_state->skip_t = 2;
00293
00294 gamma_ptr = gamma_tbl;
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 res = register_chrdev(HIST_MAJOR, "hist", &hist__fops);
00320 if(res < 0) {
00321 printk(KERN_ERR "hist: couldn't get a major number.\n");
00322 return res;
00323 }
00324
00325 buf[0].buf = hb_1;
00326 buf[1].buf = hb_2;
00327 for(i = 0; i < BUF_C; i++) {
00328 buf[i].tv.tv_sec = 0;
00329 buf[i].tv.tv_usec = 0;
00330 init_MUTEX(&buf[i].lock);
00331 }
00332 gamma[0].buf = gamma_table_1;
00333 gamma[1].buf = gamma_table_2;
00334 gamma[0].tv.tv_sec = 0;
00335 gamma[0].tv.tv_usec = 0;
00336 gamma[1].tv.tv_sec = 0;
00337 gamma[1].tv.tv_usec = 1;
00338 tv_gamma.tv_sec = 0;
00339 tv_gamma.tv_usec = 0;
00340 tv_gamma_hb_0.tv_sec = 0;
00341 tv_gamma_hb_0.tv_usec = 0;
00342 printk("hist: init ok\n");
00343
00344 res = register_chrdev(AUTOEXP_MAJOR, "autoexp", &autoexp__fops);
00345 if(res < 0) {
00346 printk(KERN_ERR "autoexp: couldn't get a major number.\n");
00347 return res;
00348 }
00349
00350 for(i = 0; i < 4; i++)
00351 for(j = 0; j < 256; j++)
00352 hb_0[i * 256 + j] = j;
00353 for(i = 0; i < 6; i++)
00354 for(j = 0; j < 256; j++) {
00355 gamma_table[i * 256 + j] = j + (j << 8);
00356 gamma_table_1[i * 256 + j] = j + (j << 8);
00357 gamma_table_2[i * 256 + j] = j + (j << 8);
00358 }
00359
00360 atomic_set(&sensor_refresh, 1);
00361 return res;
00362 }
00363
00364 static void __exit hist__exit(void) {
00365 unregister_chrdev(HIST_MAJOR, "autoexp");
00366 printk("autoexp: exit ok\n");
00367 unregister_chrdev(HIST_MAJOR, "hist");
00368 printk("hist: exit ok\n");
00369
00370
00371 }
00372
00373 module_init(hist__init);
00374 module_exit(hist__exit);
00375
00376
00377
00378
00379
00380
00381
00382 int hist__open(struct inode *inode, struct file *filp) {
00383 if(down_trylock(&iface_lock))
00384 return -EBUSY;
00385 atomic_set(&autoexp_on, 1);
00386 if(autoexp_state->on)
00387 atomic_set(&autoexp_enable, 1);
00388 printk("/dev/hist: open()\r\n");
00389 return 0;
00390 }
00391
00392 int hist__release(struct inode *inode, struct file *filp) {
00393 printk("/dev/hist: release()\r\n");
00394 up(&iface_lock);
00395
00396 atomic_set(&autoexp_on, 0);
00397 atomic_set(&autoexp_enable, 0);
00398 atomic_set(&image_new, 0);
00399 atomic_set(&sensor_window, 0);
00400 init_MUTEX(&sensor_lock);
00401 return 0;
00402 }
00403
00404 int hist__ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) {
00405 int i;
00406 struct autoexp_t set;
00407 struct autoexp_log_t log;
00408
00409 switch(_IOC_TYPE(cmd)) {
00410 case IOC_HIST_SET:
00411 copy_from_user(&set, (const void *)arg, sizeof(set));
00412
00413 if(down_interruptible(&sensor_lock))
00414 return -EFAULT;
00415 if(set.exp != 0) {
00416 if(first_exp >= 3) {
00417 sensor_desc.exposure = set.exp;
00418 autoexp_set->exp = set.exp;
00419 atomic_set(&sensor_refresh, 1);
00420 }
00421 }
00422 up(&sensor_lock);
00423
00424
00425
00426
00427 if(down_interruptible(&image_lock) == 0) {
00428 if(aexp_window_set->width != set.width || aexp_window_set->height != set.height || aexp_window_set->left != set.left || aexp_window_set->top != set.top) {
00429 if(set.width != HIST_NOT_CHANGE)
00430 aexp_window_set->width = set.width;
00431 if(set.height != HIST_NOT_CHANGE)
00432 aexp_window_set->height = set.height;
00433 if(set.left != HIST_NOT_CHANGE)
00434 aexp_window_set->left = set.left;
00435 if(set.top != HIST_NOT_CHANGE)
00436 aexp_window_set->top = set.top;
00437 atomic_set(&image_new, 1);
00438 }
00439 up(&image_lock);
00440 }
00441
00442 break;
00443 case IOC_HIST_SET_LOG:
00444 copy_from_user(&log, (const void *)arg, sizeof(log));
00445 down(&ae_log_lock);
00446 if(ae_log_p == ae_log_buf)
00447 ae_log_p = &ae_log_buf[LOG_C - 1];
00448 else
00449 ae_log_p--;
00450 if(ae_log_c < LOG_C)
00451 ae_log_c++;
00452 port_csp0_addr[X313_WA_RTC_LATCH] = 0xFF;
00453 log.tv_sec = port_csp0_addr[X313_RA_RTC_SEC];
00454 log.tv_usec = port_csp0_addr[X313_RA_RTC_USEC];
00455 memcpy((void *)ae_log_p, (void *)&log, sizeof(struct autoexp_log_t));
00456 up(&ae_log_lock);
00457 break;
00458 case IOC_HIST_GET:
00459
00460 while(1) {
00461
00462 i = 0;
00463 down(&autoexp_conf_lock);
00464 if(autoexp_conf_new) {
00465 autoexp_conf_new = 0;
00466
00467 copy_to_user((void *)arg, autoexp_set, sizeof(*autoexp_set));
00468 i = 1;
00469 }
00470 up(&autoexp_conf_lock);
00471 if(i != 0)
00472 return REZ_HIST_CONF;
00473
00474 for(i = 0; i < BUF_C; i++) {
00475 if(down_trylock(&buf[i].lock))
00476 continue;
00477 if(buf[i].tv.tv_sec == 0 && buf[i].tv.tv_usec == 0) {
00478 up(&buf[i].lock);
00479 continue;
00480 }
00481
00482 filp->private_data = (void *)&buf[i];
00483 return REZ_HIST_TABLE;
00484 }
00485 interruptible_sleep_on(&wq_hist);
00486 }
00487 break;
00488 default:
00489 return -EFAULT;
00490 }
00491 return 0;
00492 }
00493
00494 static void hist__vma_open(struct vm_area_struct *vma);
00495 static void hist__vma_close(struct vm_area_struct *vma);
00496 static struct vm_operations_struct hist__vm_ops = {
00497 .open = hist__vma_open,
00498 .close = hist__vma_close,
00499 };
00500
00501 int hist__mmap(struct file *filp, struct vm_area_struct *vma) {
00502 int res = 0;
00503 struct buf_t *b;
00504
00505 b = (struct buf_t *)filp->private_data;
00506 if(b == NULL)
00507 return -EFAULT;
00508 if(b->tv.tv_sec == 0 && b->tv.tv_usec == 0)
00509 return -EFAULT;
00510 vma->vm_private_data = filp->private_data;
00511 vma->vm_ops = &hist__vm_ops;
00512
00513
00514
00515
00516 res = remap_pfn_range(vma,vma->vm_start, virt_to_phys(b->buf) >> PAGE_SHIFT,vma->vm_end-vma->vm_start,vma->vm_page_prot);
00517
00518 hist__vma_open(vma);
00519 return res;
00520 }
00521
00522 void hist__vma_open(struct vm_area_struct *vma) {
00523 }
00524
00525 void hist__vma_close(struct vm_area_struct *vma) {
00526 struct buf_t *b;
00527 b = (struct buf_t *)vma->vm_private_data;
00528 b->tv.tv_sec = 0;
00529 b->tv.tv_usec = 0;
00530 up(&b->lock);
00531 }
00532
00533
00534
00535
00536
00537
00538 #define STEP_INIT 0x00
00539 #define STEP_1 0x01
00540 #define STEP_2 0x02
00541 #define STEP_3 0x03
00542 #define STEP_4 0x04
00543
00544
00545
00546 void hist_irq(unsigned long src) {
00547 static int step = STEP_INIT;
00548
00549
00550 int i;
00551 int flag;
00552
00553 int ae_on = 0;
00554 struct timeval tv;
00555
00556 struct buf_t *b;
00557 unsigned short *_g;
00558 struct gamma_t *g_1;
00559 struct gamma_t *g_2;
00560
00561 do_gettimeofday(&tv);
00562
00563
00564 if(atomic_read(&autoexp_enable) != 0)
00565 ae_on = 1;
00566
00567
00568
00569
00570 if(atomic_read(&sensor_window) != 0) {
00571 atomic_set(&sensor_window, 0);
00572 step = STEP_1;
00573 }
00574 if(atomic_read(&image_new) != 0) {
00575
00576 if(!down_trylock(&image_lock)) {
00577 atomic_set(&image_new, 0);
00578
00579 aexp_window->width = (window_sensor.width * aexp_window_set->width) / 100;
00580 aexp_window->left = ((window_sensor.width - aexp_window->width) * aexp_window_set->left) / 100;
00581 aexp_window->left += 2;
00582 aexp_window->height = (window_sensor.height * aexp_window_set->height) / 100;
00583 aexp_window->top = ((window_sensor.height - aexp_window->height) * aexp_window_set->top) / 100;
00584 aexp_window->top += 2;
00585 aexp_window->top &= 0xFFFE;
00586
00587 if(aexp_window->width != 0 && aexp_window->height != 0) {
00588 port_csp0_addr[X313_WA_HIST_SIZE] = (((aexp_window->height - 1) & 0xFFFF) << 16) + ((aexp_window->width - 1) & 0xFFFF);
00589 port_csp0_addr[X313_WA_HIST_POS] = ((aexp_window->top & 0xFFFF) << 16) + (aexp_window->left & 0xFFFF);
00590 }
00591 if(step != STEP_INIT)
00592 step = STEP_2;
00593 else
00594 step = STEP_1;
00595 up(&image_lock);
00596 }
00597 }
00598
00599
00600
00601
00602 if(ae_on) {
00603 if(atomic_read(&sensor_refresh) != 0) {
00604 if(program_sensor_exposition() != 0)
00605 return;
00606 atomic_set(&sensor_refresh, 0);
00607 step = STEP_1;
00608 }
00609 }
00610
00611
00612
00613
00614
00615 if(step == STEP_4) {
00616 for(i = 0; i < 256 * 4; i++) {
00617 port_csp0_addr[X313_WA_HIST_ADDR] = i;
00618 hb_0[i] = port_csp4_addr[X313_RA_HIST_DATA];
00619 }
00620 memcpy(((void *)hb_0) + OFFSET_HIST_C, &c_hist, 4);
00621 c_hist++;
00622
00623 if(tv_less(&tv_gamma_hb_0, &tv_gamma)) {
00624 if(!down_trylock(&gamma_lock)) {
00625 memcpy(((void *)hb_0) + 256 * 4 * 4, (void *)gamma_table, 256 * 6 * 2);
00626
00627 tv_gamma_hb_0 = tv;
00628 up(&gamma_lock);
00629 }
00630 }
00631 }
00632
00633
00634
00635
00636
00637
00638
00639 switch(step) {
00640
00641 case STEP_INIT:
00642 break;
00643
00644 case STEP_1:
00645 step = STEP_2;
00646 break;
00647
00648 case STEP_2:
00649 step = STEP_3;
00650 break;
00651
00652 case STEP_3:
00653 step = STEP_4;
00654 break;
00655
00656 case STEP_4:
00657 if(ae_on == 0)
00658 break;
00659
00660 flag = 1;
00661 for(i = 0; i < BUF_C; i++) {
00662 if(down_trylock(&buf[i].lock))
00663 continue;
00664 flag = 0;
00665 b = &buf[i];
00666 _g = (unsigned short *)(((void *)b->buf) + 1024 * 4);
00667 memcpy((void *)b->buf, (void *)hb_0, 256 * 4 * 4);
00668 b->tv = tv;
00669
00670 if(tv_less(&gamma[0].tv, &gamma[1].tv)) {
00671 g_1 = &gamma[0];
00672 g_2 = &gamma[1];
00673 } else {
00674 g_1 = &gamma[1];
00675 g_2 = &gamma[0];
00676 }
00677 if(g_1->tv.tv_sec == 0)
00678 g_1 = g_2;
00679 else {
00680 if(tv_less(&b->tv, &g_2->tv))
00681 g_1 = g_1;
00682 else
00683 g_1 = g_2;
00684 }
00685 memcpy((void *)_g, (void *)g_1->buf + 256 * 4 * 2, 256 * 2 * 2);
00686
00687 up(&b->lock);
00688 break;
00689 }
00690
00691 if(flag == 0)
00692 wake_up_interruptible(&wq_hist);
00693
00694
00695
00696
00697
00698 break;
00699 default:
00700 break;
00701 }
00702
00703 return;
00704 }
00705
00706 void hist_irq__(unsigned long src) {
00707
00708 static int step = STEP_INIT;
00709
00710 unsigned long i;
00711 struct buf_t *b;
00712 static unsigned long _width = 0;
00713 static unsigned long _height = 0;
00714 unsigned short *_g;
00715 struct gamma_t *g_1;
00716 struct gamma_t *g_2;
00717 struct timeval tv;
00718
00719 static int src_done_c = 0;
00720 int in_busy_skip = 1;
00721
00723 if(src == IRQ_SRC_VACT)
00724 src_done_c = 0;
00725 else {
00726 src_done_c++;
00727 if(src_done_c < 2)
00728 return;
00729 src_done_c--;
00730 }
00731 do_gettimeofday(&tv);
00732
00733
00734 for(i = 0; i < 256 * 4; i++) {
00735 port_csp0_addr[X313_WA_HIST_ADDR] = i;
00736 hb_0[i] = port_csp4_addr[X313_RA_HIST_DATA];
00737 if((hb_0[i] & 0xFFFC0000) != 0x00000000)
00738 printk("hist[%ld] == 0x%08lX (0x%08lX) - %d:%d\r\n", i, hb_0[i], hb_0[i] & 0xFFFC0000, (int) tv.tv_sec, (int) tv.tv_usec);
00739 }
00740 memcpy(((void *)hb_0) + OFFSET_HIST_C, &c_hist, 4);
00741 c_hist++;
00742
00743 if(tv_less(&tv_gamma_hb_0, &tv_gamma)) {
00744 if(down_trylock(&gamma_lock)) {
00745 memcpy(((void *)hb_0) + 256 * 4 * 4, (void *)gamma_table, 256 * 6 * 2);
00746 do_gettimeofday(&tv_gamma_hb_0);
00747 up(&gamma_lock);
00748 }
00749 }
00750
00751 if(atomic_read(&autoexp_enable) == 0) {
00752
00753 if(step != STEP_INIT)
00754 step = STEP_1;
00755 return;
00756 }
00757
00758 restep:
00759 switch(step) {
00760
00761 case STEP_INIT:
00762 if(atomic_read(&image_reprogrammed) != 0)
00763 atomic_inc(&image_reprogrammed);
00764 if(atomic_read(&image_reprogrammed) == 3) {
00765 atomic_set(&image_reprogrammed, 0);
00766 step = STEP_1;
00767
00768 goto restep;
00769 }
00770 break;
00771
00772
00773
00774 case STEP_1:
00775 if(atomic_read(&image_reprogrammed) == 1) {
00776 step = STEP_INIT;
00777 goto restep;
00778 }
00779
00780
00781 _width = aexp_window->width;
00782 _height = aexp_window->height;
00783 if(atomic_read(&image_new) != 0) {
00784
00785 if(down_trylock(&image_lock))
00786 break;
00787 atomic_set(&image_new, 0);
00788
00789 aexp_window->width = (window_sensor.width * aexp_window_set->width) / 100;
00790 aexp_window->left = ((window_sensor.width - aexp_window->width) * aexp_window_set->left) / 100;
00791 aexp_window->left += 2;
00792 aexp_window->height = (window_sensor.height * aexp_window_set->height) / 100;
00793 aexp_window->top = ((window_sensor.height - aexp_window->height) * aexp_window_set->top) / 100;
00794 aexp_window->top += 2;
00795 aexp_window->top &= 0xFFFE;
00796
00797 if(aexp_window->width != 0 && aexp_window->height != 0) {
00798 port_csp0_addr[X313_WA_HIST_SIZE] = (((aexp_window->height - 1) & 0xFFFF) << 16) + ((aexp_window->width - 1) & 0xFFFF);
00799 port_csp0_addr[X313_WA_HIST_POS] = ((aexp_window->top & 0xFFFF) << 16) + (aexp_window->left & 0xFFFF);
00800 }
00801 up(&image_lock);
00802 }
00803
00804
00805 if(atomic_read(&sensor_refresh) == 0)
00806 return;
00807 if(program_sensor_exposition() != 0)
00808 break;
00809
00810 atomic_set(&image_reprogrammed, 0);
00811 step = STEP_2;
00812
00813
00814
00815
00816
00817
00818 break;
00819
00820
00821
00822 case STEP_2:
00823 if(atomic_read(&image_reprogrammed) != 0) {
00824 step = STEP_1;
00825 goto restep;
00826 }
00827 step = STEP_3;
00828 break;
00829
00830
00831
00832 case STEP_3:
00833 if(atomic_read(&image_reprogrammed) != 0) {
00834 step = STEP_1;
00835 goto restep;
00836 }
00837 step = STEP_4;
00838 break;
00839
00840
00841
00842 case STEP_4:
00843
00844 if(_width == 0 || _height == 0) {
00845 step = STEP_1;
00846 return;
00847 }
00848
00849 for(i = 0; i < BUF_C; i++) {
00850 if(down_trylock(&buf[i].lock))
00851 continue;
00852 in_busy_skip = 0;
00853 b = &buf[i];
00854 _g = (unsigned short *)(((void *)b->buf) + 1024 * 4);
00855 memcpy((void *)b->buf, (void *)hb_0, 256 * 4 * 4);
00856 b->tv = tv;
00857
00858 if(tv_less(&gamma[0].tv, &gamma[1].tv)) {
00859 g_1 = &gamma[0];
00860 g_2 = &gamma[1];
00861 } else {
00862 g_1 = &gamma[1];
00863 g_2 = &gamma[0];
00864 }
00865 if(g_1->tv.tv_sec == 0)
00866 g_1 = g_2;
00867 else {
00868 if(tv_less(&b->tv, &g_2->tv))
00869 g_1 = g_1;
00870 else
00871 g_1 = g_2;
00872 }
00873 memcpy((void *)_g, (void *)g_1->buf + 256 * 4 * 2, 256 * 2 * 2);
00874
00875 up(&b->lock);
00876 break;
00877 }
00878
00879 if(in_busy_skip == 0) {
00880 wake_up_interruptible(&wq_hist);
00881 step = STEP_1;
00882 }
00883 break;
00884 default:
00885 return;
00886 }
00887 }
00888
00889 struct hist_sensor_t *hist_sensor_lock(void) {
00890 if(atomic_read(&autoexp_enable) == 0)
00891 return NULL;
00892 if(down_interruptible(&sensor_lock))
00893 return NULL;
00894 if(first_exp < 3) {
00895 first_exp++;
00896
00897 sensor_desc.exposure = autoexp_state->exp;
00898 }
00899 return &sensor_desc;
00900 }
00901
00902 void hist_sensor_unlock(void) {
00903 up(&sensor_lock);
00904 }
00905
00906 void hist_image_exp(unsigned long exp) {
00907 if(first_exp < 3) {
00908 autoexp_set->exp = exp;
00909 autoexp_state->exp = exp;
00910
00911 }
00912 }
00913
00914 void hist_image_size(unsigned long width, unsigned long height) {
00915 if(window_sensor.width != width || window_sensor.height != height) {
00916 down(&image_lock);
00917 window_sensor.width = width - 4;
00918 window_sensor.height = height - 4;
00919 atomic_set(&image_new, 1);
00920
00921 atomic_set(&sensor_window, 1);
00922 up(&image_lock);
00923 }
00924 }
00925
00926 void window2state (void) {
00927 autoexp_state->width = aexp_window_set->width;
00928 autoexp_state->height = aexp_window_set->height;
00929 autoexp_state->left = aexp_window_set->left;
00930 autoexp_state->top = aexp_window_set->top;
00931
00932 autoexp_state->exp = get_imageParamsR(P_EXPOS);
00933
00934 }
00935 void get_autoexposure_parameters(void)
00936 {
00937 if(down_interruptible(&autoexp_conf_lock) == 0) {
00938
00939 window2state();
00940 up(&autoexp_conf_lock);
00941 }
00942 }
00943
00944
00945 void set2state(void)
00946 {
00947 autoexp_conf_new = 1;
00948 if(autoexp_set->on != 0 && autoexp_set->on != HIST_NOT_CHANGE) {
00949 autoexp_state->on = 1;
00950
00951 atomic_set(&autoexp_enable, 1);
00952 }
00953 if(autoexp_set->on == 0) {
00954 autoexp_state->on = 0;
00955 atomic_set(&autoexp_enable, 0);
00956 exposition_unlock();
00957
00958 }
00959 if(autoexp_set->s_index != HIST_NOT_CHANGE)
00960 autoexp_state->s_index = autoexp_set->s_index;
00961 if(autoexp_set->s_percent != HIST_NOT_CHANGE)
00962 autoexp_state->s_percent = autoexp_set->s_percent;
00963 if(autoexp_set->overexp_max != HIST_NOT_CHANGE)
00964 autoexp_state->overexp_max = autoexp_set->overexp_max;
00965 if(autoexp_set->exp_max != HIST_NOT_CHANGE)
00966 autoexp_state->exp_max = autoexp_set->exp_max;
00967 if(autoexp_set->skip_pmin != HIST_NOT_CHANGE)
00968 autoexp_state->skip_pmin = autoexp_set->skip_pmin;
00969 if(autoexp_set->skip_pmax != HIST_NOT_CHANGE)
00970 autoexp_state->skip_pmax = autoexp_set->skip_pmax;
00971 if(autoexp_set->skip_t != HIST_NOT_CHANGE)
00972 autoexp_state->skip_t = autoexp_set->skip_t;
00973 }
00974 void set_autoexposure_parameters(void)
00975 {
00976 if(down_interruptible(&autoexp_conf_lock) == 0) {
00977
00978 set2state();
00979 up(&autoexp_conf_lock);
00980 wake_up_interruptible(&wq_hist);
00981 }
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 void __add_gamma(unsigned short index, unsigned short *table) {
01001 unsigned short *ptr;
01002 unsigned short value;
01003 int i;
01004
01005 if(index >= GAMMA_COUNT) {
01006 printk("gamma fault! index == %d\r\n", index);
01007 return;
01008 }
01009 value = table[0];
01010 if(value == 0 || value > GAMMA_COUNT) {
01011 printk("gamma fault! value == %d\r\n", value);
01012 return;
01013 }
01014 ptr = gamma_ptr + (value - 1) * GAMMA_TABLE_SIZE;
01015 for(i = 0; i < GAMMA_TABLE_SIZE; i++)
01016 ptr[i] = (table[i + 1] >> 8) + (0xFF00 & (table[i + 1] << 8));
01017 }
01018
01019
01020
01021
01022
01023
01024 extern unsigned long *ccam_dma;
01025
01026 #define _WRITE_GAMMA 0x10
01027 #define _WRITE_GAMMA_BUF (2 + _GAMMA_TABLE_SIZE * 2)
01028
01029 struct autoexp_context_t {
01030 int write;
01031 int count;
01032 unsigned char *buf;
01033 int buf_fill;
01034 int c;
01035 };
01036
01037 static int autoexp__open(struct inode *inode, struct file *filp) {
01038 filp->private_data = NULL;
01039 return 0;
01040 }
01041
01042 static int autoexp__release(struct inode *inode, struct file *filp) {
01043 if(filp->private_data)
01044 kfree(filp->private_data);
01045 return 0;
01046 }
01047
01048 static int fill_buffer(int c_query, const char *buf, size_t count, size_t *offset, struct autoexp_context_t *c) {
01049 int r = 0;
01050 int len;
01051
01052 len = c_query - c->buf_fill;
01053 if(len > count)
01054 len = count;
01055 r = copy_from_user((void *)&c->buf[c->buf_fill], &buf[*offset], len);
01056 c->buf_fill += len;
01057 *offset += len;
01058 return len;
01059 }
01060
01061 static ssize_t autoexp__write(struct file *filp, const char *buf, size_t count, loff_t *offp) {
01062 struct autoexp_context_t *c;
01063 size_t offset = 0;
01064 size_t ret = count;
01065
01066 c = (struct autoexp_context_t *)filp->private_data;
01067 if(c == NULL) {
01068 return -EFAULT;
01069
01070 }
01071 switch(c->write) {
01072 case _WRITE_GAMMA:
01073 while(count) {
01074 count -= fill_buffer(_WRITE_GAMMA_BUF, buf, count, &offset, c);
01075 if(c->buf_fill == _WRITE_GAMMA_BUF) {
01076 __add_gamma(c->c, (unsigned short *)c->buf);
01077 c->c++;
01078 c->buf_fill = 0;
01079 }
01080 }
01081 break;
01082 default: {
01083
01084 return -EFAULT;
01085 }
01086 }
01087 *offp += ret;
01088 return ret;
01089 }
01090
01091 static int autoexp__ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) {
01092 struct autoexp_context_t *c;
01093 int ae_c;
01094 int r, t;
01095
01096 switch(_IOC_TYPE(cmd)) {
01097 case IOC_AUTOEXP_GET_LOG:
01098 ae_c = _IOC_NR(cmd);
01099 if(ae_c > LOG_C)
01100 return -EFAULT;
01101 if(ae_log_c == 0)
01102 return -EFAULT;
01103 if(down_interruptible(&ae_log_lock))
01104 return -EFAULT;
01105 if(ae_c > ae_log_c)
01106 ae_c = ae_log_c;
01107 r = ae_c;
01108 if(ae_log_c == LOG_C) {
01109 t = &ae_log_buf[LOG_C] - ae_log_p;
01110 if(ae_c <= t) {
01111 copy_to_user((void *)arg, (void *)ae_log_p, ae_c * sizeof(struct autoexp_log_t));
01112 } else {
01113 copy_to_user((void *)arg, (void *)ae_log_p, t * sizeof(struct autoexp_log_t));
01114 ae_c -= t;
01115 copy_to_user((void *)(arg + sizeof(struct autoexp_log_t) * t), (void *)ae_log_buf, ae_c * sizeof(struct autoexp_log_t));
01116 }
01117 } else {
01118 copy_to_user((void *)arg, (void *)ae_log_p, ae_c * sizeof(struct autoexp_log_t));
01119 }
01120 up(&ae_log_lock);
01121 return r;
01122 case IOC_AUTOEXP_SET:
01123
01124
01125 if(down_interruptible(&autoexp_conf_lock) == 0) {
01126
01127 copy_from_user(autoexp_set, (const void *)arg, sizeof(*autoexp_set));
01128 set2state();
01129 #if 0
01130 autoexp_conf_new = 1;
01131 if(autoexp_set->on != 0 && autoexp_set->on != HIST_NOT_CHANGE) {
01132 autoexp_state->on = 1;
01133
01134 atomic_set(&autoexp_enable, 1);
01135 }
01136 if(autoexp_set->on == 0) {
01137 autoexp_state->on = 0;
01138 atomic_set(&autoexp_enable, 0);
01139 exposition_unlock();
01140
01141 }
01142 if(autoexp_set->s_index != HIST_NOT_CHANGE)
01143 autoexp_state->s_index = autoexp_set->s_index;
01144 if(autoexp_set->s_percent != HIST_NOT_CHANGE)
01145 autoexp_state->s_percent = autoexp_set->s_percent;
01146 if(autoexp_set->overexp_max != HIST_NOT_CHANGE)
01147 autoexp_state->overexp_max = autoexp_set->overexp_max;
01148 if(autoexp_set->exp_max != HIST_NOT_CHANGE)
01149 autoexp_state->exp_max = autoexp_set->exp_max;
01150 if(autoexp_set->skip_pmin != HIST_NOT_CHANGE)
01151 autoexp_state->skip_pmin = autoexp_set->skip_pmin;
01152 if(autoexp_set->skip_pmax != HIST_NOT_CHANGE)
01153 autoexp_state->skip_pmax = autoexp_set->skip_pmax;
01154 if(autoexp_set->skip_t != HIST_NOT_CHANGE)
01155 autoexp_state->skip_t = autoexp_set->skip_t;
01156 #endif
01157 up(&autoexp_conf_lock);
01158 wake_up_interruptible(&wq_hist);
01159 }
01160
01161 break;
01162 case IOC_AUTOEXP_GET:
01163
01164 if(down_interruptible(&autoexp_conf_lock) == 0) {
01165 window2state();
01166 #if 0
01167
01168
01169
01170
01172 autoexp_state->width = aexp_window_set->width;
01173 autoexp_state->height = aexp_window_set->height;
01174 autoexp_state->left = aexp_window_set->left;
01175 autoexp_state->top = aexp_window_set->top;
01176
01177 autoexp_state->exp = get_imageParamsR(P_EXPOS);
01178 #endif
01179
01180 copy_to_user((void *)arg, autoexp_state, sizeof(*autoexp_state));
01181 up(&autoexp_conf_lock);
01182 }
01183
01184 break;
01185 case IOC_AUTOEXP_GAMMA_TABLE:
01186
01187 c = (struct autoexp_context_t *)kmalloc(sizeof(struct autoexp_context_t), GFP_KERNEL);
01188 if(c == NULL) {
01189 printk("fail kmalloc context\r\n");
01190 return -EFAULT;
01191 }
01192 c->write = _WRITE_GAMMA;
01193 c->count = 0;
01194 c->c = 0;
01195 c->buf_fill = 0;
01196 c->buf = (unsigned char *)ccam_dma;
01197 filp->private_data = (void *)c;
01198 break;
01199 default:
01200 return -EFAULT;
01201 }
01202 return 0;
01203 }
01204
01205 static void autoexp__vma_close(struct vm_area_struct *vma);
01206 static struct vm_operations_struct autoexp__vm_ops = {
01207 .close = autoexp__vma_close,
01208 };
01209
01210 int autoexp__mmap(struct file *filp, struct vm_area_struct *vma) {
01211
01212 vma->vm_ops = &autoexp__vm_ops;
01213 if(vma->vm_start == 0x00) {
01214
01215
01216 return remap_pfn_range(vma,vma->vm_start, virt_to_phys(hb_0) >> PAGE_SHIFT,vma->vm_end - vma->vm_start, vma->vm_page_prot);
01217 }
01218 if(vma->vm_start == 0x10000000) {
01219
01220
01221 return remap_pfn_range(vma,vma->vm_start, virt_to_phys(gamma_table) >> PAGE_SHIFT,vma->vm_end - vma->vm_start, vma->vm_page_prot);
01222 }
01223 return -EFAULT;
01224 }
01225
01226 void autoexp__vma_close(struct vm_area_struct *vma) {
01227
01228 }
01229
01230
01231
01232
01233
01234
01235 static unsigned long _gamma = 0xFFFFFFFF;
01236 static unsigned long _black = 0x00;
01237
01238 static unsigned short _scale_red = 0x0100;
01239 static unsigned short _scale_green = 0x0100;
01240 static unsigned short _scale_blue = 0x0100;
01241 static unsigned short _scale_green1 = 0x0100;
01242
01243 #define FPGA333_TABLE_ADDR_GAMMA 0x0400
01244
01245
01246
01247 unsigned long gamma_v(unsigned long index, unsigned short *table) {
01248 unsigned long v1, v2;
01249 unsigned long i;
01250 unsigned long step;
01251 unsigned long delta;
01252
01253 if(index >= 0xFF00)
01254 return 0xFFFF;
01255 i = index >> 8;
01256 v1 = table[i];
01257 v2 = table[i + 1];
01258 step = index & 0xFF;
01259 delta = v2 - v1;
01260 delta = (step * delta) >> 8;
01261 v1 += delta;
01262 if(v1 > 0xFFFF)
01263 v1 = 0xFFFF;
01264 return v1;
01265 }
01266
01267 unsigned short _gamma_table_or[GAMMA_TABLE_SIZE];
01268 unsigned short _gamma_table[256 * 6];
01269 unsigned long gamma_table_to_fpga[256 * 4];
01270
01271 void set_gamma(unsigned long __gamma, unsigned long black, unsigned long scale_red, unsigned long scale_green, unsigned long scale_blue, unsigned long scale_green1) {
01272 u16 *g;
01273 u32 v;
01274 int i;
01275 int j;
01276 int k;
01277 int l;
01278 long x1, y1, x2, y2, a, b;
01279 long value;
01280 unsigned long scale = 0x100;
01281 unsigned short *_gt;
01282
01283
01284
01285
01286
01287
01288
01289
01290 struct timeval tv;
01291 int base, diff, d;
01292
01293 MD1(printk("!!! ----->>>>>> set gamma: 0x%08X <<<<<<<<---------- !!!!!!!!!!\n", __gamma));
01294
01295
01296
01297 if(__gamma >= 200)
01298 __gamma = 199;
01299 if(black > 32)
01300 black = 32;
01301 if(black > 256)
01302 black = 0;
01303 if(_gamma == __gamma && black == _black && scale_red == _scale_red && scale_green == _scale_green && scale_blue == _scale_blue && scale_green1 == _scale_green1)
01304 return;
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01322
01323
01324
01325
01326
01327
01328
01329
01330 _gamma = __gamma;
01331 _black = black;
01332 _scale_red = scale_red;
01333 _scale_green = scale_green;
01334 _scale_blue = scale_blue;
01335 _scale_green1 = scale_green1;
01336 g = (u16 *)(gamma_ptr + (_gamma * _GAMMA_TABLE_SIZE));
01337
01338 l = 0;
01339 int skip_interpolation = 0;
01340 if(_black == 0 && scale_red == 0x100 && scale_green == 0x100 && scale_blue == 0x100 && scale_green1 == 0x100) {
01341
01342 skip_interpolation = 1;
01343 }
01344 for(j = 0; j < 4; j++) {
01345 if(skip_interpolation) {
01346
01347 for(i = 0; i < GAMMA_TABLE_SIZE; i++) {
01348 if(i > 0) {
01349 _gamma_table[j * 256 + i - 1] = g[i - 1] & 0xFFFF;
01350 }
01351 _gamma_table_or[i] = g[i] & 0xFFFF;
01352 }
01353 } else {
01354 switch(j) {
01355 case 0: scale = scale_red; break;
01356 case 1: scale = scale_green; break;
01357 case 2: scale = scale_green1; break;
01358 case 3: scale = scale_blue; break;
01359 }
01360
01361
01362 x1 = (_black << 8);
01363 y1 = 0;
01364 x2 = 0xFFFFFF / scale;
01365 y2 = 0xFFFF;
01366 a = ((y2 - y1) << 8) / (x2 - x1);
01367 b = ((a * x2) >> 8) - y2;
01368 for(i = 0; i < GAMMA_TABLE_SIZE; i++) {
01369 if(i <= _black) {
01370 value = 0x00;
01371 } else {
01372 v = (a * ((i << 8) + i)) >> 8;
01373 value = gamma_v(v - b, g);
01374 if(value > 0xFFFF)
01375 value = 0xFFFF;
01376 }
01377 if(i + 1 == GAMMA_TABLE_SIZE)
01378 value = 0xFFFF;
01379 if(i > 0) {
01380
01381 _gamma_table[j * 256 + i - 1] = value & 0xFFFF;
01382 }
01383 _gamma_table_or[i] = (value & 0xFFFF) >> 6;
01384 }
01385 }
01386
01387 for(i = 0; i < 256; i++) {
01388 base = _gamma_table_or[i];
01389 diff = _gamma_table_or[i + 1];
01390 diff -= base;
01391 if((diff > 63) || (diff < -64)) {
01392 diff = (diff + 8) >> 4;
01393 d = (base & 0x3ff) | ((diff & 0x7f) << 10) | (1 << 17);
01394 } else {
01395 d = (base & 0x3ff) | ((diff & 0x7f) << 10);
01396 }
01397 gamma_table_to_fpga[l] = d;
01398 l++;
01399 }
01400 }
01401
01403
01404 fpga_table_write(FPGA333_TABLE_ADDR_GAMMA, gamma_table_to_fpga, 256 * 4);
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418 _gt = _gamma_table + 256 * 4;
01419 memset((void *)_gt, 0, 256 * 2);
01420 if(_scale_red < _scale_green && _scale_red < _scale_blue && _scale_red < _scale_green1)
01421 k = 0;
01422 else {
01423 if(_scale_green < _scale_blue && _scale_green < _scale_green1) {
01424 k = 256;
01425 } else {
01426 if(_scale_green1 < _scale_blue) {
01427 k = 512;
01428 } else {
01429 k = 768;
01430 }
01431 }
01432 }
01433
01434
01435 for(i = 0; i < 256; i++)
01436 _gt[_gamma_table[i + k] >> 8] = i << 8;
01437
01438 for(i = 1; i < 256; i++) {
01439 if(_gt[i] == 0) {
01440 for(j = i; j < 256; j++) {
01441 if(_gt[j] != 0)
01442 break;
01443 }
01444 a = 0x100 / (j - i + 1);
01445 for(; i < j; i++)
01446 _gt[i] = _gt[i - 1] + a;
01447 }
01448 }
01449
01450
01451 _gt = _gamma_table + 256 * 5;
01452 memcpy((void *)_gt, (void *)g, 256 * 2);
01453
01454 do_gettimeofday(&tv);
01455
01456 if(down_interruptible(&gamma_lock) == 0) {
01457 tv_gamma = tv;
01458 memcpy((void *)gamma_table, (void *)_gamma_table, 256 * 6 * 2);
01459 memcpy(((void *)hb_0) + OFFSET_GAMMA_C, &c_gamma, 4);
01460 c_gamma++;
01461 up(&gamma_lock);
01462 }
01463
01464 MD1(printk("gamma... OK!\n"));
01466
01467
01468
01469
01470 }
01471