Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / media / dvb / ttpci / av7110_av.c
index b922851..2eff09f 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
 
-#define DEBUG_VARIABLE av7110_debug
-extern int av7110_debug;
-
 #include "av7110.h"
 #include "av7110_hw.h"
 #include "av7110_av.h"
 #include "av7110_ipack.h"
-#include "dvb_functions.h"
 
 /* MPEG-2 (ISO 13818 / H.222.0) stream types */
 #define PROG_STREAM_MAP  0xBC
@@ -102,8 +98,6 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
 {
        struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv;
 
-//     DEB_EE(("struct dvb_filter_pes2ts:%p\n", p2t));
-
        if (!(dvbdmxfeed->ts_type & TS_PACKET))
                return 0;
        if (buf[3] == 0xe0)      // video PES do not have a length in TS
@@ -119,8 +113,6 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
 {
        struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
 
-//     DEB_EE(("dvb_demux_feed:%p\n", dvbdmxfeed));
-
        dvbdmxfeed->cb.ts(data, 188, NULL, 0,
                          &dvbdmxfeed->feed.ts, DMX_OK);
        return 0;
@@ -129,9 +121,10 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
 int av7110_av_start_record(struct av7110 *av7110, int av,
                           struct dvb_demux_feed *dvbdmxfeed)
 {
+       int ret = 0;
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 
-       DEB_EE(("av7110: %p, dvb_demux_feed:%p\n", av7110, dvbdmxfeed));
+       dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed);
 
        if (av7110->playing || (av7110->rec_mode & av))
                return -EBUSY;
@@ -145,7 +138,7 @@ int av7110_av_start_record(struct av7110 *av7110, int av,
                                       dvbdmx->pesfilter[0]->pid,
                                       dvb_filter_pes2ts_cb,
                                       (void *) dvbdmx->pesfilter[0]);
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
                break;
 
        case RP_VIDEO:
@@ -153,7 +146,7 @@ int av7110_av_start_record(struct av7110 *av7110, int av,
                                       dvbdmx->pesfilter[1]->pid,
                                       dvb_filter_pes2ts_cb,
                                       (void *) dvbdmx->pesfilter[1]);
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
                break;
 
        case RP_AV:
@@ -165,15 +158,16 @@ int av7110_av_start_record(struct av7110 *av7110, int av,
                                       dvbdmx->pesfilter[1]->pid,
                                       dvb_filter_pes2ts_cb,
                                       (void *) dvbdmx->pesfilter[1]);
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
                break;
        }
-       return 0;
+       return ret;
 }
 
 int av7110_av_start_play(struct av7110 *av7110, int av)
 {
-       DEB_EE(("av7110: %p\n", av7110));
+       int ret = 0;
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (av7110->rec_mode)
                return -EBUSY;
@@ -190,54 +184,57 @@ int av7110_av_start_play(struct av7110 *av7110, int av)
        av7110->playing |= av;
        switch (av7110->playing) {
        case RP_AUDIO:
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
                break;
        case RP_VIDEO:
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
                av7110->sinfo = 0;
                break;
        case RP_AV:
                av7110->sinfo = 0;
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
                break;
        }
-       return av7110->playing;
+       if (!ret)
+               ret = av7110->playing;
+       return ret;
 }
 
-void av7110_av_stop(struct av7110 *av7110, int av)
+int av7110_av_stop(struct av7110 *av7110, int av)
 {
-       DEB_EE(("av7110: %p\n", av7110));
+       int ret = 0;
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (!(av7110->playing & av) && !(av7110->rec_mode & av))
-               return;
-
+               return 0;
        av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
        if (av7110->playing) {
                av7110->playing &= ~av;
                switch (av7110->playing) {
                case RP_AUDIO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
                        break;
                case RP_VIDEO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
                        break;
                case RP_NONE:
-                       av7110_set_vidmode(av7110, av7110->vidmode);
+                       ret = av7110_set_vidmode(av7110, av7110->vidmode);
                        break;
                }
        } else {
                av7110->rec_mode &= ~av;
                switch (av7110->rec_mode) {
                case RP_AUDIO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
                        break;
                case RP_VIDEO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
                        break;
                case RP_NONE:
                        break;
                }
        }
+       return ret;
 }
 
 
@@ -247,8 +244,6 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
        u32 sync;
        u16 blen;
 
-       DEB_EE(("dvb_ring_buffer_t: %p\n", buf));
-
        if (!dlen) {
                wake_up(&buf->queue);
                return -1;
@@ -279,8 +274,8 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
 
        dvb_ringbuffer_read(buf, dest, (size_t) blen, 0);
 
-       DEB_S(("pread=0x%08lx, pwrite=0x%08lx\n",
-              (unsigned long) buf->pread, (unsigned long) buf->pwrite));
+       dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
+              (unsigned long) buf->pread, (unsigned long) buf->pwrite);
        wake_up(&buf->queue);
        return blen;
 }
@@ -290,7 +285,10 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
 {
        int err, vol, val, balance = 0;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
+
+       av7110->mixer.volume_left = volleft;
+       av7110->mixer.volume_right = volright;
 
        switch (av7110->adac_type) {
        case DVB_ADAC_TI:
@@ -311,7 +309,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
                i2c_writereg(av7110, 0x20, 0x04, volright);
                return 0;
 
-       case DVB_ADAC_MSP:
+       case DVB_ADAC_MSP34x0:
                vol  = (volleft > volright) ? volleft : volright;
                val     = (vol * 0x73 / 255) << 8;
                if (vol > 0)
@@ -324,19 +322,22 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
        return 0;
 }
 
-void av7110_set_vidmode(struct av7110 *av7110, int mode)
+int av7110_set_vidmode(struct av7110 *av7110, int mode)
 {
-       DEB_EE(("av7110: %p\n", av7110));
+       int ret;
+       dprintk(2, "av7110:%p, \n", av7110);
 
-       av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
+       ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
 
-       if (!av7110->playing) {
-               ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO],
+       if (!ret && !av7110->playing) {
+               ret = ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO],
                           av7110->pids[DMX_PES_AUDIO],
                           av7110->pids[DMX_PES_TELETEXT],
                           0, av7110->pids[DMX_PES_PCR]);
-               av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+               if (!ret)
+                       ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
        }
+       return ret;
 }
 
 
@@ -347,17 +348,18 @@ static int sw2mode[16] = {
        VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
 };
 
-static void get_video_format(struct av7110 *av7110, u8 *buf, int count)
+static int get_video_format(struct av7110 *av7110, u8 *buf, int count)
 {
        int i;
        int hsize, vsize;
        int sw;
        u8 *p;
+       int ret = 0;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (av7110->sinfo)
-               return;
+               return 0;
        for (i = 7; i < count - 10; i++) {
                p = buf + i;
                if (p[0] || p[1] || p[2] != 0x01 || p[3] != 0xb3)
@@ -366,11 +368,14 @@ static void get_video_format(struct av7110 *av7110, u8 *buf, int count)
                hsize = ((p[1] &0xF0) >> 4) | (p[0] << 4);
                vsize = ((p[1] &0x0F) << 8) | (p[2]);
                sw = (p[3] & 0x0F);
-               av7110_set_vidmode(av7110, sw2mode[sw]);
-               DEB_S(("dvb: playback %dx%d fr=%d\n", hsize, vsize, sw));
-               av7110->sinfo = 1;
+               ret = av7110_set_vidmode(av7110, sw2mode[sw]);
+               if (!ret) {
+                       dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw);
+                       av7110->sinfo = 1;
+               }
                break;
        }
+       return ret;
 }
 
 
@@ -404,7 +409,7 @@ static inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf,
 static void play_video_cb(u8 *buf, int count, void *priv)
 {
        struct av7110 *av7110 = (struct av7110 *) priv;
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if ((buf[3] & 0xe0) == 0xe0) {
                get_video_format(av7110, buf, count);
@@ -416,7 +421,7 @@ static void play_video_cb(u8 *buf, int count, void *priv)
 static void play_audio_cb(u8 *buf, int count, void *priv)
 {
        struct av7110 *av7110 = (struct av7110 *) priv;
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        aux_ring_buffer_write(&av7110->aout, buf, count);
 }
@@ -428,7 +433,7 @@ static ssize_t dvb_play(struct av7110 *av7110, const u8 __user *buf,
                        unsigned long count, int nonblock, int type)
 {
        unsigned long todo = count, n;
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (!av7110->kbuf[type])
                return -ENOBUFS;
@@ -461,7 +466,7 @@ static ssize_t dvb_play_kernel(struct av7110 *av7110, const u8 *buf,
                        unsigned long count, int nonblock, int type)
 {
        unsigned long todo = count, n;
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (!av7110->kbuf[type])
                return -ENOBUFS;
@@ -491,7 +496,7 @@ static ssize_t dvb_aplay(struct av7110 *av7110, const u8 __user *buf,
                         unsigned long count, int nonblock, int type)
 {
        unsigned long todo = count, n;
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (!av7110->kbuf[type])
                return -ENOBUFS;
@@ -681,7 +686,7 @@ void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t
 }
 
 
-int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length)
+static int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length)
 {
        int i;
        int c = 0;
@@ -770,7 +775,7 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l
        struct av7110 *av7110 = (struct av7110 *) demux->priv;
        struct ipack *ipack = &av7110->ipack[feed->pes_type];
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        switch (feed->pes_type) {
        case 0:
@@ -811,8 +816,6 @@ void dvb_video_add_event(struct av7110 *av7110, struct video_event *event)
        struct dvb_video_events *events = &av7110->video_events;
        int wp;
 
-       DEB_D(("\n"));
-
        spin_lock_bh(&events->lock);
 
        wp = (events->eventw + 1) % MAX_VIDEO_EVENT;
@@ -835,8 +838,6 @@ static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event
 {
        struct dvb_video_events *events = &av7110->video_events;
 
-       DEB_D(("\n"));
-
        if (events->overflow) {
                events->overflow = 0;
                return -EOVERFLOW;
@@ -875,7 +876,7 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
        unsigned int mask = 0;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if ((file->f_flags & O_ACCMODE) != O_RDONLY)
                poll_wait(file, &av7110->avout.queue, wait);
@@ -902,7 +903,7 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf,
        struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if ((file->f_flags & O_ACCMODE) == O_RDONLY)
                return -EPERM;
@@ -919,7 +920,7 @@ static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
        unsigned int mask = 0;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        poll_wait(file, &av7110->aout.queue, wait);
 
@@ -938,7 +939,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
        struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) {
                printk(KERN_ERR "not audio source memory\n");
@@ -947,7 +948,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
        return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
 }
 
-u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
+static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
 
 #define MIN_IFRAME 400000
 
@@ -955,7 +956,7 @@ static int play_iframe(struct av7110 *av7110, u8 __user *buf, unsigned int len,
 {
        int i, n;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (!(av7110->playing & RP_VIDEO)) {
                if (av7110_av_start_play(av7110, RP_VIDEO) < 0)
@@ -985,7 +986,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
        unsigned long arg = (unsigned long) parg;
        int ret = 0;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
 
        if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
                if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT &&
@@ -998,49 +999,57 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
        case VIDEO_STOP:
                av7110->videostate.play_state = VIDEO_STOPPED;
                if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
-                       av7110_av_stop(av7110, RP_VIDEO);
+                       ret = av7110_av_stop(av7110, RP_VIDEO);
                else
-                       vidcom(av7110, VIDEO_CMD_STOP,
+                       ret = vidcom(av7110, VIDEO_CMD_STOP,
                               av7110->videostate.video_blank ? 0 : 1);
-               av7110->trickmode = TRICK_NONE;
+               if (!ret)
+                       av7110->trickmode = TRICK_NONE;
                break;
 
        case VIDEO_PLAY:
                av7110->trickmode = TRICK_NONE;
                if (av7110->videostate.play_state == VIDEO_FREEZED) {
                        av7110->videostate.play_state = VIDEO_PLAYING;
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       if (ret)
+                               break;
                }
 
                if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) {
                        if (av7110->playing == RP_AV) {
-                               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+                               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+                               if (ret)
+                                       break;
                                av7110->playing &= ~RP_VIDEO;
                        }
-                       av7110_av_start_play(av7110, RP_VIDEO);
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
-               } else {
-                       //av7110_av_stop(av7110, RP_VIDEO);
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       ret = av7110_av_start_play(av7110, RP_VIDEO);
                }
-               av7110->videostate.play_state = VIDEO_PLAYING;
+               if (!ret)
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+               if (!ret)
+                       av7110->videostate.play_state = VIDEO_PLAYING;
                break;
 
        case VIDEO_FREEZE:
                av7110->videostate.play_state = VIDEO_FREEZED;
                if (av7110->playing & RP_VIDEO)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0);
                else
-                       vidcom(av7110, VIDEO_CMD_FREEZE, 1);
-               av7110->trickmode = TRICK_FREEZE;
+                       ret = vidcom(av7110, VIDEO_CMD_FREEZE, 1);
+               if (!ret)
+                       av7110->trickmode = TRICK_FREEZE;
                break;
 
        case VIDEO_CONTINUE:
                if (av7110->playing & RP_VIDEO)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0);
-               vidcom(av7110, VIDEO_CMD_PLAY, 0);
-               av7110->videostate.play_state = VIDEO_PLAYING;
-               av7110->trickmode = TRICK_NONE;
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0);
+               if (!ret)
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+               if (!ret) {
+                       av7110->videostate.play_state = VIDEO_PLAYING;
+                       av7110->trickmode = TRICK_NONE;
+               }
                break;
 
        case VIDEO_SELECT_SOURCE:
@@ -1056,7 +1065,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
                break;
 
        case VIDEO_GET_EVENT:
-               ret=dvb_video_get_event(av7110, parg, file->f_flags);
+               ret = dvb_video_get_event(av7110, parg, file->f_flags);
                break;
 
        case VIDEO_GET_SIZE:
@@ -1086,7 +1095,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
                }
                if (ret < 0)
                        break;
-               av7110->videostate.video_format = format;
+               av7110->videostate.display_format = format;
                ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
                                    1, (u16) val);
                break;
@@ -1116,25 +1125,32 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
        case VIDEO_FAST_FORWARD:
                //note: arg is ignored by firmware
                if (av7110->playing & RP_VIDEO)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                     __Scan_I, 2, AV_PES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                           __Scan_I, 2, AV_PES, 0);
                else
-                       vidcom(av7110, VIDEO_CMD_FFWD, arg);
-               av7110->trickmode = TRICK_FAST;
-               av7110->videostate.play_state = VIDEO_PLAYING;
+                       ret = vidcom(av7110, VIDEO_CMD_FFWD, arg);
+               if (!ret) {
+                       av7110->trickmode = TRICK_FAST;
+                       av7110->videostate.play_state = VIDEO_PLAYING;
+               }
                break;
 
        case VIDEO_SLOWMOTION:
                if (av7110->playing&RP_VIDEO) {
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
-                       vidcom(av7110, VIDEO_CMD_SLOW, arg);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
+                       if (!ret)
+                               ret = vidcom(av7110, VIDEO_CMD_SLOW, arg);
                } else {
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
-                       vidcom(av7110, VIDEO_CMD_STOP, 0);
-                       vidcom(av7110, VIDEO_CMD_SLOW, arg);
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       if (!ret)
+                               ret = vidcom(av7110, VIDEO_CMD_STOP, 0);
+                       if (!ret)
+                               ret = vidcom(av7110, VIDEO_CMD_SLOW, arg);
+               }
+               if (!ret) {
+                       av7110->trickmode = TRICK_SLOW;
+                       av7110->videostate.play_state = VIDEO_PLAYING;
                }
-               av7110->trickmode = TRICK_SLOW;
-               av7110->videostate.play_state = VIDEO_PLAYING;
                break;
 
        case VIDEO_GET_CAPABILITIES:
@@ -1147,18 +1163,21 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
                av7110_ipack_reset(&av7110->ipack[1]);
 
                if (av7110->playing == RP_AV) {
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                     __Play, 2, AV_PES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                           __Play, 2, AV_PES, 0);
+                       if (ret)
+                               break;
                        if (av7110->trickmode == TRICK_FAST)
-                               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                             __Scan_I, 2, AV_PES, 0);
+                               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                                   __Scan_I, 2, AV_PES, 0);
                        if (av7110->trickmode == TRICK_SLOW) {
-                               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                             __Slow, 2, 0, 0);
-                               vidcom(av7110, VIDEO_CMD_SLOW, arg);
+                               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                                   __Slow, 2, 0, 0);
+                               if (!ret)
+                                       ret = vidcom(av7110, VIDEO_CMD_SLOW, arg);
                        }
                        if (av7110->trickmode == TRICK_FREEZE)
-                               vidcom(av7110, VIDEO_CMD_STOP, 1);
+                               ret = vidcom(av7110, VIDEO_CMD_STOP, 1);
                }
                break;
 
@@ -1181,7 +1200,7 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
        unsigned long arg = (unsigned long) parg;
        int ret = 0;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
 
        if (((file->f_flags & O_ACCMODE) == O_RDONLY) &&
            (cmd != AUDIO_GET_STATUS))
@@ -1190,28 +1209,32 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
        case AUDIO_STOP:
                if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
-                       av7110_av_stop(av7110, RP_AUDIO);
+                       ret = av7110_av_stop(av7110, RP_AUDIO);
                else
-                       audcom(av7110, AUDIO_CMD_MUTE);
-               av7110->audiostate.play_state = AUDIO_STOPPED;
+                       ret = audcom(av7110, AUDIO_CMD_MUTE);
+               if (!ret)
+                       av7110->audiostate.play_state = AUDIO_STOPPED;
                break;
 
        case AUDIO_PLAY:
                if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
-                       av7110_av_start_play(av7110, RP_AUDIO);
-               audcom(av7110, AUDIO_CMD_UNMUTE);
-               av7110->audiostate.play_state = AUDIO_PLAYING;
+                       ret = av7110_av_start_play(av7110, RP_AUDIO);
+               if (!ret)
+                       ret = audcom(av7110, AUDIO_CMD_UNMUTE);
+               if (!ret)
+                       av7110->audiostate.play_state = AUDIO_PLAYING;
                break;
 
        case AUDIO_PAUSE:
-               audcom(av7110, AUDIO_CMD_MUTE);
-               av7110->audiostate.play_state = AUDIO_PAUSED;
+               ret = audcom(av7110, AUDIO_CMD_MUTE);
+               if (!ret)
+                       av7110->audiostate.play_state = AUDIO_PAUSED;
                break;
 
        case AUDIO_CONTINUE:
                if (av7110->audiostate.play_state == AUDIO_PAUSED) {
                        av7110->audiostate.play_state = AUDIO_PLAYING;
-                       audcom(av7110, AUDIO_CMD_MUTE | AUDIO_CMD_PCM16);
+                       ret = audcom(av7110, AUDIO_CMD_UNMUTE | AUDIO_CMD_PCM16);
                }
                break;
 
@@ -1221,18 +1244,21 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
 
        case AUDIO_SET_MUTE:
        {
-               audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE);
-               av7110->audiostate.mute_state = (int) arg;
+               ret = audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE);
+               if (!ret)
+                       av7110->audiostate.mute_state = (int) arg;
                break;
        }
 
        case AUDIO_SET_AV_SYNC:
                av7110->audiostate.AV_sync_state = (int) arg;
-               audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF);
+               ret = audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF);
                break;
 
        case AUDIO_SET_BYPASS_MODE:
-               ret = -EINVAL;
+               if (FW_VERSION(av7110->arm_app) < 0x2621)
+                       ret = -EINVAL;
+               av7110->audiostate.bypass_mode = (int)arg;
                break;
 
        case AUDIO_CHANNEL_SELECT:
@@ -1240,15 +1266,24 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
 
                switch(av7110->audiostate.channel_select) {
                case AUDIO_STEREO:
-                       audcom(av7110, AUDIO_CMD_STEREO);
+                       ret = audcom(av7110, AUDIO_CMD_STEREO);
+                       if (!ret)
+                               if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+                                       i2c_writereg(av7110, 0x20, 0x02, 0x49);
                        break;
 
                case AUDIO_MONO_LEFT:
-                       audcom(av7110, AUDIO_CMD_MONO_L);
+                       ret = audcom(av7110, AUDIO_CMD_MONO_L);
+                       if (!ret)
+                               if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+                                       i2c_writereg(av7110, 0x20, 0x02, 0x4a);
                        break;
 
                case AUDIO_MONO_RIGHT:
-                       audcom(av7110, AUDIO_CMD_MONO_R);
+                       ret = audcom(av7110, AUDIO_CMD_MONO_R);
+                       if (!ret)
+                               if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+                                       i2c_writereg(av7110, 0x20, 0x02, 0x45);
                        break;
 
                default:
@@ -1262,15 +1297,19 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
                break;
 
        case AUDIO_GET_CAPABILITIES:
-               *(int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+               if (FW_VERSION(av7110->arm_app) < 0x2621)
+                       *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+               else
+                       *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
+                                               AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
                break;
 
        case AUDIO_CLEAR_BUFFER:
                dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
                av7110_ipack_reset(&av7110->ipack[0]);
                if (av7110->playing == RP_AV)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                              __Play, 2, AV_PES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                           __Play, 2, AV_PES, 0);
                break;
        case AUDIO_SET_ID:
 
@@ -1279,7 +1318,7 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
        {
                struct audio_mixer *amix = (struct audio_mixer *)parg;
 
-               av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
+               ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
                break;
        }
        case AUDIO_SET_STREAMTYPE:
@@ -1297,7 +1336,7 @@ static int dvb_video_open(struct inode *inode, struct file *file)
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
        int err;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if ((err = dvb_generic_open(inode, file)) < 0)
                return err;
@@ -1321,7 +1360,7 @@ static int dvb_video_release(struct inode *inode, struct file *file)
        struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
                av7110_av_stop(av7110, RP_VIDEO);
@@ -1336,7 +1375,7 @@ static int dvb_audio_open(struct inode *inode, struct file *file)
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
        int err=dvb_generic_open(inode, file);
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        if (err < 0)
                return err;
@@ -1350,7 +1389,7 @@ static int dvb_audio_release(struct inode *inode, struct file *file)
        struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
        struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-       DEB_EE(("av7110: %p\n", av7110));
+       dprintk(2, "av7110:%p, \n", av7110);
 
        av7110_av_stop(av7110, RP_AUDIO);
        return dvb_generic_release(inode, file);
@@ -1420,10 +1459,10 @@ int av7110_av_register(struct av7110 *av7110)
        av7110->video_events.overflow = 0;
        memset(&av7110->video_size, 0, sizeof (video_size_t));
 
-       dvb_register_device(av7110->dvb_adapter, &av7110->video_dev,
+       dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
                            &dvbdev_video, av7110, DVB_DEVICE_VIDEO);
 
-       dvb_register_device(av7110->dvb_adapter, &av7110->audio_dev,
+       dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
                            &dvbdev_audio, av7110, DVB_DEVICE_AUDIO);
 
        return 0;
@@ -1437,25 +1476,32 @@ void av7110_av_unregister(struct av7110 *av7110)
 
 int av7110_av_init(struct av7110 *av7110)
 {
-       av7110->vidmode = VIDEO_MODE_PAL;
+       void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
+       int i, ret;
 
-       av7110_ipack_init(&av7110->ipack[0], IPACKS, play_audio_cb);
-       av7110->ipack[0].data = (void *) av7110;
-       av7110_ipack_init(&av7110->ipack[1], IPACKS, play_video_cb);
-       av7110->ipack[1].data = (void *) av7110;
+       for (i = 0; i < 2; i++) {
+               struct ipack *ipack = av7110->ipack + i;
+
+               ret = av7110_ipack_init(ipack, IPACKS, play[i]);
+               if (ret < 0) {
+                       if (i)
+                               av7110_ipack_free(--ipack);
+                       goto out;
+               }
+               ipack->data = av7110;
+       }
 
        dvb_ringbuffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN);
        dvb_ringbuffer_init(&av7110->aout, av7110->iobuf + AVOUTLEN, AOUTLEN);
 
        av7110->kbuf[0] = (u8 *)(av7110->iobuf + AVOUTLEN + AOUTLEN + BMPLEN);
        av7110->kbuf[1] = av7110->kbuf[0] + 2 * IPACKS;
-
-       return 0;
+out:
+       return ret;
 }
 
-int av7110_av_exit(struct av7110 *av7110)
+void av7110_av_exit(struct av7110 *av7110)
 {
        av7110_ipack_free(&av7110->ipack[0]);
        av7110_ipack_free(&av7110->ipack[1]);
-       return 0;
 }