summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/ttpci/av7110.c
diff options
context:
space:
mode:
authorJohannes Stezenbach <devnull@localhost>2003-04-22 13:19:05 +0000
committerJohannes Stezenbach <devnull@localhost>2003-04-22 13:19:05 +0000
commite4b81e505a1aee843073badd3062488776aecfa0 (patch)
tree15a0ccc7e599b1d0371c2e67522e4e9473f99c4b /linux/drivers/media/dvb/ttpci/av7110.c
parentfb1f8cef99947775eaab5a571de9a79ddad04888 (diff)
downloadmediapointer-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.c139
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);