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 #define P_ACTUAL_WIDTH2 ( get_imageParamsR(P_ACTUAL_WIDTH)+4 )
00066 #define P_ACTUAL_HEIGHT2 ( get_imageParamsR(P_ACTUAL_HEIGHT)+4 )
00067
00068 #include <linux/module.h>
00069 #include <linux/sched.h>
00070 #include <linux/slab.h>
00071 #include <linux/errno.h>
00072 #include <linux/kernel.h>
00073 #include <linux/fs.h>
00074 #include <linux/string.h>
00075 #include <linux/init.h>
00076 #include <linux/autoconf.h>
00077
00078 #include <asm/system.h>
00079
00080 #include <asm/io.h>
00081
00082 #include <asm/irq.h>
00083
00084 #include <asm/delay.h>
00085 #include <asm/uaccess.h>
00086
00087 #include <asm/elphel/c313a.h>
00088
00089 #include "fpgactrl.h"
00090
00091 #include "x3x3.h"
00092 #include "cc3x3.h"
00093 #include "cxsdram.h"
00094
00095 #define D(x)
00096
00097 #define MD3(x)
00098
00099 static int linebuf_fpn[4096];
00100 static int lineinbuf_fpn;
00101 static int linebufdirty_fpn = 0;
00102 static int linebuf_img[4096];
00103 static int lineinbuf_img;
00104
00105
00106 int *x313_fpn_readline(int line, int ignore) {
00107 int ntilex, padlen, sa, nw, n, i, li;
00108
00109 if(line == lineinbuf_fpn)
00110 return linebuf_fpn;
00111 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3)
00112 return NULL;
00113 if(linebufdirty_fpn) {
00114 if (x313_fpn_writeline() < 0)
00115 return NULL;
00116 }
00117 if(ignore)
00118 return linebuf_fpn;
00119 nw = ((P_ACTUAL_WIDTH2 + 1) >> 1);
00120 ntilex = ((nw + 3) >> 2);
00121
00122 padlen = ((ntilex + 31) >> 5);
00123
00124 sa = X313_MAP_FPN + ((padlen * line) << 8);
00125
00126
00127 X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0x3ff, 0xfff);
00128
00129 port_csp0_addr[X313_WA_SD_MODE] |= 0x23;
00130 li = 0;
00131
00132 while (nw > 0) {
00133 i = 1000;
00134 D(printk("wait "));
00135 while (((i--) > 0) && !X313_SR(PIORDY));
00136 udelay(1);
00137 D(printk("ready, i=%d\n", (int) i));
00138 if (i == 0)
00139 return NULL;
00140 n = nw;
00141 if (n > 128)
00142 n = 128;
00143 i = port_csp4_addr[X313_WA_SD_PIOWIN];
00144 for (i = 0; i < n; i++)
00145 linebuf_fpn[li++] = port_csp4_addr[X313_WA_SD_PIOWIN];
00146 nw -= n;
00147 if (nw > 0)
00148 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0;
00149 }
00150 lineinbuf_fpn = line;
00151 return linebuf_fpn;
00152 }
00153
00154 int x313_fpn_writeline(void) {
00155 int ntilex, padlen, sa, nw, n, i, li;
00156
00157 if(linebufdirty_fpn == 0)
00158 return 0;
00159
00160 if(lineinbuf_fpn >= 0) {
00161 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3)
00162 return -1;
00163 nw = ((P_ACTUAL_WIDTH2 + 1) >> 1);
00164 ntilex = ((nw + 3) >> 2);
00165
00166 padlen = ((ntilex + 31) >> 5);
00167
00168 sa = X313_MAP_FPN + ((padlen * lineinbuf_fpn) << 8);
00169
00170 X313_INIT_SDCHAN(3, 0, 1, 0, sa, 0x3ff, 0xfff);
00171
00172
00173 port_csp0_addr[X313_WA_SD_MODE] |= 0x23;
00174 li = 0;
00175
00176 while (nw > 0) {
00177
00178 i = 1000;
00179 D(printk("wait "));
00180 while (((i--) > 0) && !X313_SR(PIORDY));
00181 udelay(1);
00182 D(printk("ready, i=%d\n", (int) i));
00183 if (i == 0)
00184 return -1;
00185
00186 n = nw;
00187 if (n > 128)
00188 n = 128;
00189 for (i = 0; i < n; i++)
00190 port_csp0_addr[X313_WA_SD_PIOWIN] = linebuf_fpn[li++];
00191 nw -= n;
00192 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0;
00193 }
00194
00195
00196
00197
00198
00199
00200 i = 1000;
00201 while (((i--) > 0) && !X313_SR(PIOWEMPTY))
00202 udelay(1);
00203 if (i == 0)
00204 return -EFAULT;
00205 }
00206 linebufdirty_fpn = 0;
00207 return 0;
00208 }
00209
00210
00211 ssize_t x313_fpn_read(struct file * file, char *buf, size_t count, loff_t * off) {
00212 unsigned long p, fsz, y, xb, xbl, left;
00213 char *bp = buf;
00214 char *mp;
00215
00216 MD3(printk("x313_fpn_read, count=%x, off=%x\n", (int) count, (int) off));
00217
00218 p = *off;
00219
00220 fsz = (P_ACTUAL_WIDTH2 * P_ACTUAL_HEIGHT2) << 1;
00221
00222 if((p + count) > fsz) {
00223 count = fsz - p;
00224 }
00225 left = count;
00226 while(left > 0) {
00227
00228
00229 y = (p / P_ACTUAL_WIDTH2) >> 1;
00230
00231 xb = p - y * (P_ACTUAL_WIDTH2 << 1);
00232 xbl = (P_ACTUAL_WIDTH2 << 1) - xb;
00233 if(xbl > left)
00234 xbl = left;
00235 if(!(mp = (char *)x313_fpn_readline(y, 0)))
00236 return -EFAULT;
00237
00238 mp += xb;
00239
00240 if(copy_to_user(bp, mp, xbl))
00241 return -EFAULT;
00242 left -= xbl;
00243 p += xbl;
00244 bp += xbl;
00245 }
00246
00247 *off+=count;
00248 return count;
00249 }
00250
00251 ssize_t x313_fpn_write(struct file * file, const char *buf, size_t count, loff_t * off) {
00252 unsigned long p, fsz, y, xb, xbl, left;
00253 const char *bp = buf;
00254 char *mp;
00255
00256
00257
00258 p=*off;
00259 fsz = (P_ACTUAL_WIDTH2 * P_ACTUAL_HEIGHT2) << 1;
00260 if (p >= fsz)
00261 return -EINVAL;
00262 if ((p + count) > fsz) {
00263 count = fsz - p;
00264 }
00265 left = count;
00266 while (left > 0) {
00267
00268 y = (p / P_ACTUAL_WIDTH2) >> 1;
00269 xb = p - y * (P_ACTUAL_WIDTH2 << 1);
00270 xbl = (P_ACTUAL_WIDTH2 << 1) - xb;
00271 if (xbl > left)
00272 xbl = left;
00273
00274 if (!(mp = (char *) x313_fpn_readline(y, ((xb == 0) && (xbl == (P_ACTUAL_WIDTH2 << 1))))))
00275 return -EFAULT;
00276
00277 mp += xb;
00278 if (copy_from_user(mp, bp, xbl))
00279 return -EFAULT;
00280 left -= xbl;
00281 p += xbl;
00282 bp += xbl;
00283 linebufdirty_fpn = 1;
00284 }
00285
00286 *off+=count;
00287 return count;
00288 }
00289
00290
00291 loff_t x313_fpn_lseek(struct file * file, loff_t offset, int orig) {
00292
00293
00294
00295
00296
00297
00298 unsigned long fsz;
00299
00300 fsz = (P_ACTUAL_WIDTH2 * P_ACTUAL_HEIGHT2) << 1;
00301
00302 MD3(printk("fpn_lseek %x\n", (int) offset));
00303
00304 D(printk("fsdram_lseek\n"));
00305
00306 switch (orig) {
00307 case 0:
00308 file->f_pos = offset;
00309 break;
00310 case 1:
00311 file->f_pos += offset;
00312 break;
00313 case 2:
00314 file->f_pos = fsz + offset;
00315 break;
00316 default:
00317 return -EINVAL;
00318 }
00319
00320
00321 if (file->f_pos < 0) {
00322 file->f_pos = 0;
00323 return (-EOVERFLOW);
00324 }
00325
00326 if (file->f_pos > fsz) {
00327 file->f_pos = fsz;
00328 return (-EOVERFLOW);
00329 }
00330 return (file->f_pos);
00331 }
00332
00333
00334
00335 int *x313_frame_readline(int line) {
00336 int ntilex, padlen, sa, nw, n, i, li;
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 if(line == lineinbuf_img)
00348 return linebuf_img;
00349 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3)
00350 return NULL;
00351 lineinbuf_img = line;
00352 if((get_imageParamsR(P_BITS) == 8) && !get_imageParamsR(P_BGFRAME))
00353 nw = ((P_ACTUAL_WIDTH2 + 3) >> 2);
00354 else
00355 nw = ((P_ACTUAL_WIDTH2 + 1) >> 1);
00356 ntilex = ((nw + 3) >> 2);
00357
00358 padlen = ((ntilex + 31) >> 5);
00359
00360
00361
00362
00363
00364 sa = X313_MAP_FRAME + ((padlen * line) << 8);
00365
00366
00367 X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0x3ff, 0xfff);
00368
00369
00370
00371 port_csp0_addr[X313_WA_SD_MODE] |= 0x23;
00372 li = 0;
00373 while(nw > 0) {
00374 i = 1000;
00375 D(printk("wait "));
00376 while(((i--) > 0) && !X313_SR(PIORDY));
00377 udelay(1);
00378 D(printk("ready, i = %d\n", (int) i));
00379 if(i == 0)
00380 return NULL;
00381 n = nw;
00382 if(n > 128)
00383 n = 128;
00384 i = port_csp4_addr[X313_WA_SD_PIOWIN];
00385 for(i = 0; i < n; i++)
00386
00387 linebuf_img[li++] = port_csp4_addr[X313_WA_SD_PIOWIN];
00388 nw -= n;
00389 if(nw > 0)
00390 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 return linebuf_img;
00448 }
00449
00450 static int lock_flag = 0;
00451
00452 int slock = 0;
00453 wait_queue_head_t vack_wait_queue;
00454
00455 void ch0_lock(void) {
00456 unsigned long t = port_csp0_addr[0x27];
00457 t = t & ~(1 << 2);
00458 port_csp0_addr[0x27] = t;
00459 }
00460
00461 void ch0_dis(void) {
00462
00463 slock = 2;
00464 while(slock == 2)
00465 yield();
00466
00467
00468 }
00469
00470 void ch0_en(void) {
00471 unsigned long t = port_csp0_addr[0x27];
00472 t |= 1 << 2;
00473 port_csp0_addr[0x27] = t;
00474 slock = 0;
00475 }
00476
00477 ssize_t x313_frame_read(struct file * file, char *buf, size_t count, loff_t * off) {
00478 unsigned long p, fsz, y, xb, xbl, left;
00479 char *bp = buf;
00480 char *mp;
00481
00482 if(lock_flag == 0) {
00483 lock_flag = 1;
00484 printk("frame read first time - lock sensor and wait it\r\n");
00485
00486
00487
00488
00489 ch0_dis();
00490 }
00491
00492
00493
00494 p=*off;
00495
00496 fsz = (P_ACTUAL_WIDTH2 * P_ACTUAL_HEIGHT2) << (((get_imageParamsR(P_BITS) == 8) && !get_imageParamsR(P_BGFRAME)) ? 0 : 1);
00497
00498 if((p + count) > fsz) {
00499 count = fsz - p;
00500 }
00501 left = count;
00502 while(left > 0) {
00503
00504 if((get_imageParamsR(P_BITS) == 8) && !get_imageParamsR(P_BGFRAME)) {
00505 y = p / P_ACTUAL_WIDTH2;
00506 xb = p - y * P_ACTUAL_WIDTH2;
00507 xbl = P_ACTUAL_WIDTH2 - xb;
00508 } else {
00509 y = (p / P_ACTUAL_WIDTH2) >> 1;
00510 xb = p - y * (P_ACTUAL_WIDTH2 << 1);
00511 xbl = (P_ACTUAL_WIDTH2 << 1) - xb;
00512 }
00513 if(xbl > left)
00514 xbl = left;
00515
00516 if(!(mp = (char *)x313_frame_readline(y + P_ACTUAL_HEIGHT2 * get_imageParamsR(P_PAGE_READ)))) {
00517 printk("read SDRAM error!\r\n");
00518 return -EFAULT;
00519 }
00520
00521 mp += xb;
00522
00523 if(copy_to_user(bp, mp, xbl)) {
00524 printk("copy_to_user error!\r\n");
00525 return -EFAULT;
00526 }
00527 left -= xbl;
00528 p += xbl;
00529 bp += xbl;
00530 }
00531
00532 *off+=count;
00533
00534 return count;
00535 }
00536
00537
00538 loff_t x313_frame_lseek(struct file * file, loff_t offset, int orig) {
00539
00540
00541
00542
00543
00544
00545 unsigned long fsz;
00546 fsz = (P_ACTUAL_WIDTH2 * P_ACTUAL_HEIGHT2) << (((get_imageParamsR(P_BITS) == 8) && !get_imageParamsR(P_BGFRAME)) ? 0 : 1);
00547
00548
00549
00550 switch (orig) {
00551 case 0:
00552 file->f_pos = offset;
00553 break;
00554 case 1:
00555 file->f_pos += offset;
00556 break;
00557 case 2:
00558 file->f_pos = fsz + offset;
00559 break;
00560 default:
00561 return -EINVAL;
00562 }
00563
00564
00565 if (file->f_pos < 0) {
00566 file->f_pos = 0;
00567 return (-EOVERFLOW);
00568 }
00569
00570 if (file->f_pos > fsz) {
00571 file->f_pos = fsz;
00572 return (-EOVERFLOW);
00573 }
00574 return (file->f_pos);
00575 }
00576
00577 int x313_frame_open(struct inode *inode, struct file *filp) {
00578 inode->i_size = (P_ACTUAL_WIDTH2 * P_ACTUAL_HEIGHT2) << (((get_imageParamsR(P_BITS) == 8) && !get_imageParamsR(P_BGFRAME)) ? 0 : 1);
00579 linebufdirty_fpn = 0;
00580 lineinbuf_img = -1;
00581
00582
00583 return 0;
00584 }
00585
00586 void x313_frame_release(void) {
00587
00588 if(lock_flag == 1) {
00589 printk("frame release - release sensor\r\n");
00590
00591 ch0_en();
00592 lock_flag = 0;
00593 }
00594 }
00595
00596 int x313_fpn_open(struct inode *inode, struct file *filp) {
00597 inode->i_size = (P_ACTUAL_WIDTH2 * P_ACTUAL_HEIGHT2) << 1;
00598 linebufdirty_fpn = 0;
00599 lineinbuf_fpn = -1;
00600 MD3(printk("fpn_open, size = %x\n", (int) inode->i_size));
00601 return 0;
00602 }
00603
00604 void x313_fpn_release(void) {
00605 if(linebufdirty_fpn)
00606 x313_fpn_writeline();
00607 MD3(printk("fpn_release\n"));
00608
00609 }
00610
00611 void x313_f_invalidate(void) {
00612 linebufdirty_fpn = 0;
00613 lineinbuf_fpn = -1;
00614 lineinbuf_img = -1;
00615 }