diff options
author | Johannes Stezenbach <devnull@localhost> | 2003-04-22 13:19:05 +0000 |
---|---|---|
committer | Johannes Stezenbach <devnull@localhost> | 2003-04-22 13:19:05 +0000 |
commit | e4b81e505a1aee843073badd3062488776aecfa0 (patch) | |
tree | 15a0ccc7e599b1d0371c2e67522e4e9473f99c4b /linux/drivers/media/dvb/ttpci/av7110.c | |
parent | fb1f8cef99947775eaab5a571de9a79ddad04888 (diff) | |
download | mediapointer-dvb-s2-e4b81e505a1aee843073badd3062488776aecfa0.tar.gz mediapointer-dvb-s2-e4b81e505a1aee843073badd3062488776aecfa0.tar.bz2 |
As announced last week:
Video API change for VIDEO_EVENT_SIZE_CHANGED and VIDEO_GET_SIZE ioctl,
and VIDEO_FORMAT_221_1.
Implemented video events for VIDEO_EVENT_SIZE_CHANGED (use poll(2) with
POLLPRI) and ioctl VIDEO_GET_SIZE.
Diffstat (limited to 'linux/drivers/media/dvb/ttpci/av7110.c')
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110.c | 139 |
1 files changed, 135 insertions, 4 deletions
diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 11c2856ab..5b00e7cba 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -96,6 +96,7 @@ static inline int i2c_writereg(av7110_t *av7110, u8 id, u8 reg, u8 val); static inline u8 i2c_readreg(av7110_t *av7110, u8 id, u8 reg); static int outcom(av7110_t *av7110, int type, int com, int num, ...); static void SetMode(av7110_t *av7110, int mode); +static void dvb_video_add_event (av7110_t *av7110, struct video_event *event); void pes_to_ts(u8 const *buf, long int length, u16 pid, p2t_t *p); void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed); @@ -907,6 +908,47 @@ void gpioirq (unsigned long data) case DATA_PES_PLAY: break; + case DATA_MPEG_VIDEO_EVENT: + { + u32 h_ar; + struct video_event event; + + av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2); + h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2); + + iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); + iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); + + av7110->video_size.h = h_ar & 0xfff; + DEB_D(("GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", + av7110->video_size.w, + av7110->video_size.h, + av7110->video_size.aspect_ratio)); + + event.type = VIDEO_EVENT_SIZE_CHANGED; + event.u.size.w = av7110->video_size.w; + event.u.size.h = av7110->video_size.h; + switch ((h_ar >> 12) & 0xf) + { + case 3: + av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9; + event.u.size.aspect_ratio = VIDEO_FORMAT_16_9; + av7110->videostate.video_format = VIDEO_FORMAT_16_9; + break; + case 4: + av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1; + event.u.size.aspect_ratio = VIDEO_FORMAT_221_1; + av7110->videostate.video_format = VIDEO_FORMAT_221_1; + break; + default: + av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3; + event.u.size.aspect_ratio = VIDEO_FORMAT_4_3; + av7110->videostate.video_format = VIDEO_FORMAT_4_3; + } + dvb_video_add_event(av7110, &event); + break; + } + case DATA_CI_PUT: { int avail; @@ -3313,6 +3355,76 @@ dvb_ca_read(struct file *file, char *buf, size_t count, loff_t *ppos) /****************************************************************************** + * Video MPEG decoder events + ******************************************************************************/ +static +void dvb_video_add_event (av7110_t *av7110, struct video_event *event) +{ + struct dvb_video_events *events = &av7110->video_events; + int wp; + + DEB_D(("\n")); + + if (down_interruptible (&events->sem)) + return; + + wp = (events->eventw + 1) % MAX_VIDEO_EVENT; + + if (wp == events->eventr) { + events->overflow = 1; + events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT; + } + + //FIXME: timestamp? + memcpy(&events->events[events->eventw], event, sizeof(struct video_event)); + + events->eventw = wp; + + up (&events->sem); + + wake_up_interruptible (&events->wait_queue); +} + + +static +int dvb_video_get_event (av7110_t *av7110, struct video_event *event, int flags) +{ + struct dvb_video_events *events = &av7110->video_events; + + DEB_D(("\n")); + + if (events->overflow) { + events->overflow = 0; + return -EOVERFLOW; + } + + if (events->eventw == events->eventr) { + int ret; + + if (flags & O_NONBLOCK) + return -EWOULDBLOCK; + + ret = wait_event_interruptible (events->wait_queue, + events->eventw != events->eventr); + if (ret < 0) + return ret; + } + + if (down_interruptible (&events->sem)) + return -ERESTARTSYS; + + memcpy (event, &events->events[events->eventr], + sizeof(struct video_event)); + + events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT; + + up (&events->sem); + + return 0; +} + + +/****************************************************************************** * DVB device file operations ******************************************************************************/ @@ -3326,12 +3438,16 @@ unsigned int dvb_video_poll(struct file *file, poll_table *wait) DEB_EE(("av7110: %p\n",av7110)); poll_wait(file, &av7110->avout.queue, wait); + poll_wait(file, &av7110->video_events.wait_queue, wait); + + if (av7110->video_events.eventw != av7110->video_events.eventr) + mask = POLLPRI; if (av7110->playing) { if (FREE_COND) mask |= (POLLOUT | POLLWRNORM); } else /* if not playing: may play if asked for */ - mask = (POLLOUT | POLLWRNORM); + mask |= (POLLOUT | POLLWRNORM); return mask; } @@ -3469,9 +3585,13 @@ dvb_video_ioctl(struct inode *inode, struct file *file, break; case VIDEO_GET_EVENT: - //FIXME: write firmware support for this - ret=-EOPNOTSUPP; - + ret=dvb_video_get_event(av7110, parg, file->f_flags); + break; + + case VIDEO_GET_SIZE: + memcpy(parg, &av7110->video_size, sizeof(video_size_t)); + break; + case VIDEO_SET_DISPLAY_FORMAT: { video_displayformat_t format=(video_displayformat_t) arg; @@ -3720,6 +3840,11 @@ static int dvb_video_open(struct inode *inode, struct file *file) av7110->video_blank=1; av7110->audiostate.AV_sync_state=1; av7110->videostate.stream_source=VIDEO_SOURCE_DEMUX; + + if ((file->f_flags & O_ACCMODE) != O_RDONLY) + /* empty event queue */ + av7110->video_events.eventr = av7110->video_events.eventw = 0; + return 0; } @@ -3924,6 +4049,12 @@ int av7110_register(av7110_t *av7110) if (ret < 0) return ret; + init_waitqueue_head (&av7110->video_events.wait_queue); + init_MUTEX (&av7110->video_events.sem); + av7110->video_events.eventw = av7110->video_events.eventr = 0; + av7110->video_events.overflow = 0; + memset(&av7110->video_size, 0, sizeof (video_size_t)); + dvb_register_device(av7110->dvb_adapter, &av7110->video_dev, &dvbdev_video, av7110, DVB_DEVICE_VIDEO); |