📄 cx88-blackbird.c
字号:
retval = wait_ready_gpio0_bit1(core,1); cx_writeb(P1_MDATA3, 0); val = (unsigned char)cx_read(P1_MDATA3) << 24; cx_writeb(P1_MDATA2, 0); val |= (unsigned char)cx_read(P1_MDATA2) << 16; cx_writeb(P1_MDATA1, 0); val |= (unsigned char)cx_read(P1_MDATA1) << 8; cx_writeb(P1_MDATA0, 0); val |= (unsigned char)cx_read(P1_MDATA0); *value = val; return retval;}static int register_write(struct cx88_core *core, u32 address, u32 value){ cx_writeb(P1_RDATA0, (unsigned int)value); cx_writeb(P1_RDATA1, (unsigned int)(value >> 8)); cx_writeb(P1_RDATA2, (unsigned int)(value >> 16)); cx_writeb(P1_RDATA3, (unsigned int)(value >> 24)); cx_writeb(P1_RADDR0, (unsigned int)address); cx_writeb(P1_RADDR1, (unsigned int)(address >> 8)); cx_writeb(P1_RRDWR, 1); cx_read(P1_RDATA0); cx_read(P1_RADDR0); return wait_ready_gpio0_bit1(core,1);}static int register_read(struct cx88_core *core, u32 address, u32 *value){ int retval; u32 val; cx_writeb(P1_RADDR0, (unsigned int)address); cx_writeb(P1_RADDR1, (unsigned int)(address >> 8)); cx_writeb(P1_RRDWR, 0); cx_read(P1_RADDR0); retval = wait_ready_gpio0_bit1(core,1); val = (unsigned char)cx_read(P1_RDATA0); val |= (unsigned char)cx_read(P1_RDATA1) << 8; val |= (unsigned char)cx_read(P1_RDATA2) << 16; val |= (unsigned char)cx_read(P1_RDATA3) << 24; *value = val; return retval;}/* ------------------------------------------------------------------ *//* We don't need to call the API often, so using just one mailbox will probably suffice */static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, u32 inputcnt, u32 outputcnt, ...){ unsigned long timeout; u32 value, flag, retval; int i; va_list args; va_start(args, outputcnt); dprintk(1,"%s: 0x%X\n", __FUNCTION__, command); /* this may not be 100% safe if we can't read any memory location without side effects */ memory_read(dev->core, dev->mailbox - 4, &value); if (value != 0x12345678) { dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n"); return -1; } memory_read(dev->core, dev->mailbox, &flag); if (flag) { dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag); return -1; } flag |= 1; /* tell 'em we're working on it */ memory_write(dev->core, dev->mailbox, flag); /* write command + args + fill remaining with zeros */ memory_write(dev->core, dev->mailbox + 1, command); /* command code */ memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ for (i = 0; i < inputcnt ; i++) { value = va_arg(args, int); memory_write(dev->core, dev->mailbox + 4 + i, value); dprintk(1, "API Input %d = %d\n", i, value); } for (; i < 16 ; i++) memory_write(dev->core, dev->mailbox + 4 + i, 0); flag |= 3; /* tell 'em we're done writing */ memory_write(dev->core, dev->mailbox, flag); /* wait for firmware to handle the API command */ timeout = jiffies + msecs_to_jiffies(10); for (;;) { memory_read(dev->core, dev->mailbox, &flag); if (0 != (flag & 4)) break; if (time_after(jiffies,timeout)) { dprintk(0, "ERROR: API Mailbox timeout\n"); return -1; } udelay(10); } /* read output values */ for (i = 0; i < outputcnt ; i++) { int *vptr = va_arg(args, int *); memory_read(dev->core, dev->mailbox + 4 + i, vptr); dprintk(1, "API Output %d = %d\n", i, *vptr); } va_end(args); memory_read(dev->core, dev->mailbox + 2, &retval); dprintk(1, "API result = %d\n",retval); flag = 0; memory_write(dev->core, dev->mailbox, flag); return retval;}static int blackbird_find_mailbox(struct cx8802_dev *dev){ u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456}; int signaturecnt=0; u32 value; int i; for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) { memory_read(dev->core, i, &value); if (value == signature[signaturecnt]) signaturecnt++; else signaturecnt = 0; if (4 == signaturecnt) { dprintk(1, "Mailbox signature found\n"); return i+1; } } dprintk(0, "Mailbox signature values not found!\n"); return -1;}static int blackbird_load_firmware(struct cx8802_dev *dev){ static const unsigned char magic[8] = { 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa }; const struct firmware *firmware; int i, retval = 0; u32 value = 0; u32 checksum = 0; u32 *dataptr; retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); msleep(1); retval |= register_write(dev->core, IVTV_REG_APU, 0); if (retval < 0) dprintk(0, "Error with register_write\n"); retval = request_firmware(&firmware, BLACKBIRD_FIRM_ENC_FILENAME, &dev->pci->dev); if (retval != 0) { dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", BLACKBIRD_FIRM_ENC_FILENAME); dprintk(0, "Please fix your hotplug setup, the board will " "not work without firmware loaded!\n"); return -1; } if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n", firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); return -1; } if (0 != memcmp(firmware->data, magic, 8)) { dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n"); return -1; } /* transfer to the chip */ dprintk(1,"Loading firmware ...\n"); dataptr = (u32*)firmware->data; for (i = 0; i < (firmware->size >> 2); i++) { value = *dataptr; checksum += ~value; memory_write(dev->core, i, value); dataptr++; } /* read back to verify with the checksum */ for (i--; i >= 0; i--) { memory_read(dev->core, i, &value); checksum -= ~value; } if (checksum) { dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n"); return -1; } release_firmware(firmware); dprintk(0, "Firmware upload successful.\n"); retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); retval |= register_read(dev->core, IVTV_REG_SPU, &value); retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); msleep(1); retval |= register_read(dev->core, IVTV_REG_VPU, &value); retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); if (retval < 0) dprintk(0, "Error with register_write\n"); return 0;}/** Settings used by the windows tv app for PVR2000:=================================================================================================================Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode-----------------------------------------------------------------------------------------------------------------MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoMPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoVCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoDVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoDB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo=================================================================================================================*DB: "DirectBurn"*/static struct blackbird_dnr default_dnr_params = { .mode = BLACKBIRD_DNR_BITS_MANUAL, .type = BLACKBIRD_MEDIAN_FILTER_DISABLED, .spatial = 0, .temporal = 0};static struct v4l2_mpeg_compression default_mpeg_params = { .st_type = V4L2_MPEG_PS_2, .st_bitrate = { .mode = V4L2_BITRATE_CBR, .min = 0, .target = 0, .max = 0 }, .ts_pid_pmt = 16, .ts_pid_audio = 260, .ts_pid_video = 256, .ts_pid_pcr = 259, .ps_size = 0, .au_type = V4L2_MPEG_AU_2_II, .au_bitrate = { .mode = V4L2_BITRATE_CBR, .min = 224, .target = 224, .max = 224 }, .au_sample_rate = 44100, .au_pesid = 0, .vi_type = V4L2_MPEG_VI_2, .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3, .vi_bitrate = { .mode = V4L2_BITRATE_CBR, .min = 4000, .target = 4500, .max = 6000 }, .vi_frame_rate = 25, .vi_frames_per_gop = 15, .vi_bframes_count = 2, .vi_pesid = 0, .closed_gops = 0, .pulldown = 0};static enum blackbird_stream_type mpeg_stream_types[] = { [V4L2_MPEG_SS_1] = BLACKBIRD_STREAM_MPEG1, [V4L2_MPEG_PS_2] = BLACKBIRD_STREAM_PROGRAM, [V4L2_MPEG_TS_2] = BLACKBIRD_STREAM_TRANSPORT, [V4L2_MPEG_PS_DVD] = BLACKBIRD_STREAM_DVD,};static enum blackbird_aspect_ratio mpeg_stream_ratios[] = { [V4L2_MPEG_ASPECT_SQUARE] = BLACKBIRD_ASPECT_RATIO_1_1_SQUARE, [V4L2_MPEG_ASPECT_4_3] = BLACKBIRD_ASPECT_RATIO_4_3, [V4L2_MPEG_ASPECT_16_9] = BLACKBIRD_ASPECT_RATIO_16_9, [V4L2_MPEG_ASPECT_1_221] = BLACKBIRD_ASPECT_RATIO_221_100,};static enum blackbird_video_bitrate_type mpeg_video_bitrates[] = { [V4L2_BITRATE_NONE] = BLACKBIRD_VIDEO_CBR, [V4L2_BITRATE_CBR] = BLACKBIRD_VIDEO_CBR, [V4L2_BITRATE_VBR] = BLACKBIRD_VIDEO_VBR,};/* find the best layer I/II bitrate to fit a given numeric value */struct bitrate_bits { u32 bits; /* layer bits for the best fit */ u32 rate; /* actual numeric value for the layer best fit */};struct bitrate_approximation { u32 target; /* numeric value of the rate we want */ struct bitrate_bits layer[2];};static struct bitrate_approximation mpeg_audio_bitrates[] = { /* target layer[0].bits layer[0].rate layer[1].bits layer[1].rate */ { 0, { { 0, 0, }, { 0, 0, }, }, }, { 32, { { BLACKBIRD_AUDIO_BITS_LAYER_1_32 , 32, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_32 , 32, }, }, }, { 48, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_48 , 48, }, }, }, { 56, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_56 , 56, }, }, }, { 64, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_64 , 64, }, }, }, { 80, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_80 , 80, }, }, }, { 96, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_96 , 96, }, }, }, { 112, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_112, 112, }, }, }, { 128, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_128, 128, }, }, }, { 160, { { BLACKBIRD_AUDIO_BITS_LAYER_1_160, 160, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_160, 160, }, }, }, { 192, { { BLACKBIRD_AUDIO_BITS_LAYER_1_192, 192, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_192, 192, }, }, }, { 224, { { BLACKBIRD_AUDIO_BITS_LAYER_1_224, 224, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_224, 224, }, }, }, { 256, { { BLACKBIRD_AUDIO_BITS_LAYER_1_256, 256, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_256, 256, }, }, }, { 288, { { BLACKBIRD_AUDIO_BITS_LAYER_1_288, 288, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, { 320, { { BLACKBIRD_AUDIO_BITS_LAYER_1_320, 320, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, { 352, { { BLACKBIRD_AUDIO_BITS_LAYER_1_352, 352, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, { 384, { { BLACKBIRD_AUDIO_BITS_LAYER_1_384, 384, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, { 416, { { BLACKBIRD_AUDIO_BITS_LAYER_1_416, 416, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, { 448, { { BLACKBIRD_AUDIO_BITS_LAYER_1_448, 448, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },};static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates);static void blackbird_set_default_params(struct cx8802_dev *dev){ struct v4l2_mpeg_compression *params = &dev->params; u32 au_params; /* assign stream type */ if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) params->st_type = V4L2_MPEG_PS_2; if( params->st_type == V4L2_MPEG_SS_1 ) params->vi_type = V4L2_MPEG_VI_1; else params->vi_type = V4L2_MPEG_VI_2; blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); /* assign framerate */ if( params->vi_frame_rate <= 25 ) { params->vi_frame_rate = 25; blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); } else { params->vi_frame_rate = 30; blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); } /* assign aspect ratio */ if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); /* assign gop properties */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); /* assign gop closure */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); /* assign 3 2 pulldown */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); /* make sure the params are within bounds */ if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) params->vi_bitrate.mode = V4L2_BITRATE_NONE; if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) params->vi_bitrate.mode = V4L2_BITRATE_NONE; if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) params->au_bitrate.mode = V4L2_BITRATE_NONE; /* assign audio properties */ /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ au_params = BLACKBIRD_AUDIO_BITS_STEREO | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | BLACKBIRD_AUDIO_BITS_CRC_OFF | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | BLACKBIRD_AUDIO_BITS_COPY | 0; if( params->au_sample_rate <= 32000 ) { params->au_sample_rate = 32000; au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; } else if( params->au_sample_rate <= 44100 ) { params->au_sample_rate = 44100; au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; } else { params->au_sample_rate = 48000; au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; } if( params->au_type == V4L2_MPEG_AU_2_I ) { au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; } else { /* TODO: try to handle the other formats more gracefully */ params->au_type = V4L2_MPEG_AU_2_II; au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; } if( params->au_bitrate.mode ) { int layer; if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) params->au_bitrate.max = params->vi_bitrate.target; else params->au_bitrate.target = params->vi_bitrate.max; layer = params->au_type; if( params->au_bitrate.target == 0 ) { /* TODO: use the minimum possible bitrate instead of 0 ? */ au_params |= 0; } else if( params->au_bitrate.target >= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; params->au_bitrate.max = params->au_bitrate.target; au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; } else { /* round up to the nearest supported bitrate */ int i; for(i = 1; i < BITRATES_SIZE; i++) { if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -