📄 zr36050.c
字号:
/*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/ zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8); zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff); zr36050_write(ptr, ZR050_AF_HI, 0xff); zr36050_write(ptr, ZR050_AF_M, 0xff); zr36050_write(ptr, ZR050_AF_LO, 0xff); /* setup the variable jpeg tables */ sum += zr36050_set_sof(ptr); sum += zr36050_set_sos(ptr); sum += zr36050_set_dri(ptr); /* setup the fixed jpeg tables - maybe variable, though - * (see table init section above) */ dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name); sum += zr36050_pushit(ptr, ZR050_DQT_IDX, sizeof(zr36050_dqt), zr36050_dqt); sum += zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht), zr36050_dht); zr36050_write(ptr, ZR050_APP_IDX, 0xff); zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn); zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00); zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2); sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60, ptr->app.data) + 4; zr36050_write(ptr, ZR050_COM_IDX, 0xff); zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe); zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00); zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2); sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60, ptr->com.data) + 4; /* do the internal huffman table preload */ zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI); zr36050_write(ptr, ZR050_GO, 1); // launch codec zr36050_wait_end(ptr); dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name, ptr->status1); if ((ptr->status1 & 0x4) == 0) { dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name); return; // something is wrong, its timed out!!!! } /* 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); zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8); zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff); tmp = bitcnt & 0xffff; zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8); zr36050_write(ptr, ZR050_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); zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8); zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff); tmp = bitcnt & 0xffff; zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8); zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff); /* compression setup with or without bitrate control */ zr36050_write(ptr, ZR050_MODE, ZR050_MO_COMP | ZR050_MO_PASS2 | (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0)); /* this headers seem to deliver "valid AVI" jpeg frames */ zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DQT | ZR050_ME_DHT | ((ptr->app.len > 0) ? ZR050_ME_APP : 0) | ((ptr->com.len > 0) ? ZR050_ME_COM : 0)); } else { dprintk(2, "%s: EXPANSION SETUP\n", ptr->name); /* 050 communicates with 055 in master mode */ zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK); /* encoding table preload */ zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM); /* disable all IRQs */ zr36050_write(ptr, ZR050_INT_REQ_0, 0); zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1 dprintk(3, "%s: write DHT\n", ptr->name); zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht), zr36050_dht); /* do the internal huffman table preload */ zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI); zr36050_write(ptr, ZR050_GO, 1); // launch codec zr36050_wait_end(ptr); dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name, ptr->status1); if ((ptr->status1 & 0x4) == 0) { dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name); return; // something is wrong, its timed out!!!! } /* setup misc. data for expansion */ zr36050_write(ptr, ZR050_MODE, 0); zr36050_write(ptr, ZR050_MARKERS_EN, 0); } /* adr on selected, to allow GO from master */ zr36050_read(ptr, 0);}/* ========================================================================= 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 intzr36050_set_mode (struct videocodec *codec, int mode){ struct zr36050 *ptr = (struct zr36050 *) 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; zr36050_init(ptr); return 0;}/* set picture size (norm is ignored as the codec doesn't know about it) */static intzr36050_set_video (struct videocodec *codec, struct tvnorm *norm, struct vfe_settings *cap, struct vfe_polarity *pol){ struct zr36050 *ptr = (struct zr36050 *) codec->data; int size; dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n", ptr->name, norm->HStart, norm->VStart, cap->x, cap->y, cap->width, cap->height, cap->decimation, cap->quality); /* 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) & 0xff); /* (KM) JPEG quality */ size = ptr->width * ptr->height; size *= 16; /* size in bits */ /* apply quality setting */ size = size * cap->quality / 200; /* Minimum: 1kb */ if (size < 8192) size = 8192; /* Maximum: 7/8 of code buffer */ if (size > ptr->total_code_vol * 7) size = ptr->total_code_vol * 7; ptr->real_code_vol = size >> 3; /* in bytes */ /* Set max_block_vol here (previously in zr36050_init, moved * here for consistency with zr36060 code */ zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol); return 0;}/* additional control functions */static intzr36050_control (struct videocodec *codec, int type, int size, void *data){ struct zr36050 *ptr = (struct zr36050 *) 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; zr36050_read_status1(ptr); *ival = ptr->status1; 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; /* (Kieran Morrissey) * code copied from zr36060.c to ensure proper bitrate */ 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 = zr36050_read_scalefactor(ptr); break; case CODEC_S_JPEG_SCALE: /* set scaling factor */ if (size != sizeof(int)) return -EFAULT; ptr->scalefact = *ival; break; case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */ struct jpeg_app_marker *app = data; if (size != sizeof(struct jpeg_app_marker)) return -EFAULT; *app = ptr->app; break; } case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */ struct jpeg_app_marker *app = data; if (size != sizeof(struct jpeg_app_marker)) return -EFAULT; ptr->app = *app; break; } case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */ struct jpeg_com_marker *com = data; if (size != sizeof(struct jpeg_com_marker)) return -EFAULT; *com = ptr->com; break; } case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */ struct jpeg_com_marker *com = data; if (size != sizeof(struct jpeg_com_marker)) return -EFAULT; ptr->com = *com; break; } default: return -EINVAL; } return size;}/* ========================================================================= Exit and unregister function: Deinitializes Zoran's JPEG processor ========================================================================= */static intzr36050_unset (struct videocodec *codec){ struct zr36050 *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; zr36050_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 intzr36050_setup (struct videocodec *codec){ struct zr36050 *ptr; int res; dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n", zr36050_codecs); if (zr36050_codecs == MAX_CODECS) { dprintk(1, KERN_ERR "zr36050: Can't attach more codecs!\n"); return -ENOSPC; } //mem structure init codec->data = ptr = kmalloc(sizeof(struct zr36050), GFP_KERNEL); if (NULL == ptr) { dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n"); return -ENOMEM; } memset(ptr, 0, sizeof(struct zr36050)); snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]", zr36050_codecs); ptr->num = zr36050_codecs++; ptr->codec = codec; //testing res = zr36050_basic_test(ptr); if (res < 0) { zr36050_unset(codec); return res; } //final setup memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8); memcpy(ptr->v_samp_ratio, zr36050_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; ptr->max_block_vol = 240; ptr->scalefact = 0x100; ptr->dri = 1; /* no app/com marker by default */ ptr->app.appn = 0; ptr->app.len = 0; ptr->com.len = 0; zr36050_init(ptr); dprintk(1, KERN_INFO "%s: codec attached and running\n", ptr->name); return 0;}static const struct videocodec zr36050_codec = { .owner = THIS_MODULE, .name = "zr36050", .magic = 0L, // magic not used .flags = CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER, .type = CODEC_TYPE_ZR36050, .setup = zr36050_setup, // functionality .unset = zr36050_unset, .set_mode = zr36050_set_mode, .set_video = zr36050_set_video, .control = zr36050_control, // others are not used};/* ========================================================================= HOOK IN DRIVER AS KERNEL MODULE ========================================================================= */static int __initzr36050_init_module (void){ //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION); zr36050_codecs = 0; return videocodec_register(&zr36050_codec);}static void __exitzr36050_cleanup_module (void){ if (zr36050_codecs) { dprintk(1, "zr36050: something's wrong - %d codecs left somehow.\n", zr36050_codecs); } videocodec_unregister(&zr36050_codec);}module_init(zr36050_init_module);module_exit(zr36050_cleanup_module);MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors " ZR050_VERSION);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -