📄 vdc.c
字号:
/* * Sample program for FR400 Companion Chip VDC axLinux driver. * * Copyright (C) 2002 AXE,Inc. * */#include <stdio.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include <sys/stat.h>#include <linux/fr400cc_vdc.h>/* * [memory map] * 0x00000000 - 0x01000000 kernel * 0x01000000 - 0x01c00000 vdc.c * 0x01c00000 - 0x03c00000 (don't use, broken??) * 0x03c00000 - 0x04000000 romdisk */#define TMPBUF_BASE 0x01000000#define TMPBUF_SIZE 0x02c00000static unsigned char *local_area = (unsigned char *)TMPBUF_BASE;static unsigned char *mmap_area = NULL;static struct fr400vdc_config cfg;static int fd = -1;#define REGIO_TEST 1 /* 2003/Jan/27 */#define CSRON_OPT 1 /* 2003/Jan/21 */#define PIXUT 1 /* 2003/Jan/21 */#define CFGCHK 1 /* 2002/Dec/20 */#define OPTCHK 1 /* 2002/Dec/19 */#define YUV_TEST_DATA 1 /* 2202/Dec/17 */#define RGB_DBL 1 /* 2002/Dec/17 */#define VDC_CFG_MOD 1 /* 2002/Nov/11 */#define RGB 1 /* 2002/Nov/01 */#define TXT_DEBUG 0#define DBG_MSG 0#if REGIO_TEST#include <linux/fr400cc_io.h>#endif#if TXT_DEBUGstatic char txtbufline[1024]; /* 1 line */static char txtbuf[100*1024];static const int txtbufsz = sizeof(txtbuf);static int txtbufcnt = 0;static int txtbufidx = 0;static char *txtbuf_get(){ return txtbufline; }static void txtbuf_add_sub(char *src, int sz){ char *dst; dst = txtbuf + txtbufidx; bcopy(src, dst, sz); txtbufidx = (txtbufidx + sz) % txtbufsz; if(txtbufcnt < txtbufsz){ txtbufcnt += sz; if(txtbufcnt >= txtbufsz) txtbufcnt = txtbufsz; }}static void txtbuf_add(){ char *src; int sz, rest, cpsz; sz = strlen(txtbufline); if(sz > sizeof(txtbufline)-1) sz = sizeof(txtbufline)-1; src = txtbufline; cpsz = sz; rest = txtbufsz - txtbufidx; if(cpsz > rest) cpsz = rest; txtbuf_add_sub(src, cpsz); src += cpsz; sz -= cpsz; if(sz <= 0) return; txtbuf_add_sub(src, sz);}static void txtbuf_dump(){ int i, j, st; fprintf(stderr, "--> txtbuf dump\n"); st = 0; if(txtbufcnt >= txtbufsz) st = txtbufidx; for(i=0; i<txtbufcnt; i++){ j = (st + i) % txtbufsz; fputc(txtbuf[j], stderr); } fprintf(stderr, "<-- txtbuf dump\n");}#endif /* TXT_DEBUG */static voidtm_dif( struct timeval *a, struct timeval *b, struct timeval *re){ re->tv_sec = a->tv_sec - b->tv_sec; re->tv_usec = a->tv_usec - b->tv_usec; while(re->tv_usec < 0){ re->tv_sec--; re->tv_usec += 1000000; }}static void *mmap_fd(int fd){ void *start; int length, prot, flags, offset; start = NULL; length = cfg.buf_unit_sz * cfg.buf_num; prot = PROT_READ | PROT_WRITE; flags = MAP_SHARED; offset = 0; return mmap(start, length, prot, flags, fd, offset);}static intfile_sz(char *fn){ struct stat st; if(stat(fn, &st) == -1) return -1; return st.st_size;}static intload_area(char *fn, unsigned char *buf){ FILE *fp; int fsz, sz, x; unsigned char *p; fprintf(stderr, "load %s ... ", fn); fflush(stderr); if((fsz = file_sz(fn)) < 0){ fprintf(stderr, "%s ???\n", fn); return -1; } if((fp = fopen(fn, "r")) == NULL) return -1; sz = fsz; p = buf; while(sz > 0){ if((x = fread(p, 1, sz, fp)) < 0){ fclose(fp); return -1; } p += x; sz -= x; } fclose(fp); if(cfg.pix_x == 640){ /* !!! */ int i, j, n; p = buf; n = fsz / 4; for(i=0; i<n; i++){ j = n - i - 1; bcopy(p+j*4, p+j*2*4, 4); bcopy(p+j*4, p+(j*2+1)*4, 4); } if(!cfg.skipbf){ sz = fsz * 2; bcopy(p, p+sz, sz); } } fprintf(stderr, "ok.\n"); return 0;}static voidhelp(){ printf("--help , -help , -?\n"); printf("-dma-mode <0|1|3> : DA,SCA,2D\n"); printf("-hdc n\n"); printf("-hfp n\n"); printf("-hsc n\n"); printf("-hbp n\n"); printf("-hsop n\n"); printf("-vdc n\n"); printf("-vfp n\n"); printf("-vsc n\n"); printf("-vbp n\n"); printf("-vsop n\n"); printf("-hip n\n"); printf("-vip n\n"); printf("-rck n\n"); printf("-rddl n\n"); printf("-cscv n\n"); printf("-ats n\n"); printf("-dsm n\n"); printf("-interlace n\n"); printf("-csron n\n"); printf("-bit <8|16>\n"); printf("-qvga\n"); printf("-rgb\n"); printf("-y2rgb\n"); printf("-yuv\n"); printf("-xga\n"); printf("-h320\n"); printf("-lcd\n"); printf("-skipbf N (N=0|1|2 , default:0\n" " 0 top bottom same dma (once)\n" " 1 top bottom another dma , same data\n" " 2 top bottom another dma , anoter data)\n"); printf("-rd_count_buf_idx\n"); printf("-f <yuv filepath>\n"); printf("-load N N (start .. cnt)\n"); printf("-fmt <load format string> (defalut: cap%%03d.yuv)\n"); printf("-nonblock N (N=0|1 , default:1\n"); printf("-block ( == -nonblock 0)\n"); printf("-vsync (vsync test)\n"); printf("-vsync-auto (vsync test 2)\n"); printf("-cnt N\n"); printf("-sec N\n"); printf("-showall-stop\n"); printf("-pack\n"); printf("-grad\n"); printf("-cbar\n"); printf("-bw\n"); printf("-mix\n"); printf("-dbl\n"); printf("-v\n"); printf("-dma-mode\n");#if REGIO_TEST printf("-rct1 0xHHHHHHHH\n"); printf("-rct2 0xHHHHHHHH\n"); printf("-csr-x N\n"); printf("-csr-y N\n"); printf("-bci\n"); printf("-show-rs\n"); printf("-regio-w 0xHHHHHHHH 0xHHHHHHHH\n"); printf("-regio-r 0xHHHHHHHH\n");#endif}static intopt_chk(int ac, char **av, char *key){ int i; for(i=1; i<ac; i++){ if(strcmp(av[i], key) == 0) return i; } return 0;}static intopt_chk_str(int ac, char **av, char *key, char **re){ int i; i = opt_chk(ac, av, key); if(i!=0 && i+1<ac){ *re = av[i+1]; return 0; } return -1;}static voidopt_chk_int(int ac, char **av, char *key, int *re){ int i; i = opt_chk(ac, av, key); if(i!=0 && i+1<ac){ sscanf(av[i+1], "%d", re); }}static voidopt_chk_int2(int ac, char **av, char *key, int *re1, int *re2){ int i; i = opt_chk(ac, av, key); if(i!=0 && i+2<ac){ sscanf(av[i+1], "%d", re1); sscanf(av[i+2], "%d", re2); }}#if REGIO_TESTstatic ints2val(char *s, unsigned *re){ unsigned v; int cnt, neg, d; if(s == NULL) return -2; if(strncmp(s, "0x", 2) == 0){ if((cnt = sscanf(s, "0x%x", &v)) != 1) return -1; *re = v; return 0; } neg = 0; if(s[0] == '-'){ neg = 1; s++; } if((cnt = sscanf(s, "%d", &d)) != 1) return -1; if(neg) d = -d; *re = (unsigned)d; return 0;}static intopt_chk_val(int ac, char **av, char *key, unsigned *re){ char *str; if(opt_chk_str(ac, av, key, &str) != 0) return -1; if(s2val(str, re) != 0) return -2; return 0;}#endif#if CFGCHKstatic int verbose = 0;static voidconfig_show(struct fr400vdc_config *cfg){ int *prm; prm = cfg->prm; printf("pix_x:%d , pix_y:%d , pix_sz:%d\n", cfg->pix_x, cfg->pix_y, cfg->pix_sz); printf("skipbf:%d , buf_unit_sz:%d , buf_num:%d\n", cfg->skipbf, cfg->buf_unit_sz, cfg->buf_num); printf("stop_immidiate:%d , rd_count_buf_idx:%d\n", cfg->stop_immidiate, cfg->rd_count_buf_idx); printf("H: %d + %d + %d + %d + %d*2 = %d\n", prm[1], prm[2], prm[3], prm[4], prm[10], prm[1]+prm[2]+prm[3]+prm[4]+prm[10]*2); printf("V: %d + %d + %d + %d + %d*2 = %d\n", prm[6], prm[7], prm[8], prm[9], prm[11], prm[6]+prm[7]+prm[8]+prm[9]+prm[11]*2); printf("RCK: %d RDDL: %d\n", prm[12], cfg->rddl); printf("HLS:%d , PAL:%d , CSCV:%d , DBLS:%d\n", cfg->hls, cfg->pal, cfg->cscv, cfg->dbls); printf("R601:%d , TFOP:%d , DSM:%d , DFP:%d\n", cfg->r601, cfg->tfop, cfg->dsm, cfg->dfp); printf("DIE:%d , ENOP:%d , VSOP:%d , HSOP:%d\n", cfg->die, cfg->enop, cfg->vsop, cfg->hsop); printf("DSR:%d , CSRON:%d , DPF:%d , DMS:%d\n", cfg->dsr, cfg->csron, cfg->dpf, cfg->dms); printf("dma_mode:%d , dma_ats:%d , dma_rs:%d\n", cfg->dma_mode, cfg->dma_ats, cfg->dma_rs);}#if REGIO_TESTstatic intbci_set(int fd, char *text, int len){ char ch[3], c; unsigned buf[64]; int x, y, v, pos, div, mod, i; struct fr400cc_vdc_regio regio; int ret; ch[0] = *text++; len--; ch[1] = *text++; len--; ch[2] = *text++; len--; bzero(buf, sizeof(buf)); for(y=0; y<32; y++){ for(x=0; x<32; x++){ if(len <= 0) continue; c = *text++; len--; if(c == ch[0]) continue; v = 0; if(c == ch[1]) v = 1; else if(c == ch[2]) v = 2; pos = y * 32 + x; div = pos / 16; mod = pos % 16; buf[div] |= v << ((15-mod) * 2); } } for(i=0; i<64; i++){ regio.reg_offset = FR400CC_VDC_BCI + i*4; regio.value = buf[i]; if((ret = ioctl(fd, VDCIOCSREGIO, ®io)) != 0){ fprintf(stderr, "ioctl sregio bci err\n"); return ret; } } return 0;}static intregio_test(int ac, char **av, int fd){ int ret, i; unsigned val, mask; int cx, cy; struct fr400cc_vdc_regio regio; static char *bci_def = ".*@" "********************************" "********************************" "**............................**" "**............................**" "**..@@@@@@@@@@@@@@@@@@@@@@@@..**" "**..@@@@@@@@@@@@@@@@@@@@@@@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@....................@@..**" "**..@@@@@@@@@@@@@@@@@@@@@@@@..**" "**..@@@@@@@@@@@@@@@@@@@@@@@@..**" "**............................**" "**............................**" "********************************" "********************************"; ret = 0; if(opt_chk_val(ac, av, "-rct1", &val) == 0){ regio.reg_offset = FR400CC_VDC_RCT1; regio.value = val; if((ret = ioctl(fd, VDCIOCSREGIO, ®io)) != 0){ fprintf(stderr, "ioctl sregio rct1 err\n"); return ret; } } if(opt_chk_val(ac, av, "-rct2", &val) == 0){ regio.reg_offset = FR400CC_VDC_RCT2; regio.value = val; if((ret = ioctl(fd, VDCIOCSREGIO, ®io)) != 0){ fprintf(stderr, "ioctl sregio rct2 err\n"); return ret; } } cx = cy = -1; opt_chk_int(ac, av, "-csr-x", &cx); opt_chk_int(ac, av, "-csr-y", &cy); if(cx != -1 || cy != -1){ regio.reg_offset = FR400CC_VDC_RCH; if((ret = ioctl(fd, VDCIOCGREGIO, ®io)) != 0){ fprintf(stderr, "ioctl gregio rch err\n"); return ret; } if(cx != -1){ mask = ((1 << 11) - 1) << 16; regio.value &= ~mask; cx <<= 16; cx &= mask; regio.value |= cx; } if(cy != -1){ mask = ((1 << 11) - 1) << 0; regio.value &= ~mask; cy <<= 0; cy &= mask; regio.value |= cy; } if((ret = ioctl(fd, VDCIOCSREGIO, ®io)) != 0){ fprintf(stderr, "ioctl sregio rch err\n"); return ret; } } if(opt_chk(ac, av, "-bci")){ if((ret = bci_set(fd, bci_def, strlen(bci_def))) != 0){ return ret; } } if(opt_chk(ac, av, "-show-rs")){ regio.reg_offset = FR400CC_VDC_RS; if((ret = ioctl(fd, VDCIOCGREGIO, ®io)) != 0){ fprintf(stderr, "ioctl gregio rs err\n"); return ret; } printf("-show-rs : %08x\n", regio.value); } if(opt_chk_val(ac, av, "-regio-r", &val) == 0){ regio.reg_offset = val; if((ret = ioctl(fd, VDCIOCGREGIO, ®io)) != 0){ fprintf(stderr, "ioctl gregio regio-r err\n"); return ret; } printf("-regio-r : offset=%08x value=08x\n", regio.reg_offset, regio.value); } if((i = opt_chk(ac, av, "-regio-w")) != 0 && i+2<ac){ if((ret = s2val(av[i+1], ®io.reg_offset)) != 0){ fprintf(stderr, "-regio-w offset ???\n"); return ret; } if((ret = s2val(av[i+2], ®io.value)) != 0){ fprintf(stderr, "-regio-w value ???\n"); return ret; } if((ret = ioctl(fd, VDCIOCSREGIO, ®io)) != 0){ fprintf(stderr, "ioctl sregio regio-w err\n"); return ret; } } return ret;}#endifstatic int#if REGIO_TESTioctl_start(int ac, char **av, int fd, unsigned long prm)#elseioctl_start(int fd, unsigned long prm)#endif{ if(verbose){ struct fr400vdc_config cfg; if(ioctl(fd, VDCIOCGCFG, &cfg) != 0){ fprintf(stderr, "ioctl get cfg err\n"); return -1; } config_show(&cfg); }#if REGIO_TEST { int ret; if((ret = ioctl(fd, VDCIOCSTART, prm)) != 0) return ret; if((ret = regio_test(ac, av, fd)) != 0) return ret; return ret; }#else return ioctl(fd, VDCIOCSTART, prm);#endif}#endif /* CFGCHK */#if PIXUT/* pix_type */#define PIXUT_RGB_NOPACK 2#define PIXUT_RGB_PACK 3#define PIXUT_YUV 4static intpix_sz(int pix_type){ switch(pix_type){ case PIXUT_RGB_NOPACK: return 4; case PIXUT_RGB_PACK: return 3; case PIXUT_YUV: return 2; } return 0;}static intpix_type_rgb(int pack){ return pack ? PIXUT_RGB_PACK : PIXUT_RGB_NOPACK;}static voidpix_rgb2yuv(unsigned char *src, unsigned char *dst){ unsigned int r1, r2, g1, g2, b1, b2; double R, G, B; double Y1, Y2, U, V; unsigned int y1, y2, u, v; r1 = *src++; g1 = *src++; b1 = *src++; r2 = *src++; g2 = *src++; b2 = *src++; Y1 = 0.2989*r1 + 0.5866*g1 + 0.1145*b1; Y2 = 0.2989*r2 + 0.5866*g2 + 0.1145*b2; R = (r1 + r2) / 2.0; G = (g1 + g2) / 2.0; B = (b1 + b2) / 2.0; U = -0.1684*R -0.3311*G + 0.4997*B; V = 0.4998*R - 0.4187*G - 0.0813*B; y1 = Y1; y2 = Y2; u = U + 128; v = V + 128; *dst++ = y1; *dst++ = u; *dst++ = y1; *dst++ = v;}static voidpix_yuv2rgb(unsigned char *src, unsigned char *dst, int pack){ int y1, y2, u, v; unsigned int r1, r2; unsigned int g1, g2; unsigned int b1, b2; double R, G, B; y1 = *src++; u = *src++; y2 = *src++; v = *src++; u -= 128; v -= 128; R = y1 + 1.4022*v; r1 = R; R = y2 + 1.4022*v; r2 = R; G = y1 - 0.3441*u - 0.7139*v; g1 = G; G = y2 - 0.3441*u - 0.7139*v; g2 = G; B = y1 + 1.7718*u - 0.0012*v; b1 = B; B = y2 + 1.7718*u - 0.0012*v; b2 = B; if(!pack) *dst++ = 0; *dst++ = r1; *dst++ = g1; *dst++ = b1; if(!pack) *dst++ = 0; *dst++ = r2; *dst++ = g2; *dst++ = b2;}struct pix_prm{ int x, y, w, h; int r, g, b; char *buf; int pix_type; int interlace;};char *pix_buf_posi(struct pix_prm *p){ int y; y = p->y; if(p->interlace){ y /= 2; if(p->y & 1) y += cfg.pix_y / 2; } return p->buf + (y * cfg.pix_x + p->x) * pix_sz(p->pix_type);}static voidpix_set(struct pix_prm *p){ struct pix_prm p2; unsigned char *ubuf, yuv_buf[10], *up; p2 = *p; if(p2.pix_type == PIXUT_YUV) p2.x &= ~1; ubuf = (unsigned char *)pix_buf_posi(&p2); switch(p2.pix_type){ case PIXUT_YUV: pix_yuv2rgb(ubuf, yuv_buf, 1); up = yuv_buf; if(p->x & 1) up += 3; *up++ = p2.r; *up++ = p2.g; *up++ = p2.b; pix_rgb2yuv(yuv_buf, ubuf); break; case PIXUT_RGB_NOPACK: *ubuf++ = 0; case PIXUT_RGB_PACK: *ubuf++ = p2.r; *ubuf++ = p2.g; *ubuf++ = p2.b; break; }}static voidpix_set2(struct pix_prm *p){ struct pix_prm p2; unsigned char *ubuf, yuv_buf[10], *up; p2 = *p; switch(p2.pix_type){ case PIXUT_YUV: if((p->x & 1) == 0){ ubuf = (unsigned char *)pix_buf_posi(&p2); up = yuv_buf; *up++ = p2.r; *up++ = p2.g; *up++ = p2.b;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -