--- margi2/cvdv.c 2001/02/01 14:47:33 1.5 +++ margi2/cvdv.c 2001/03/06 23:39:26 1.6 @@ -487,12 +487,13 @@ int DecoderWriteBlock(struct cvdv_cards int co = 0; // u32 SCR_compare; res = 0; - //Prepare(card); + + Prepare(card); if (size > 0) { if (!card->use_ring) - MargiSetBuffers(card, NBBUF* + MargiSetBuffers(card, NBBUF* 128 * CHANNELBUFFERSIZE); if (card->startingDVDV || card->startingDVDA) @@ -500,7 +501,6 @@ int DecoderWriteBlock(struct cvdv_cards if (initial) { DecoderStreamReset(card); - DecoderSetupReset(card); //TODO stop and start channel interface setSCR = 1; } @@ -509,29 +509,29 @@ int DecoderWriteBlock(struct cvdv_cards SCR_base = ParseSCR(data); SetSCR(card, SCR_base); } - + card->DMAABusy = 0; while (((res = MargiPush(card, size, data)) < size) - && co < 100) { + && co < 1000) { data+=res; size-=res; co++; -// printk(KERN_DEBUG LOGNAME + // printk(KERN_DEBUG LOGNAME // ": DecoderWriteBlock - buffers only filled with %d instead of %d bytes\n", - // res, size); + // res, size); if (card->DMAABusy) interruptible_sleep_on(&card->wqA); } if (card->startingDVDV) { card->startingDVDV = 0; + card->startingV = 1; DecoderStartDecode(card); } if (card->startingDVDA) { card->startingDVDA = 0; - AudioSetPlayMode(card, AUDIO_PLAY); + card->startingA = 1; + AudioSetPlayMode(card, MAUDIO_PLAY); } - - } return 0; } @@ -545,18 +545,17 @@ int DecoderWriteBlock(struct cvdv_cards // Char Device Procedures // // // ////////////////////////////// - -static ssize_t PSwrite(struct file *file, const char *data, size_t count, - loff_t * offset) +static long margi_write(struct video_device *dev, const char *data, + unsigned long count, int nonblock) { - struct cvdv_cards *card = - minorlist[MINOR(file->f_dentry->d_inode->i_rdev) % MAXDEV]; // minor number modulo 16 - int channel = MINOR(file->f_dentry->d_inode->i_rdev) / MAXDEV; // minor number div. 16 + struct cvdv_cards *card = (struct cvdv_cards*)dev; + struct StreamSetup *setup = &card->setup; // int i; // int laststart=-1; // int B3=0, B5=0, C0=0, E0=0, BD=0, BF=0; int res; + int channel=0; if (card != NULL) { if (count > 0) { // Do we have data? @@ -592,13 +591,22 @@ static ssize_t PSwrite(struct file *file ": Video Decoder Prepare failed: device with this minor number not found\n"); return -ENODEV; // device with this minor number not found } +} + + +static ssize_t PSwrite(struct file *file, const char *data, size_t count, + loff_t * offset) +{ + struct cvdv_cards *card = + minorlist[MINOR(file->f_dentry->d_inode->i_rdev) % MAXDEV]; // minor number modulo 16 + return margi_write((struct video_device *)card, data, count, 0); + } static unsigned int PSpoll(struct file *file, poll_table * table) { struct cvdv_cards *card = minorlist[MINOR(file->f_dentry->d_inode->i_rdev) % MAXDEV]; // minor number modulo 16 -// int channel=MINOR(file->f_dentry->d_inode->i_rdev) / MAXDEV; // minor number div. 16 if (card != NULL) { return POLLOUT | POLLWRNORM; // always writeable, HAS TO BE CHANGED!!!! @@ -607,11 +615,18 @@ static unsigned int PSpoll(struct file * return POLLERR; // device with this minor number not found } + +static int margi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + // struct cvdv_cards *card = (struct cvdv_cards*)dev; + return 0; +} + + static int PSioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct cvdv_cards *card = minorlist[MINOR(inode->i_rdev) % MAXDEV]; // minor number modulo 16 -// int channel=MINOR(inode->i_rdev) / MAXDEV; // minor number div. 16 struct drawcmd *dc; struct decodercmd *command; u16 attr; @@ -823,8 +838,6 @@ static int PSioctl(struct inode *inode, stream_DVD; card->setup.videoID = 0; DecoderPrepareVideo(card); - //VideoSetBackground(card,1,0,0,0); // black - //DecoderPreparePS(card, -1, 1,2,2,3,1); DecoderPreparePS(card, 0, 0, 2, 2, 3, 1); @@ -832,7 +845,8 @@ static int PSioctl(struct inode *inode, SetVideoAttr(card, command->param1); - card->startingDVDV = 1; // tell the card to start playing as soon as ES-buffers are sufficiently full + card->startingDVDV = 1; +// tell the card to start playing as soon as ES-buffers are sufficiently full return 0; case Decoder_Set_Audioattribute: printk(KERN_DEBUG LOGNAME @@ -868,33 +882,41 @@ static int PSioctl(struct inode *inode, } } + static int PSmmap(struct file *file, struct vm_area_struct *vm) { return -ENODEV; } -static int PSopen(struct inode *inode, struct file *file) + + +static int margi_open(struct video_device *dev, int flags) { - struct cvdv_cards *card = minorlist[MINOR(inode->i_rdev) % MAXDEV]; // minor number modulo 16 - int channel = MINOR(inode->i_rdev) / MAXDEV; // minor number div. 16 - int i, closed; + struct cvdv_cards *card = (struct cvdv_cards*)dev; + + int closed; if (card != NULL) { - printk(KERN_DEBUG LOGNAME ": -- PSopen %d\n",channel); + printk(KERN_DEBUG LOGNAME ": -- PSopen \n"); CloseCard(card); OSDClose(card); - if (card->open[channel]) +#ifdef NOINT + card->timer.function = Timerfunction; + card->timer.data=(unsigned long) card; + card->timer.expires=jiffies+1; + add_timer(&card->timer); +#endif + + if (card->open) printk(KERN_DEBUG LOGNAME - ": PSopen - already open: channel %d\n", - channel); + ": PSopen - already open\n"); closed = 1; - for (i = 0; i < MINORNUM; i++) - if (card->open[i]) - closed = 0; + if (card->open) + closed = 0; if (closed) { // first open() for this card? MargiFreeBuffers(card); VideoSetBackground(card, 1, 0, 0, 0); // black } - card->open[channel]++; + card->open++; //MOD_INC_USE_COUNT; return 0; } else { @@ -902,30 +924,35 @@ static int PSopen(struct inode *inode, s ": Video Decoder Prepare failed: device with this minor number not found\n"); return -ENODEV; // device with this minor number not found } + } -static int PSrelease(struct inode *inode, struct file *file) + +static int PSopen(struct inode *inode, struct file *file) { struct cvdv_cards *card = minorlist[MINOR(inode->i_rdev) % MAXDEV]; // minor number modulo 16 - int channel = MINOR(inode->i_rdev) / MAXDEV; // minor number div. 16 - int i, closed; + return margi_open((struct video_device *) card,0); +} + + +static int all_margi_close(struct video_device *dev) +{ + struct cvdv_cards *card = (struct cvdv_cards*)dev; + + int closed; int count; count = ring_read_rest(&(card->rbuf)); if (count > 0 ) card->DMAABusy = 1; if (card != NULL) { printk(KERN_DEBUG LOGNAME ": -- PSrelease\n"); - if (!card->open[channel]) + if (!card->open) printk(KERN_DEBUG LOGNAME - ": PSrelease - not open: channel %d\n", - channel); - card->open[channel]--; + ": PSrelease - not open\n"); + card->open--; //MOD_DEC_USE_COUNT; - if (!card->open[channel]) { + if (!card->open) { closed = 1; - for (i = 0; i < MINORNUM; i++) - if (card->open[i]) - closed = 0; if (closed) { // last close() for this card? printk(KERN_DEBUG LOGNAME ": PSrelease - last close\n"); @@ -956,6 +983,19 @@ static int PSrelease(struct inode *inode ": Video Decoder Prepare failed: device with this minor number not found\n"); return -ENODEV; // device with this minor number not found } + +} + + +static void margi_close(struct video_device *dev) +{ + all_margi_close(dev); +} + +static int PSrelease(struct inode *inode, struct file *file) +{ + struct cvdv_cards *card = minorlist[MINOR(inode->i_rdev) % MAXDEV]; // minor number modulo 16 + return all_margi_close((struct video_device *)card); } ////////////////////////// @@ -973,3 +1013,494 @@ struct file_operations cvdv_fileops = { open: PSopen, release: PSrelease, }; + +static int margi_init_done(struct video_device *dev) +{ + printk(KERN_ERR "margi: margi_init_done called\n"); + return 0; +} + +static int margi_mmap(struct video_device *dev, + const char *adr, unsigned long size) +{ + return 0; +} + +static struct video_device margi_template = { + name: "Margi MPEG2 Decoder", + type: (VID_TYPE_MPEG_DECODER), + open: margi_open, + close: margi_close, + write: margi_write, + ioctl: margi_ioctl, + mmap: margi_mmap, + initialize: margi_init_done, +}; + + + +#ifdef DVB + +static inline int +num2type(struct cvdv_cards *card, int num) +{ + if (!card->dvb_devs) + return -2; + if (num>=card->dvb_devs->num) + return -2; + return card->dvb_devs->tab[num]; +} + +static int +dvbdev_open(struct dvb_device *dvbdev, int num, + struct inode *inode, struct file *file) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + int ret=0; + + if (type<0) + return -EINVAL; + + if (card->users[num] >= card->dvb_devs->max_users[num]) + return -EBUSY; + + if ((file->f_flags&O_ACCMODE)!=O_RDONLY) + if (card->writers[num] >= card->dvb_devs->max_writers[num]) + return -EBUSY; + + switch (type) { + case DVB_DEVICE_VIDEO_0: + card->video_blank=true; + card->audiostate.AVSyncState=true; + card->videostate.streamSource=VIDEO_SOURCE_DEMUX; + break; + + case DVB_DEVICE_AUDIO_0: + card->audiostate.streamSource=AUDIO_SOURCE_DEMUX; + break; + + case DVB_DEVICE_DEMUX_0: + if ((file->f_flags&O_ACCMODE)!=O_RDWR) + return -EINVAL; + ret=DmxDevFilterAlloc(&card->dmxdev, file); + break; + case DVB_DEVICE_DVR_0: + ret=DmxDevDVROpen(&card->dmxdev, file); + break; + default: + return -EINVAL; + } + if (ret<0) + return ret; + if ((file->f_flags&O_ACCMODE)!=O_RDONLY) + card->writers[num]++; + card->users[num]++; + return ret; +} + +static int +dvbdev_close(struct dvb_device *dvbdev, int num, + struct inode *inode, struct file *file) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + int ret=0; + + if (type<0) + return -EINVAL; + + switch (type) { + case DVB_DEVICE_VIDEO_0: + all_margi_close((struct video_device *)card); + break; + + case DVB_DEVICE_AUDIO_0: + all_margi_close((struct video_device *)card); + break; + + case DVB_DEVICE_DEMUX_0: + ret=DmxDevFilterFree(&card->dmxdev, file); + break; + + case DVB_DEVICE_DVR_0: + ret=DmxDevDVRClose(&card->dmxdev, file); + break; + default: + return -EINVAL; + } + if (ret<0) + return ret; + if ((file->f_flags&O_ACCMODE)!=O_RDONLY) + card->writers[num]--; + card->users[num]--; + return ret; +} + +static ssize_t +dvbdev_write(struct dvb_device *dvbdev, int num, + struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + + switch (type) { + case DVB_DEVICE_VIDEO_0: + if (card->videostate.streamSource!=VIDEO_SOURCE_MEMORY) + return -EPERM; + return margi_write((struct video_device *)card, buf, count, + file->f_flags&O_NONBLOCK); + + case DVB_DEVICE_AUDIO_0: + if (card->audiostate.streamSource!=AUDIO_SOURCE_MEMORY) + return -EPERM; + return count; + + case DVB_DEVICE_DVR_0: + return DmxDevDVRWrite(&card->dmxdev, file, buf, count, ppos); + default: + return -EOPNOTSUPP; + } + return 0; +} + + +static int +dvbdev_ioctl(struct dvb_device *dvbdev, int num, + struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + void *parg=(void *)arg; + int type=num2type(card, num); + + switch (type) { + case DVB_DEVICE_VIDEO_0: + if (((file->f_flags&O_ACCMODE)==O_RDONLY) && + (cmd!=VIDEO_GET_STATUS)) + return -EPERM; + + switch (cmd) { + + case VIDEO_STOP: + card->videostate.playState=VIDEO_STOPPED; + DecoderPause(card); + return 0; + + case VIDEO_PLAY: + + if (card->videostate.streamSource== + VIDEO_SOURCE_MEMORY) { + DecoderUnPause(card); + } + card->videostate.playState=VIDEO_PLAYING; + break; + + case VIDEO_FREEZE: + card->videostate.playState=VIDEO_FREEZED; + DecoderPause(card); + break; + + case VIDEO_CONTINUE: + if (card->videostate.playState==VIDEO_FREEZED) { + DecoderUnPause(card); + } + break; + + case VIDEO_SELECT_SOURCE: + card->videostate.streamSource=(videoStreamSource_t) arg; + break; + + case VIDEO_SET_BLANK: + card->videostate.videoBlank=(boolean) arg; + break; + + case VIDEO_GET_STATUS: + if(copy_to_user(parg, &card->videostate, + sizeof(struct videoStatus))) + return -EFAULT; + break; + + case VIDEO_GET_EVENT: + return -EOPNOTSUPP; + + case VIDEO_SET_DISPLAY_FORMAT: + { + videoDisplayFormat_t format=(videoDisplayFormat_t) arg; + u16 val=0; + + switch(format) { + case VIDEO_PAN_SCAN: + val=VID_PAN_SCAN_PREF; + break; + + case VIDEO_LETTER_BOX: + val=VID_VC_AND_PS_PREF; + break; + + case VIDEO_CENTER_CUT_OUT: + val=VID_CENTRE_CUT_PREF; + break; + + default: + return -EINVAL; + } + + card->videostate.videoFormat=format; + return 0; + } + + case VIDEO_STILLPICTURE: + { + struct videoDisplayStillPicture pic; + + if(copy_from_user(&pic, parg, + sizeof(struct videoDisplayStillPicture))) + return -EFAULT; + + break; + } + + case VIDEO_FAST_FORWARD: + if (card->videostate.streamSource!=VIDEO_SOURCE_MEMORY) + return -EPERM; + break; + + case VIDEO_SLOWMOTION: + if (card->videostate.streamSource!=VIDEO_SOURCE_MEMORY) + return -EPERM; + + break; + + case VIDEO_GET_CAPABILITIES: + { + int cap=VIDEO_CAP_MPEG1| + VIDEO_CAP_MPEG2| + VIDEO_CAP_SYS| + VIDEO_CAP_PROG; + + if (copy_to_user(parg, &cap, + sizeof(cap))) + return -EFAULT; + break; + } + default: + return -ENOIOCTLCMD; + } + return 0; + + case DVB_DEVICE_AUDIO_0: + if (((file->f_flags&O_ACCMODE)==O_RDONLY) && + (cmd!=AUDIO_GET_STATUS)) + return -EPERM; + + switch (cmd) { + + case AUDIO_STOP: + if (card->audiostate.streamSource!=AUDIO_SOURCE_MEMORY) + break; + AudioStopDecode(card); + card->audiostate.playState=AUDIO_STOPPED; + break; + + case AUDIO_PLAY: + if (card->audiostate.streamSource!=AUDIO_SOURCE_MEMORY) + break; + AudioSetPlayMode(card, MAUDIO_PLAY); + card->audiostate.playState=AUDIO_PLAYING; + break; + + case AUDIO_PAUSE: + card->audiostate.playState=AUDIO_PAUSED; + AudioSetPlayMode(card, MAUDIO_PAUSE); + break; + + case AUDIO_CONTINUE: + if (card->audiostate.playState==AUDIO_PAUSED) { + card->audiostate.playState=AUDIO_PLAYING; + AudioSetPlayMode(card, MAUDIO_PLAY); + } + break; + + case AUDIO_SELECT_SOURCE: + card->audiostate.streamSource=(audioStreamSource_t) arg; + break; + + case AUDIO_SET_MUTE: + { + AudioMute(card, arg); + card->audiostate.muteState=(boolean) arg; + break; + } + + case AUDIO_SET_AV_SYNC: + card->audiostate.AVSyncState=(boolean) arg; + break; + + case AUDIO_SET_BYPASS_MODE: + return -EINVAL; + + case AUDIO_CHANNEL_SELECT: + card->audiostate.channelSelect=(audioChannelSelect_t) arg; + + switch(card->audiostate.channelSelect) { + case AUDIO_STEREO: + break; + + case AUDIO_MONO_LEFT: + break; + + case AUDIO_MONO_RIGHT: + break; + + default: + return -EINVAL; + } + return 0; + + case AUDIO_GET_STATUS: + if(copy_to_user(parg, &card->audiostate, + sizeof(struct audioStatus))) + return -EFAULT; + break; + + case AUDIO_GET_CAPABILITIES: + { + int cap=AUDIO_CAP_LPCM| + AUDIO_CAP_MP1| + AUDIO_CAP_MP2; + + if (copy_to_user(parg, &cap, + sizeof(cap))) + return -EFAULT; + break; + } + default: + return -ENOIOCTLCMD; + } + break; + + + case DVB_DEVICE_DEMUX_0: + return DmxDevIoctl(&card->dmxdev, file, cmd, arg); + + default: + return -EOPNOTSUPP; + } + return 0; +} + +static unsigned int +dvbdev_poll(struct dvb_device *dvbdev, int num, + struct file *file, poll_table * wait) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + + switch (type) { + case DVB_DEVICE_DEMUX_0: + return DmxDevPoll(&card->dmxdev, file, wait); + + case DVB_DEVICE_VIDEO_0: + return PSpoll(file, wait); + + case DVB_DEVICE_AUDIO_0: + return PSpoll(file, wait); + + case DVB_DEVICE_CA_0: + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + + +static int +dvbdev_device_type(struct dvb_device *dvbdev, unsigned int num) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + + return num2type(card, num); +} +#endif + +/****************************************************************************** + * driver registration + ******************************************************************************/ + + +void v4l_init(struct cvdv_cards *card) +{ + + memcpy( &card->video, &margi_template, sizeof(struct video_device)); + + if( 0 > (video_register_device(&card->video, VFL_TYPE_GRABBER))) { + printk(KERN_ERR "margi: can't register videodevice\n"); + } +} + +#ifdef DVB + +#define INFU 32768 + +static dvb_devs_t mdvb_devs = { + 4, + { + DVB_DEVICE_VIDEO_0, DVB_DEVICE_AUDIO_0, + DVB_DEVICE_DEMUX_0, DVB_DEVICE_DVR_0 + }, + { INFU, INFU, INFU, INFU}, + { 1, 1, INFU, 1} +}; + +int dvb_register(struct cvdv_cards *card) +{ + int i; + struct dvb_device *dvbd=&card->dvb_dev; + + if (card->dvb_registered) + return -1; + card->dvb_registered=1; + + card->audiostate.AVSyncState=0; + card->audiostate.muteState=0; + card->audiostate.playState=AUDIO_STOPPED; + card->audiostate.streamSource=AUDIO_SOURCE_MEMORY; + card->audiostate.channelSelect=AUDIO_STEREO; + card->audiostate.bypassMode=0; + + card->videostate.videoBlank=0; + card->videostate.playState=VIDEO_STOPPED; + card->videostate.streamSource=VIDEO_SOURCE_MEMORY; + card->videostate.videoFormat=VIDEO_FORMAT_4_3; + card->videostate.displayFormat=VIDEO_CENTER_CUT_OUT; + + // init and register demuxes + + + // init and register dvb device structure + dvbd->priv=(void *) card; + dvbd->open=dvbdev_open; + dvbd->close=dvbdev_close; + dvbd->write=dvbdev_write; + dvbd->ioctl=dvbdev_ioctl; + dvbd->poll=dvbdev_poll; + dvbd->device_type=dvbdev_device_type; + + for (i=0; iusers[i]=card->writers[i]=0; + + card->dvb_devs=0; + card->dvb_devs=&mdvb_devs; + + return dvb_register_device(dvbd); +} + +void dvb_unregister(struct cvdv_cards *card) +{ + dvb_unregister_device(&card->dvb_dev); +} +#endif