zr36060.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 989 行 · 第 1/2 页
C
989 行
zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt), zr36060_dqt); sum += zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht); sum += zr36060_pushit(ptr, ZR060_APP_IDX, sizeof(zr36060_app), zr36060_app); sum += zr36060_pushit(ptr, ZR060_COM_IDX, sizeof(zr36060_com), zr36060_com); /* setup misc. data for compression (target code sizes) */ /* size of compressed code to reach without header data */ sum = ptr->real_code_vol - sum; bitcnt = sum << 3; /* need the size in bits */ tmp = bitcnt >> 16; dprintk(3, "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n", ptr->name, sum, ptr->real_code_vol, bitcnt, tmp); zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8); zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff); tmp = bitcnt & 0xffff; zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8); zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff); bitcnt -= bitcnt >> 7; // bits without stuffing bitcnt -= ((bitcnt * 5) >> 6); // bits without eob tmp = bitcnt >> 16; dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n", ptr->name, bitcnt, tmp); zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8); zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff); tmp = bitcnt & 0xffff; zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8); zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff); /* JPEG markers to be included in the compressed stream */ zr36060_write(ptr, ZR060_MER, ZR060_MER_App | ZR060_MER_Com | ZR060_MER_DQT | ZR060_MER_DHT); /* Setup the Video Frontend */ /* Limit pixel range to 16..235 as per CCIR-601 */ zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range); } else { dprintk(2, "%s: EXPANSION SETUP\n", ptr->name); zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst); /* 060 communicates with 067 in master mode */ zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr); /* Decompression */ zr36060_write(ptr, ZR060_CMR, 0); /* Must be zero */ zr36060_write(ptr, ZR060_MBZ, 0x00); zr36060_write(ptr, ZR060_TCR_HI, 0x00); zr36060_write(ptr, ZR060_TCR_LO, 0x00); /* Disable all IRQs - no DataErr means autoreset */ zr36060_write(ptr, ZR060_IMR, 0); /* setup misc. data for expansion */ zr36060_write(ptr, ZR060_MER, 0); /* setup the fixed jpeg tables - maybe variable, though - * (see table init section above) */ zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht); /* Setup the Video Frontend */ //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FIExt); //this doesn't seem right and doesn't work... zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range); } /* Load the tables */ zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst | ZR060_LOAD_Load); zr36060_wait_end(ptr); dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name, ptr->status); if (ptr->status & ZR060_CFSR_Busy) { dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name); return; // something is wrong, its timed out!!!! }}/* ========================================================================= CODEC API FUNCTIONS this functions are accessed by the master via the API structure ========================================================================= *//* set compression/expansion mode and launches codec - this should be the last call from the master before starting processing */static intzr36060_set_mode (struct videocodec *codec, int mode){ struct zr36060 *ptr = (struct zr36060 *) codec->data; dprintk(2, "%s: set_mode %d call\n", ptr->name, mode); if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION)) return -EINVAL; ptr->mode = mode; zr36060_init(ptr); return 0;}/* set picture size (norm is ignored as the codec doesn't know about it) */static intzr36060_set_video (struct videocodec *codec, struct tvnorm *norm, struct vfe_settings *cap, struct vfe_polarity *pol){ struct zr36060 *ptr = (struct zr36060 *) codec->data; u32 reg; int size; dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name, cap->x, cap->y, cap->width, cap->height, cap->decimation); /* if () return -EINVAL; * trust the master driver that it knows what it does - so * we allow invalid startx/y and norm for now ... */ ptr->width = cap->width / (cap->decimation & 0xff); ptr->height = cap->height / (cap->decimation >> 8); zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst); /* Note that VSPol/HSPol bits in zr36060 have the opposite * meaning of their zr360x7 counterparts with the same names * N.b. for VSPol this is only true if FIVEdge = 0 (default, * left unchanged here - in accordance with datasheet). */ reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0) | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0) | (pol->field_pol ? ZR060_VPR_FIPol : 0) | (pol->blank_pol ? ZR060_VPR_BLPol : 0) | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0) | (pol->poe_pol ? ZR060_VPR_PoePol : 0) | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0) | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0); zr36060_write(ptr, ZR060_VPR, reg); reg = 0; switch (cap->decimation & 0xff) { default: case 1: break; case 2: reg |= ZR060_SR_HScale2; break; case 4: reg |= ZR060_SR_HScale4; break; } switch (cap->decimation >> 8) { default: case 1: break; case 2: reg |= ZR060_SR_VScale; break; } zr36060_write(ptr, ZR060_SR, reg); zr36060_write(ptr, ZR060_BCR_Y, 0x00); zr36060_write(ptr, ZR060_BCR_U, 0x80); zr36060_write(ptr, ZR060_BCR_V, 0x80); /* sync generator */ reg = norm->Ht - 1; /* Vtotal */ zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff); reg = norm->Wt - 1; /* Htotal */ zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff); reg = 6 - 1; /* VsyncSize */ zr36060_write(ptr, ZR060_SGR_VSYNC, reg); //reg = 30 - 1; /* HsyncSize *////*CP*/ reg = (zr->params.norm == 1 ? 57 : 68); reg = 68; zr36060_write(ptr, ZR060_SGR_HSYNC, reg); reg = norm->VStart - 1; /* BVstart */ zr36060_write(ptr, ZR060_SGR_BVSTART, reg); reg += norm->Ha / 2; /* BVend */ zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff); reg = norm->HStart - 1; /* BHstart */ zr36060_write(ptr, ZR060_SGR_BHSTART, reg); reg += norm->Wa; /* BHend */ zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff); /* active area */ reg = cap->y + norm->VStart; /* Vstart */ zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff); reg += cap->height; /* Vend */ zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff); reg = cap->x + norm->HStart; /* Hstart */ zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff); reg += cap->width; /* Hend */ zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff); /* subimage area */ reg = norm->VStart - 4; /* SVstart */ zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff); reg += norm->Ha / 2 + 8; /* SVend */ zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff); reg = norm->HStart /*+ 64 */ - 4; /* SHstart */ zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff); reg += norm->Wa + 8; /* SHend */ zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff); zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff); size = ptr->width * ptr->height; /* Target compressed field size in bits: */ size = size * 16; /* uncompressed size in bits */ /* (Ronald) by default, quality = 100 is a compression * ratio 1:2. Setting low_bitrate (insmod option) sets * it to 1:4 (instead of 1:2, zr36060 max) as limit because the * buz can't handle more at decimation=1... Use low_bitrate if * you have a Buz, unless you know what you're doing */ size = size * cap->quality / (low_bitrate ? 400 : 200); /* Lower limit (arbitrary, 1 KB) */ if (size < 8192) size = 8192; /* Upper limit: 7/8 of the code buffers */ if (size > ptr->total_code_vol * 7) size = ptr->total_code_vol * 7; ptr->real_code_vol = size >> 3; /* in bytes */ /* the MBCVR is the *maximum* block volume, according to the * JPEG ISO specs, this shouldn't be used, since that allows * for the best encoding quality. So set it to it's max value */ reg = ptr->max_block_vol; zr36060_write(ptr, ZR060_MBCVR, reg); return 0;}/* additional control functions */static intzr36060_control (struct videocodec *codec, int type, int size, void *data){ struct zr36060 *ptr = (struct zr36060 *) codec->data; int *ival = (int *) data; dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type, size); switch (type) { case CODEC_G_STATUS: /* get last status */ if (size != sizeof(int)) return -EFAULT; zr36060_read_status(ptr); *ival = ptr->status; break; case CODEC_G_CODEC_MODE: if (size != sizeof(int)) return -EFAULT; *ival = CODEC_MODE_BJPG; break; case CODEC_S_CODEC_MODE: if (size != sizeof(int)) return -EFAULT; if (*ival != CODEC_MODE_BJPG) return -EINVAL; /* not needed, do nothing */ return 0; case CODEC_G_VFE: case CODEC_S_VFE: /* not needed, do nothing */ return 0; case CODEC_S_MMAP: /* not available, give an error */ return -ENXIO; case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */ if (size != sizeof(int)) return -EFAULT; *ival = ptr->total_code_vol; break; case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */ if (size != sizeof(int)) return -EFAULT; ptr->total_code_vol = *ival; ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3; break; case CODEC_G_JPEG_SCALE: /* get scaling factor */ if (size != sizeof(int)) return -EFAULT; *ival = zr36060_read_scalefactor(ptr); break; case CODEC_S_JPEG_SCALE: /* set scaling factor */ if (size != sizeof(int)) return -EFAULT; ptr->scalefact = *ival; break; default: return -EINVAL; } return size;}/* ========================================================================= Exit and unregister function: Deinitializes Zoran's JPEG processor ========================================================================= */static intzr36060_unset (struct videocodec *codec){ struct zr36060 *ptr = codec->data; if (ptr) { /* do wee need some codec deinit here, too ???? */ dprintk(1, "%s: finished codec #%d\n", ptr->name, ptr->num); kfree(ptr); codec->data = NULL; zr36060_codecs--; return 0; } return -EFAULT;}/* ========================================================================= Setup and registry function: Initializes Zoran's JPEG processor Also sets pixel size, average code size, mode (compr./decompr.) (the given size is determined by the processor with the video interface) ========================================================================= */static intzr36060_setup (struct videocodec *codec){ struct zr36060 *ptr; int res; dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n", zr36060_codecs); if (zr36060_codecs == MAX_CODECS) { dprintk(1, KERN_ERR "zr36060: Can't attach more codecs!\n"); return -ENOSPC; } //mem structure init codec->data = ptr = kmalloc(sizeof(struct zr36060), GFP_KERNEL); if (NULL == ptr) { dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n"); return -ENOMEM; } memset(ptr, 0, sizeof(struct zr36060)); snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", zr36060_codecs); ptr->num = zr36060_codecs++; ptr->codec = codec; //testing res = zr36060_basic_test(ptr); if (res < 0) { zr36060_unset(codec); return res; } //final setup memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8); memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8); ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag * (what is the difference?) */ ptr->mode = CODEC_DO_COMPRESSION; ptr->width = 384; ptr->height = 288; ptr->total_code_vol = 16000; /* CHECKME */ ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3; ptr->max_block_vol = 240; /* CHECKME, was 120 is 240 */ ptr->scalefact = 0x100; ptr->dri = 1; /* CHECKME, was 8 is 1 */ zr36060_init(ptr); dprintk(1, KERN_INFO "%s: codec attached and running\n", ptr->name); return 0;}static const struct videocodec zr36060_codec = { .owner = THIS_MODULE, .name = "zr36060", .magic = 0L, // magic not used .flags = CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER | CODEC_FLAG_VFE, .type = CODEC_TYPE_ZR36060, .setup = zr36060_setup, // functionality .unset = zr36060_unset, .set_mode = zr36060_set_mode, .set_video = zr36060_set_video, .control = zr36060_control, // others are not used};/* ========================================================================= HOOK IN DRIVER AS KERNEL MODULE ========================================================================= */static int __initzr36060_init_module (void){ //dprintk(1, "zr36060 driver %s\n",ZR060_VERSION); zr36060_codecs = 0; return videocodec_register(&zr36060_codec);}static void __exitzr36060_cleanup_module (void){ if (zr36060_codecs) { dprintk(1, "zr36060: something's wrong - %d codecs left somehow.\n", zr36060_codecs); } /* however, we can't just stay alive */ videocodec_unregister(&zr36060_codec);}module_init(zr36060_init_module);module_exit(zr36060_cleanup_module);MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors " ZR060_VERSION);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?