📄 cvdv.c
字号:
/* cvdv.c Copyright (C) Christian Wolff Marcus Metzler for convergence integrated media. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/ ///////////////////////////////////////////////////////////////////// // // // Driver for the Convergence Digital Video decoder card (pci) // // with L64017, L64021, PCM1723, and Bt864/Bt865 chipset // // (c) Christian Wolff 19990209 for convergence integrated media // // ///////////////////////////////////////////////////////////////////////#define __NO_VERSION__#include <linux/module.h>#include "cvdv.h"#include <linux/dvb/osd.h>#include "i2c.h" ////////////////////// // global variables ////////////////////////// my little random function for memory testuint16_t rnd_seed;uint16_t rnd(uint16_t range){ // returns random 0..(range-1) range<=872 uint32_t b = 75 * (rnd_seed + 1) - 1; rnd_seed = (uint16_t) (b & 0xFFFF); return ((b * range) / 0xFFFF) - ((b / 0xFFFF) * range);}void rnd_omize(void){ rnd_seed = (uint16_t) jiffies;}static char *cimlogo[] = {".............................................",".............................................","......................###....................",".....................#####...................",".....................######..................","..............#......#####...................","...........#####....######...................",".........########...######...................","........########....######...................",".......#########...######....................","......########.....######...####.............",".....#######.......#####...#####.............",".....######.......######...######............","....#######.......######....######...........","....######........######....######...........","....#####........######......#####...........","...######........######......#####...........","...#####.........######......######..........","...#####.........#####.......######..........","...#####........######........#####..........","...#####........######.......######..........","...#####........#####.........#####..........","...#####.......######........######..........","...#####.......######........#####...........","...######.......####.........#####...........","....#####........##.........######...........","....######..................######...........","....######.................######............",".....#######..............######.....#####...",".....########............#######....#######..","......#########........########.....#######..",".......#######################......########.","........#####################.......#######..","..........#################.........#######..","............#############............#####...","...............#.#####.................##....",".............................................","............................................."}; ///////////////////////////////////////////// // // // Controlling the L64021 MPEG-2 Decoder // // ///////////////////////////////////////////////int OSDTest(struct cvdv_cards *card){ int i, j, col, x0, y0, x1, y1,aspx; uint8_t b; if (!card->OSD.open) return -2; OSDQuery(card, &x0, &y0, &x1, &y1, &aspx); OSDShow(card); OSDSetColor(card, 0, 0, 0, 0, 0, 0, 0); OSDSetColor(card, 1, 128, 255, 255, 0, 0, 0); for ( i = 0; i < cimlogo_width; i++){ for ( j = 0; j < cimlogo_height; j++){ b = cimlogo[j][i]; col = (b == '#') ? 1: 0; OSDSetPixel(card, x0+i, y0+j, col); } } return 0;}void SetVideoSystem(struct cvdv_cards *card){ uint8_t reg; // set the hsync and vsync generators in the L64017 according to the video standard reg = read_indexed_register(card, IIO_VIDEO_CONTROL1); reg &= ~0x03; switch (card->videomode) { case PAL: // 864*625*50Hz = 27MHz, 25fps I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x41 | 0x0a); I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x96); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x15); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0x13); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x54); reg |= VMS_PAL; break; case PALN: I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0xa1 | 0x0a); I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x96); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x15); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0x13); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x54); reg |= VMS_PAL; break; case PALNc: I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x81 | 0x0a); I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x8c); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x28); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xed); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); reg |= VMS_PAL; break; case NTSC: // 858*525*59.94006Hz = 27MHz, 29.97fps I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x01 | 0x0a); I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x1c); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x3e); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0xf8); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe0); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); reg |= VMS_NTSC; break; case PALM: I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x01 | 0x0a); I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x4e); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x4a); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe1); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); reg |= VMS_PAL; break; case NTSC60: // 857*525*60.010002Hz = 27MHz, 30fps I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x21 | 0x0a); I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x1c); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x3e); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0xf8); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe0); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); reg |= VMS_NTSC; break; case PALM60: I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x61 | 0x0a); I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x4e); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x4a); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe1); I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); reg |= VMS_PAL; break; case PAL60: break; } write_indexed_register(card, IIO_VIDEO_CONTROL1, reg); // set the pixel generators according to the video standard L64021Setup(card);}int SetVideoAttr(struct cvdv_cards *card, uint16_t vattr){ uint8_t video_compression_mode; uint8_t tv_system; uint8_t aspect_ratio; uint8_t display_mode; uint8_t line_21_switch_1; uint8_t line_21_switch_2; uint8_t source_picture_resolution; uint8_t source_picture_letterboxed; uint8_t reserved; uint8_t film_camera_mode; uint16_t hsize, vsize; if (vattr != card->lastvattr) { video_compression_mode = (vattr >> 14) & 0x03; tv_system = (vattr >> 12) & 0x03; aspect_ratio = (vattr >> 10) & 0x03; display_mode = (vattr >> 8) & 0x03; line_21_switch_1 = (vattr >> 7) & 0x01; line_21_switch_2 = (vattr >> 6) & 0x01; source_picture_resolution = (vattr >> 3) & 0x07; source_picture_letterboxed = (vattr >> 2) & 0x01; reserved = (vattr >> 1) & 0x01; film_camera_mode = (vattr >> 0) & 0x01; card->videomode = ((tv_system == 0) ? NTSC : ((tv_system == 1) ? PAL : PAL)); SetVideoSystem(card); hsize = ((source_picture_resolution == 0) ? 720 : ((source_picture_resolution == 1) ? 702 : 352)); vsize = ((source_picture_resolution == 3) ? ((tv_system == 0) ? 240 : 288) : ((tv_system == 0) ? 480 : 576)); if (DecoderOpen (card, hsize, vsize, ((aspect_ratio) ? 3 : 2), ((video_compression_mode) ? 0 : 1), source_picture_letterboxed, tv_system)) { MDEBUG(0, ": Video Decoder Open failed: On-card memory insufficient for frame stores\n"); } card->lastvattr = vattr; } else { MDEBUG(0, ": Video attribute not set, equal to previous one.\n"); } return 0;}int SetAudioAttr(struct cvdv_cards *card, uint16_t aattr){ uint8_t audio_coding_mode; uint8_t multichannel_extension; uint8_t audio_type; uint8_t audio_application_mode; uint8_t quantization_drc; uint8_t fs; uint8_t reserved; uint8_t num_audio_ch; if (aattr) { if (aattr != card->lastaattr) { audio_coding_mode = (aattr >> 13) & 0x07; multichannel_extension = (aattr >> 12) & 0x01; audio_type = (aattr >> 10) & 0x03; audio_application_mode = (aattr >> 8) & 0x03; quantization_drc = (aattr >> 6) & 0x03; fs = (aattr >> 4) & 0x03; reserved = (aattr >> 3) & 0x01; num_audio_ch = (aattr >> 0) & 0x07; switch (audio_coding_mode) { case 0: // AC-3 card->setup.audioselect = audio_AC3; break; case 2: // MPEG Audio card->setup.audioselect = audio_MPEG; break; case 3: // MPEG Audio with ext. card->setup.audioselect = audio_MPEG_EXT; break; case 4: // Linear Pulse Code fe_modulation_t LPCM card->setup.audioselect = audio_LPCM; break; case 6: // DTS card->setup.audioselect = audio_DTS; break; case 7: // SDDS card->setup.audioselect = audio_SDDS; break; } DecoderPrepareAudio(card); AudioInit(card, ((fs) ? 96 : 48), ((audio_application_mode == 2) ? 1 : 0)); } else { MDEBUG(0, ": Audio attribute not set, equal to previous one.\n"); } } else { card->setup.audioselect = audio_none; DecoderPrepareAudio(card); } card->lastaattr = aattr; return 0;}int Prepare(struct cvdv_cards *card){ int err, h; struct StreamSetup *setup = &card->setup; if (!card->ChannelBuffersAllocated) { DecoderStreamReset(card); if (setup->streamtype == stream_none) { setup->streamtype = stream_PS; } if (setup->audioselect == audio_none) { setup->audioselect = audio_MPEG; } DecoderPrepareAudio(card); AudioMute(card, 1); DecoderPrepareVideo(card); VideoSetBackground(card, 1, 0, 0, 0); // black switch (setup->streamtype) { default: case stream_none: // unknown stream! MDEBUG(0, ": Video Decoder Prepare failed: unknown stream type\n"); return -ENODEV; // not an MPEG stream! case stream_ES: // Elementary Stream err = DecoderPrepareES(card); break; case stream_PES: // Packetized Elementary Stream err = DecoderPreparePES(card); break; case stream_PS: // MPEG-1 System Stream / MPEG-2 Program Stream err = DecoderPreparePS(card, -1, 0, 0, 0, 0, 0); break; case stream_DVD: // DVD Stream err = DecoderPreparePS(card, 0, 0, 0, 0, 3, 1); break; } if (err) { // insufficient memory MDEBUG(0, ": Video Decoder Prepare failed: no kernel memory, please reboot if possible\n"); CloseCard(card); return -ENODEV; } } // Set up the Video Decoder as we have the stream information if ((!card->FrameBuffersAllocated) && (card->ChannelBuffersAllocated) && (card->stream.sh.valid)) { // Automatic PAL/NTSC-switch according to MPEG-Source h = card->stream.vsize; if (h < 480) h *= 2; // catch quarter sized images printk(KERN_INFO LOGNAME ": Video mode: %s\n", ((h == 480) ? "NTSC" : "PAL")); card->videomode = ((h == 480) ? NTSC : PAL); SetVideoSystem(card); // Open the Video Decoder with the parameters retreived from the stream if ( (err = DecoderOpen(card, card->stream.hsize, card->stream.vsize, card->stream.sh.aspectratio, !card->stream.MPEG2, 0, (card->stream.hsize > 480)))) { // TODO: include vbvbuffersize MDEBUG(0, ": Video Decoder Open failed: %s\n", ((err == 1) ? "Picture size too big (>1440 pixel wide)" : "On-card memory insufficient for frame stores")); CloseCard(card); return -ENODEV; // picture too big or insufficient memory } MDEBUG(1, ": Ready to go\n"); card->startingV = 1; // tell the card to start playing as soon as ES-buffers are sufficiently full card->startingA = 1; // tell the card to start playing as soon as ES-buffers are sufficiently full } return 0;}int SetSCRstart(struct cvdv_cards *card, uint32_t SCR_base){ uint32_t SCR_compare; uint32_t SCR_compareA; uint32_t SCR_compareV; if (card->startingV) { MDEBUG(0, ": SCR in DVD Pack: 0x%08X\n", SCR_base); card->startingV = 0; card->startingA = 0; DecoderMaskByte(card, 0x007, 0xD2, 0xD2); // Set 0x010, halt SCR counter SCR_compare = SCR_base + 000; if (SCR_base < 900) SCR_base = 0; else SCR_base -= 900; //DecoderWriteDWord(card,0x009,SCR_base); // Set SCR counter DecoderWriteByte(card, 0x009, SCR_base & 0xFF); // Set SCR counter DecoderWriteByte(card, 0x00A, (SCR_base >> 8) & 0xFF); DecoderWriteByte(card, 0x00B, (SCR_base >> 16) & 0xFF); DecoderWriteByte(card, 0x00C, (SCR_base >> 24) & 0xFF); DecoderMaskByte(card, 0x011, 0x03, 0x02); // compare, not capture MDEBUG(0, ": SCR compare value: 0x%08X\n", SCR_compare); //DecoderWriteDWord(card,0x00D,SCR_compare); // Set Compare register DecoderWriteByte(card, 0x00D, SCR_compare & 0xFF); // Set Compare register DecoderWriteByte(card, 0x00E, (SCR_compare >> 8) & 0xFF); DecoderWriteByte(card, 0x00F, (SCR_compare >> 16) & 0xFF); DecoderWriteByte(card, 0x010, (SCR_compare >> 24) & 0xFF); //DecoderWriteDWord(card,0x014,SCR_compare); // Set audio compare reg. DecoderWriteByte(card, 0x014, SCR_compare & 0xFF); // Set audio compare reg. DecoderWriteByte(card, 0x015, (SCR_compare >> 8) & 0xFF); DecoderWriteByte(card, 0x016, (SCR_compare >> 16) & 0xFF); DecoderWriteByte(card, 0x017, (SCR_compare >> 24) & 0xFF); DecoderSetByte(card, 0x013, 0x03); // Video and Audio start on cmp. //DecoderSetVideoPanic(card,0,DecoderGetVideoESSize(card)/4); // video panic at 25 percent VideoSetBackground(card, 1, 0, 0, 0); // black SCR_base = DecoderReadByte(card, 0x009); SCR_base = SCR_base | ((uint32_t) DecoderReadByte(card, 0x00A) << 8); SCR_base = SCR_base | ((uint32_t) DecoderReadByte(card, 0x00B) << 16); SCR_base = SCR_base | ((uint32_t) DecoderReadByte(card, 0x00C) << 24); SCR_compareA = DecoderReadByte(card, 0x014); SCR_compareA = SCR_compareA | ((uint32_t) DecoderReadByte(card, 0x015) << 8); SCR_compareA = SCR_compareA | ((uint32_t) DecoderReadByte(card, 0x016) << 16); SCR_compareA = SCR_compareA | ((uint32_t) DecoderReadByte(card, 0x017) << 24); SCR_compareV = DecoderReadByte(card, 0x00D); SCR_compareV = SCR_compareV | ((uint32_t) DecoderReadByte(card, 0x00E) << 8); SCR_compareV = SCR_compareV | ((uint32_t) DecoderReadByte(card, 0x00F) << 16); SCR_compareV = SCR_compareV | ((uint32_t) DecoderReadByte(card, 0x010) << 24); if (DecoderReadByte(card, 0x013) & 0x03) MDEBUG(1,": SCR 0x%08X, videocmp=0x%08X, audiocmp=0x%08X %02X\n", SCR_base, SCR_compareV, SCR_compareA, DecoderReadByte(card, 0x013)); DecoderMaskByte(card, 0x007, 0xD2, 0xC2); // Del 0x010, SCR counter run } return 0;} ////////////////////////////// // // // Char Device Procedures // // ////////////////////////////////static long margi_write(struct cvdv_cards *card, const char *data, unsigned long count, int nonblock){ int res; long int out=0; int free; free = ring_write_rest(&(card->rbufA)); if (card != NULL) { card->nonblock = nonblock; if (count > 0) { // Do we have data? if ((res = Prepare(card))) return res; if (!card->use_ringA) MargiSetBuffers(card, NBBUF*CHANNELBUFFERSIZE, 0); if (!nonblock && !wait_event_interruptible( card->wqA, ring_write_rest(&(card->rbufA)) >count )){ out = MargiPushA(card, count, data); } else { out = MargiPushA(card, count, data); } } return out; } else { MDEBUG(0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -