blob: d75e7e48addcc821b0869a4b524bfb3265797c08 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * av7110_av.c: audio and video MPEG decoder stuff
3 *
4 * Copyright (C) 1999-2002 Ralph Metzler
5 * & Marcus Metzler for convergence integrated media GmbH
6 *
7 * originally based on code by:
8 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
26 *
27 *
28 * the project's page is at http://www.linuxtv.org/dvb/
29 */
30
31#include <linux/types.h>
32#include <linux/kernel.h>
33#include <linux/string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/fs.h>
36
37#include "av7110.h"
38#include "av7110_hw.h"
39#include "av7110_av.h"
40#include "av7110_ipack.h"
41
42/* MPEG-2 (ISO 13818 / H.222.0) stream types */
43#define PROG_STREAM_MAP 0xBC
44#define PRIVATE_STREAM1 0xBD
45#define PADDING_STREAM 0xBE
46#define PRIVATE_STREAM2 0xBF
47#define AUDIO_STREAM_S 0xC0
48#define AUDIO_STREAM_E 0xDF
49#define VIDEO_STREAM_S 0xE0
50#define VIDEO_STREAM_E 0xEF
51#define ECM_STREAM 0xF0
52#define EMM_STREAM 0xF1
53#define DSM_CC_STREAM 0xF2
54#define ISO13522_STREAM 0xF3
55#define PROG_STREAM_DIR 0xFF
56
57#define PTS_DTS_FLAGS 0xC0
58
59//pts_dts flags
60#define PTS_ONLY 0x80
61#define PTS_DTS 0xC0
62#define TS_SIZE 188
63#define TRANS_ERROR 0x80
64#define PAY_START 0x40
65#define TRANS_PRIO 0x20
66#define PID_MASK_HI 0x1F
67//flags
68#define TRANS_SCRMBL1 0x80
69#define TRANS_SCRMBL2 0x40
70#define ADAPT_FIELD 0x20
71#define PAYLOAD 0x10
72#define COUNT_MASK 0x0F
73
74// adaptation flags
75#define DISCON_IND 0x80
76#define RAND_ACC_IND 0x40
77#define ES_PRI_IND 0x20
78#define PCR_FLAG 0x10
79#define OPCR_FLAG 0x08
80#define SPLICE_FLAG 0x04
81#define TRANS_PRIV 0x02
82#define ADAP_EXT_FLAG 0x01
83
84// adaptation extension flags
85#define LTW_FLAG 0x80
86#define PIECE_RATE 0x40
87#define SEAM_SPLICE 0x20
88
89
90static void p_to_t(u8 const *buf, long int length, u16 pid,
91 u8 *counter, struct dvb_demux_feed *feed);
92
93
94int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
95{
96 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv;
97
98 if (!(dvbdmxfeed->ts_type & TS_PACKET))
99 return 0;
100 if (buf[3] == 0xe0) // video PES do not have a length in TS
101 buf[4] = buf[5] = 0;
102 if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
103 return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
104 &dvbdmxfeed->feed.ts, DMX_OK);
105 else
106 return dvb_filter_pes2ts(p2t, buf, len, 1);
107}
108
109static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
110{
111 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
112
113 dvbdmxfeed->cb.ts(data, 188, NULL, 0,
114 &dvbdmxfeed->feed.ts, DMX_OK);
115 return 0;
116}
117
118int av7110_av_start_record(struct av7110 *av7110, int av,
119 struct dvb_demux_feed *dvbdmxfeed)
120{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700121 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
123
124 dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed);
125
126 if (av7110->playing || (av7110->rec_mode & av))
127 return -EBUSY;
128 av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
129 dvbdmx->recording = 1;
130 av7110->rec_mode |= av;
131
132 switch (av7110->rec_mode) {
133 case RP_AUDIO:
134 dvb_filter_pes2ts_init(&av7110->p2t[0],
135 dvbdmx->pesfilter[0]->pid,
136 dvb_filter_pes2ts_cb,
137 (void *) dvbdmx->pesfilter[0]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700138 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 break;
140
141 case RP_VIDEO:
142 dvb_filter_pes2ts_init(&av7110->p2t[1],
143 dvbdmx->pesfilter[1]->pid,
144 dvb_filter_pes2ts_cb,
145 (void *) dvbdmx->pesfilter[1]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700146 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 break;
148
149 case RP_AV:
150 dvb_filter_pes2ts_init(&av7110->p2t[0],
151 dvbdmx->pesfilter[0]->pid,
152 dvb_filter_pes2ts_cb,
153 (void *) dvbdmx->pesfilter[0]);
154 dvb_filter_pes2ts_init(&av7110->p2t[1],
155 dvbdmx->pesfilter[1]->pid,
156 dvb_filter_pes2ts_cb,
157 (void *) dvbdmx->pesfilter[1]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700158 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 break;
160 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700161 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162}
163
164int av7110_av_start_play(struct av7110 *av7110, int av)
165{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700166 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 dprintk(2, "av7110:%p, \n", av7110);
168
169 if (av7110->rec_mode)
170 return -EBUSY;
171 if (av7110->playing & av)
172 return -EBUSY;
173
174 av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
175
176 if (av7110->playing == RP_NONE) {
177 av7110_ipack_reset(&av7110->ipack[0]);
178 av7110_ipack_reset(&av7110->ipack[1]);
179 }
180
181 av7110->playing |= av;
182 switch (av7110->playing) {
183 case RP_AUDIO:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700184 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 break;
186 case RP_VIDEO:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700187 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 av7110->sinfo = 0;
189 break;
190 case RP_AV:
191 av7110->sinfo = 0;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700192 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 break;
194 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700195 if (!ret)
196 ret = av7110->playing;
197 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198}
199
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700200int av7110_av_stop(struct av7110 *av7110, int av)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700202 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 dprintk(2, "av7110:%p, \n", av7110);
204
205 if (!(av7110->playing & av) && !(av7110->rec_mode & av))
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700206 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
208 if (av7110->playing) {
209 av7110->playing &= ~av;
210 switch (av7110->playing) {
211 case RP_AUDIO:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700212 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 break;
214 case RP_VIDEO:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700215 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 break;
217 case RP_NONE:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700218 ret = av7110_set_vidmode(av7110, av7110->vidmode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 break;
220 }
221 } else {
222 av7110->rec_mode &= ~av;
223 switch (av7110->rec_mode) {
224 case RP_AUDIO:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700225 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 break;
227 case RP_VIDEO:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700228 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 break;
230 case RP_NONE:
231 break;
232 }
233 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700234 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235}
236
237
238int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
239{
240 int len;
241 u32 sync;
242 u16 blen;
243
244 if (!dlen) {
245 wake_up(&buf->queue);
246 return -1;
247 }
248 while (1) {
249 if ((len = dvb_ringbuffer_avail(buf)) < 6)
250 return -1;
251 sync = DVB_RINGBUFFER_PEEK(buf, 0) << 24;
252 sync |= DVB_RINGBUFFER_PEEK(buf, 1) << 16;
253 sync |= DVB_RINGBUFFER_PEEK(buf, 2) << 8;
254 sync |= DVB_RINGBUFFER_PEEK(buf, 3);
255
256 if (((sync &~ 0x0f) == 0x000001e0) ||
257 ((sync &~ 0x1f) == 0x000001c0) ||
258 (sync == 0x000001bd))
259 break;
260 printk("resync\n");
261 DVB_RINGBUFFER_SKIP(buf, 1);
262 }
263 blen = DVB_RINGBUFFER_PEEK(buf, 4) << 8;
264 blen |= DVB_RINGBUFFER_PEEK(buf, 5);
265 blen += 6;
266 if (len < blen || blen > dlen) {
267 //printk("buffer empty - avail %d blen %u dlen %d\n", len, blen, dlen);
268 wake_up(&buf->queue);
269 return -1;
270 }
271
272 dvb_ringbuffer_read(buf, dest, (size_t) blen, 0);
273
274 dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
275 (unsigned long) buf->pread, (unsigned long) buf->pwrite);
276 wake_up(&buf->queue);
277 return blen;
278}
279
280
281int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
282{
283 int err, vol, val, balance = 0;
284
285 dprintk(2, "av7110:%p, \n", av7110);
286
287 av7110->mixer.volume_left = volleft;
288 av7110->mixer.volume_right = volright;
289
290 switch (av7110->adac_type) {
291 case DVB_ADAC_TI:
292 volleft = (volleft * 256) / 1036;
293 volright = (volright * 256) / 1036;
294 if (volleft > 0x3f)
295 volleft = 0x3f;
296 if (volright > 0x3f)
297 volright = 0x3f;
298 if ((err = SendDAC(av7110, 3, 0x80 + volleft)))
299 return err;
300 return SendDAC(av7110, 4, volright);
301
302 case DVB_ADAC_CRYSTAL:
303 volleft = 127 - volleft / 2;
304 volright = 127 - volright / 2;
305 i2c_writereg(av7110, 0x20, 0x03, volleft);
306 i2c_writereg(av7110, 0x20, 0x04, volright);
307 return 0;
308
Marco Schluessler1c13b952006-01-09 15:25:06 -0200309 case DVB_ADAC_MSP34x0:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 vol = (volleft > volright) ? volleft : volright;
311 val = (vol * 0x73 / 255) << 8;
312 if (vol > 0)
313 balance = ((volright - volleft) * 127) / vol;
314 msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
315 msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
316 msp_writereg(av7110, MSP_WR_DSP, 0x0006, val); /* headphonesr */
317 return 0;
Tim Kaiser61391e02006-06-25 09:14:07 -0300318
319 case DVB_ADAC_MSP34x5:
320 vol = (volleft > volright) ? volleft : volright;
321 val = (vol * 0x73 / 255) << 8;
322 if (vol > 0)
323 balance = ((volright - volleft) * 127) / vol;
324 msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
325 msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
326 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 }
Tim Kaiser61391e02006-06-25 09:14:07 -0300328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 return 0;
330}
331
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700332int av7110_set_vidmode(struct av7110 *av7110, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333{
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700334 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 dprintk(2, "av7110:%p, \n", av7110);
336
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700337 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700339 if (!ret && !av7110->playing) {
340 ret = ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 av7110->pids[DMX_PES_AUDIO],
342 av7110->pids[DMX_PES_TELETEXT],
343 0, av7110->pids[DMX_PES_PCR]);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700344 if (!ret)
345 ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700347 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348}
349
350
351static int sw2mode[16] = {
352 VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_NTSC, VIDEO_MODE_PAL,
353 VIDEO_MODE_NTSC, VIDEO_MODE_NTSC, VIDEO_MODE_PAL, VIDEO_MODE_NTSC,
354 VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
355 VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
356};
357
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700358static int get_video_format(struct av7110 *av7110, u8 *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359{
360 int i;
361 int hsize, vsize;
362 int sw;
363 u8 *p;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700364 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 dprintk(2, "av7110:%p, \n", av7110);
367
368 if (av7110->sinfo)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700369 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 for (i = 7; i < count - 10; i++) {
371 p = buf + i;
372 if (p[0] || p[1] || p[2] != 0x01 || p[3] != 0xb3)
373 continue;
374 p += 4;
375 hsize = ((p[1] &0xF0) >> 4) | (p[0] << 4);
376 vsize = ((p[1] &0x0F) << 8) | (p[2]);
377 sw = (p[3] & 0x0F);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700378 ret = av7110_set_vidmode(av7110, sw2mode[sw]);
379 if (!ret) {
380 dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw);
381 av7110->sinfo = 1;
382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 break;
384 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700385 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386}
387
388
389/****************************************************************************
390 * I/O buffer management and control
391 ****************************************************************************/
392
393static inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf,
Oliver Endriss804b4452007-07-12 20:37:50 -0300394 const u8 *buf, unsigned long count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395{
396 unsigned long todo = count;
397 int free;
398
399 while (todo > 0) {
400 if (dvb_ringbuffer_free(rbuf) < 2048) {
401 if (wait_event_interruptible(rbuf->queue,
402 (dvb_ringbuffer_free(rbuf) >= 2048)))
403 return count - todo;
404 }
405 free = dvb_ringbuffer_free(rbuf);
406 if (free > todo)
407 free = todo;
408 dvb_ringbuffer_write(rbuf, buf, free);
409 todo -= free;
410 buf += free;
411 }
412
413 return count - todo;
414}
415
416static void play_video_cb(u8 *buf, int count, void *priv)
417{
418 struct av7110 *av7110 = (struct av7110 *) priv;
419 dprintk(2, "av7110:%p, \n", av7110);
420
421 if ((buf[3] & 0xe0) == 0xe0) {
422 get_video_format(av7110, buf, count);
423 aux_ring_buffer_write(&av7110->avout, buf, count);
424 } else
425 aux_ring_buffer_write(&av7110->aout, buf, count);
426}
427
428static void play_audio_cb(u8 *buf, int count, void *priv)
429{
430 struct av7110 *av7110 = (struct av7110 *) priv;
431 dprintk(2, "av7110:%p, \n", av7110);
432
433 aux_ring_buffer_write(&av7110->aout, buf, count);
434}
435
436#define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \
437 dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
438
Oliver Endriss804b4452007-07-12 20:37:50 -0300439static ssize_t dvb_play(struct av7110 *av7110, const char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 unsigned long count, int nonblock, int type)
441{
442 unsigned long todo = count, n;
443 dprintk(2, "av7110:%p, \n", av7110);
444
445 if (!av7110->kbuf[type])
446 return -ENOBUFS;
447
448 if (nonblock && !FREE_COND)
449 return -EWOULDBLOCK;
450
451 while (todo > 0) {
452 if (!FREE_COND) {
453 if (nonblock)
454 return count - todo;
455 if (wait_event_interruptible(av7110->avout.queue,
456 FREE_COND))
457 return count - todo;
458 }
459 n = todo;
460 if (n > IPACKS * 2)
461 n = IPACKS * 2;
462 if (copy_from_user(av7110->kbuf[type], buf, n))
463 return -EFAULT;
464 av7110_ipack_instant_repack(av7110->kbuf[type], n,
465 &av7110->ipack[type]);
466 todo -= n;
467 buf += n;
468 }
469 return count - todo;
470}
471
472static ssize_t dvb_play_kernel(struct av7110 *av7110, const u8 *buf,
473 unsigned long count, int nonblock, int type)
474{
475 unsigned long todo = count, n;
476 dprintk(2, "av7110:%p, \n", av7110);
477
478 if (!av7110->kbuf[type])
479 return -ENOBUFS;
480
481 if (nonblock && !FREE_COND)
482 return -EWOULDBLOCK;
483
484 while (todo > 0) {
485 if (!FREE_COND) {
486 if (nonblock)
487 return count - todo;
488 if (wait_event_interruptible(av7110->avout.queue,
489 FREE_COND))
490 return count - todo;
491 }
492 n = todo;
493 if (n > IPACKS * 2)
494 n = IPACKS * 2;
495 av7110_ipack_instant_repack(buf, n, &av7110->ipack[type]);
496 todo -= n;
497 buf += n;
498 }
499 return count - todo;
500}
501
Oliver Endriss804b4452007-07-12 20:37:50 -0300502static ssize_t dvb_aplay(struct av7110 *av7110, const char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 unsigned long count, int nonblock, int type)
504{
505 unsigned long todo = count, n;
506 dprintk(2, "av7110:%p, \n", av7110);
507
508 if (!av7110->kbuf[type])
509 return -ENOBUFS;
510 if (nonblock && dvb_ringbuffer_free(&av7110->aout) < 20 * 1024)
511 return -EWOULDBLOCK;
512
513 while (todo > 0) {
514 if (dvb_ringbuffer_free(&av7110->aout) < 20 * 1024) {
515 if (nonblock)
516 return count - todo;
517 if (wait_event_interruptible(av7110->aout.queue,
518 (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)))
519 return count-todo;
520 }
521 n = todo;
522 if (n > IPACKS * 2)
523 n = IPACKS * 2;
524 if (copy_from_user(av7110->kbuf[type], buf, n))
525 return -EFAULT;
526 av7110_ipack_instant_repack(av7110->kbuf[type], n,
527 &av7110->ipack[type]);
528 todo -= n;
529 buf += n;
530 }
531 return count - todo;
532}
533
534void av7110_p2t_init(struct av7110_p2t *p, struct dvb_demux_feed *feed)
535{
536 memset(p->pes, 0, TS_SIZE);
537 p->counter = 0;
538 p->pos = 0;
539 p->frags = 0;
540 if (feed)
541 p->feed = feed;
542}
543
544static void clear_p2t(struct av7110_p2t *p)
545{
546 memset(p->pes, 0, TS_SIZE);
547// p->counter = 0;
548 p->pos = 0;
549 p->frags = 0;
550}
551
552
553static int find_pes_header(u8 const *buf, long int length, int *frags)
554{
555 int c = 0;
556 int found = 0;
557
558 *frags = 0;
559
560 while (c < length - 3 && !found) {
561 if (buf[c] == 0x00 && buf[c + 1] == 0x00 &&
562 buf[c + 2] == 0x01) {
563 switch ( buf[c + 3] ) {
564 case PROG_STREAM_MAP:
565 case PRIVATE_STREAM2:
566 case PROG_STREAM_DIR:
567 case ECM_STREAM :
568 case EMM_STREAM :
569 case PADDING_STREAM :
570 case DSM_CC_STREAM :
571 case ISO13522_STREAM:
572 case PRIVATE_STREAM1:
573 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
574 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
575 found = 1;
576 break;
577
578 default:
579 c++;
580 break;
581 }
582 } else
583 c++;
584 }
585 if (c == length - 3 && !found) {
586 if (buf[length - 1] == 0x00)
587 *frags = 1;
588 if (buf[length - 2] == 0x00 &&
589 buf[length - 1] == 0x00)
590 *frags = 2;
591 if (buf[length - 3] == 0x00 &&
592 buf[length - 2] == 0x00 &&
593 buf[length - 1] == 0x01)
594 *frags = 3;
595 return -1;
596 }
597
598 return c;
599}
600
601void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p)
602{
603 int c, c2, l, add;
604 int check, rest;
605
606 c = 0;
607 c2 = 0;
608 if (p->frags){
609 check = 0;
610 switch(p->frags) {
611 case 1:
612 if (buf[c] == 0x00 && buf[c + 1] == 0x01) {
613 check = 1;
614 c += 2;
615 }
616 break;
617 case 2:
618 if (buf[c] == 0x01) {
619 check = 1;
620 c++;
621 }
622 break;
623 case 3:
624 check = 1;
625 }
626 if (check) {
627 switch (buf[c]) {
628 case PROG_STREAM_MAP:
629 case PRIVATE_STREAM2:
630 case PROG_STREAM_DIR:
631 case ECM_STREAM :
632 case EMM_STREAM :
633 case PADDING_STREAM :
634 case DSM_CC_STREAM :
635 case ISO13522_STREAM:
636 case PRIVATE_STREAM1:
637 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
638 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
639 p->pes[0] = 0x00;
640 p->pes[1] = 0x00;
641 p->pes[2] = 0x01;
642 p->pes[3] = buf[c];
643 p->pos = 4;
644 memcpy(p->pes + p->pos, buf + c, (TS_SIZE - 4) - p->pos);
645 c += (TS_SIZE - 4) - p->pos;
646 p_to_t(p->pes, (TS_SIZE - 4), pid, &p->counter, p->feed);
647 clear_p2t(p);
648 break;
649
650 default:
651 c = 0;
652 break;
653 }
654 }
655 p->frags = 0;
656 }
657
658 if (p->pos) {
659 c2 = find_pes_header(buf + c, length - c, &p->frags);
660 if (c2 >= 0 && c2 < (TS_SIZE - 4) - p->pos)
661 l = c2+c;
662 else
663 l = (TS_SIZE - 4) - p->pos;
664 memcpy(p->pes + p->pos, buf, l);
665 c += l;
666 p->pos += l;
667 p_to_t(p->pes, p->pos, pid, &p->counter, p->feed);
668 clear_p2t(p);
669 }
670
671 add = 0;
672 while (c < length) {
673 c2 = find_pes_header(buf + c + add, length - c - add, &p->frags);
674 if (c2 >= 0) {
675 c2 += c + add;
676 if (c2 > c){
677 p_to_t(buf + c, c2 - c, pid, &p->counter, p->feed);
678 c = c2;
679 clear_p2t(p);
680 add = 0;
681 } else
682 add = 1;
683 } else {
684 l = length - c;
685 rest = l % (TS_SIZE - 4);
686 l -= rest;
687 p_to_t(buf + c, l, pid, &p->counter, p->feed);
688 memcpy(p->pes, buf + c + l, rest);
689 p->pos = rest;
690 c = length;
691 }
692 }
693}
694
695
696static int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length)
697{
698 int i;
699 int c = 0;
700 int fill;
701 u8 tshead[4] = { 0x47, 0x00, 0x00, 0x10 };
702
703 fill = (TS_SIZE - 4) - length;
704 if (pes_start)
705 tshead[1] = 0x40;
706 if (fill)
707 tshead[3] = 0x30;
708 tshead[1] |= (u8)((pid & 0x1F00) >> 8);
709 tshead[2] |= (u8)(pid & 0x00FF);
710 tshead[3] |= ((*counter)++ & 0x0F);
711 memcpy(buf, tshead, 4);
712 c += 4;
713
714 if (fill) {
715 buf[4] = fill - 1;
716 c++;
717 if (fill > 1) {
718 buf[5] = 0x00;
719 c++;
720 }
721 for (i = 6; i < fill + 4; i++) {
722 buf[i] = 0xFF;
723 c++;
724 }
725 }
726
727 return c;
728}
729
730
731static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
732 struct dvb_demux_feed *feed)
733{
734 int l, pes_start;
735 u8 obuf[TS_SIZE];
736 long c = 0;
737
738 pes_start = 0;
739 if (length > 3 &&
740 buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01)
741 switch (buf[3]) {
742 case PROG_STREAM_MAP:
743 case PRIVATE_STREAM2:
744 case PROG_STREAM_DIR:
745 case ECM_STREAM :
746 case EMM_STREAM :
747 case PADDING_STREAM :
748 case DSM_CC_STREAM :
749 case ISO13522_STREAM:
750 case PRIVATE_STREAM1:
751 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
752 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
753 pes_start = 1;
754 break;
755
756 default:
757 break;
758 }
759
760 while (c < length) {
761 memset(obuf, 0, TS_SIZE);
762 if (length - c >= (TS_SIZE - 4)){
763 l = write_ts_header2(pid, counter, pes_start,
764 obuf, (TS_SIZE - 4));
765 memcpy(obuf + l, buf + c, TS_SIZE - l);
766 c += TS_SIZE - l;
767 } else {
768 l = write_ts_header2(pid, counter, pes_start,
769 obuf, length - c);
770 memcpy(obuf + l, buf + c, TS_SIZE - l);
771 c = length;
772 }
773 feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
774 pes_start = 0;
775 }
776}
777
778
779int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len)
780{
781 struct dvb_demux *demux = feed->demux;
782 struct av7110 *av7110 = (struct av7110 *) demux->priv;
783 struct ipack *ipack = &av7110->ipack[feed->pes_type];
784
785 dprintk(2, "av7110:%p, \n", av7110);
786
787 switch (feed->pes_type) {
788 case 0:
789 if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
790 return -EINVAL;
791 break;
792 case 1:
793 if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
794 return -EINVAL;
795 break;
796 default:
797 return -1;
798 }
799
800 if (!(buf[3] & 0x10)) /* no payload? */
801 return -1;
802 if (buf[1] & 0x40)
803 av7110_ipack_flush(ipack);
804
805 if (buf[3] & 0x20) { /* adaptation field? */
806 len -= buf[4] + 1;
807 buf += buf[4] + 1;
808 if (!len)
809 return 0;
810 }
811
812 av7110_ipack_instant_repack(buf + 4, len - 4, &av7110->ipack[feed->pes_type]);
813 return 0;
814}
815
816
817
818/******************************************************************************
819 * Video MPEG decoder events
820 ******************************************************************************/
821void dvb_video_add_event(struct av7110 *av7110, struct video_event *event)
822{
823 struct dvb_video_events *events = &av7110->video_events;
824 int wp;
825
826 spin_lock_bh(&events->lock);
827
828 wp = (events->eventw + 1) % MAX_VIDEO_EVENT;
829 if (wp == events->eventr) {
830 events->overflow = 1;
831 events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;
832 }
833
834 //FIXME: timestamp?
835 memcpy(&events->events[events->eventw], event, sizeof(struct video_event));
836 events->eventw = wp;
837
838 spin_unlock_bh(&events->lock);
839
840 wake_up_interruptible(&events->wait_queue);
841}
842
843
844static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event, int flags)
845{
846 struct dvb_video_events *events = &av7110->video_events;
847
848 if (events->overflow) {
849 events->overflow = 0;
850 return -EOVERFLOW;
851 }
852 if (events->eventw == events->eventr) {
853 int ret;
854
855 if (flags & O_NONBLOCK)
856 return -EWOULDBLOCK;
857
858 ret = wait_event_interruptible(events->wait_queue,
859 events->eventw != events->eventr);
860 if (ret < 0)
861 return ret;
862 }
863
864 spin_lock_bh(&events->lock);
865
866 memcpy(event, &events->events[events->eventr],
867 sizeof(struct video_event));
868 events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;
869
870 spin_unlock_bh(&events->lock);
871
872 return 0;
873}
874
875
876/******************************************************************************
877 * DVB device file operations
878 ******************************************************************************/
879
880static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
881{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300882 struct dvb_device *dvbdev = file->private_data;
883 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 unsigned int mask = 0;
885
886 dprintk(2, "av7110:%p, \n", av7110);
887
888 if ((file->f_flags & O_ACCMODE) != O_RDONLY)
889 poll_wait(file, &av7110->avout.queue, wait);
890
891 poll_wait(file, &av7110->video_events.wait_queue, wait);
892
893 if (av7110->video_events.eventw != av7110->video_events.eventr)
894 mask = POLLPRI;
895
896 if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
897 if (av7110->playing) {
898 if (FREE_COND)
899 mask |= (POLLOUT | POLLWRNORM);
900 } else /* if not playing: may play if asked for */
901 mask |= (POLLOUT | POLLWRNORM);
902 }
903
904 return mask;
905}
906
907static ssize_t dvb_video_write(struct file *file, const char __user *buf,
908 size_t count, loff_t *ppos)
909{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300910 struct dvb_device *dvbdev = file->private_data;
911 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
913 dprintk(2, "av7110:%p, \n", av7110);
914
915 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
916 return -EPERM;
917
918 if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY)
919 return -EPERM;
920
921 return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
922}
923
924static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
925{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300926 struct dvb_device *dvbdev = file->private_data;
927 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 unsigned int mask = 0;
929
930 dprintk(2, "av7110:%p, \n", av7110);
931
932 poll_wait(file, &av7110->aout.queue, wait);
933
934 if (av7110->playing) {
935 if (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
936 mask |= (POLLOUT | POLLWRNORM);
937 } else /* if not playing: may play if asked for */
938 mask = (POLLOUT | POLLWRNORM);
939
940 return mask;
941}
942
943static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
944 size_t count, loff_t *ppos)
945{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300946 struct dvb_device *dvbdev = file->private_data;
947 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 dprintk(2, "av7110:%p, \n", av7110);
950
951 if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) {
952 printk(KERN_ERR "not audio source memory\n");
953 return -EPERM;
954 }
955 return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
956}
957
958static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
959
960#define MIN_IFRAME 400000
961
Oliver Endriss804b4452007-07-12 20:37:50 -0300962static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963{
964 int i, n;
965
966 dprintk(2, "av7110:%p, \n", av7110);
967
968 if (!(av7110->playing & RP_VIDEO)) {
969 if (av7110_av_start_play(av7110, RP_VIDEO) < 0)
970 return -EBUSY;
971 }
972
973 /* setting n always > 1, fixes problems when playing stillframes
974 consisting of I- and P-Frames */
975 n = MIN_IFRAME / len + 1;
976
977 /* FIXME: nonblock? */
978 dvb_play_kernel(av7110, iframe_header, sizeof(iframe_header), 0, 1);
979
980 for (i = 0; i < n; i++)
981 dvb_play(av7110, buf, len, 0, 1);
982
983 av7110_ipack_flush(&av7110->ipack[1]);
984 return 0;
985}
986
987
988static int dvb_video_ioctl(struct inode *inode, struct file *file,
989 unsigned int cmd, void *parg)
990{
Tobias Klauserd9bdf772006-12-26 07:33:48 -0300991 struct dvb_device *dvbdev = file->private_data;
992 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 unsigned long arg = (unsigned long) parg;
994 int ret = 0;
995
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -0700996 dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
999 if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT &&
1000 cmd != VIDEO_GET_SIZE ) {
1001 return -EPERM;
1002 }
1003 }
1004
1005 switch (cmd) {
1006 case VIDEO_STOP:
1007 av7110->videostate.play_state = VIDEO_STOPPED;
1008 if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001009 ret = av7110_av_stop(av7110, RP_VIDEO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 else
Hans Verkuil2435be12007-04-27 12:31:09 -03001011 ret = vidcom(av7110, AV_VIDEO_CMD_STOP,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 av7110->videostate.video_blank ? 0 : 1);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001013 if (!ret)
1014 av7110->trickmode = TRICK_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 break;
1016
1017 case VIDEO_PLAY:
1018 av7110->trickmode = TRICK_NONE;
1019 if (av7110->videostate.play_state == VIDEO_FREEZED) {
1020 av7110->videostate.play_state = VIDEO_PLAYING;
Hans Verkuil2435be12007-04-27 12:31:09 -03001021 ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001022 if (ret)
1023 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 }
1025
1026 if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) {
1027 if (av7110->playing == RP_AV) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001028 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
1029 if (ret)
1030 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 av7110->playing &= ~RP_VIDEO;
1032 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001033 ret = av7110_av_start_play(av7110, RP_VIDEO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001035 if (!ret)
Hans Verkuil2435be12007-04-27 12:31:09 -03001036 ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001037 if (!ret)
1038 av7110->videostate.play_state = VIDEO_PLAYING;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 break;
1040
1041 case VIDEO_FREEZE:
1042 av7110->videostate.play_state = VIDEO_FREEZED;
1043 if (av7110->playing & RP_VIDEO)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001044 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 else
Hans Verkuil2435be12007-04-27 12:31:09 -03001046 ret = vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001047 if (!ret)
1048 av7110->trickmode = TRICK_FREEZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 break;
1050
1051 case VIDEO_CONTINUE:
1052 if (av7110->playing & RP_VIDEO)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001053 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0);
1054 if (!ret)
Hans Verkuil2435be12007-04-27 12:31:09 -03001055 ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001056 if (!ret) {
1057 av7110->videostate.play_state = VIDEO_PLAYING;
1058 av7110->trickmode = TRICK_NONE;
1059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 break;
1061
1062 case VIDEO_SELECT_SOURCE:
1063 av7110->videostate.stream_source = (video_stream_source_t) arg;
1064 break;
1065
1066 case VIDEO_SET_BLANK:
1067 av7110->videostate.video_blank = (int) arg;
1068 break;
1069
1070 case VIDEO_GET_STATUS:
1071 memcpy(parg, &av7110->videostate, sizeof(struct video_status));
1072 break;
1073
1074 case VIDEO_GET_EVENT:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001075 ret = dvb_video_get_event(av7110, parg, file->f_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 break;
1077
1078 case VIDEO_GET_SIZE:
1079 memcpy(parg, &av7110->video_size, sizeof(video_size_t));
1080 break;
1081
1082 case VIDEO_SET_DISPLAY_FORMAT:
1083 {
1084 video_displayformat_t format = (video_displayformat_t) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
1086 switch (format) {
1087 case VIDEO_PAN_SCAN:
Oliver Endrissdefd574e2007-07-12 23:08:07 -03001088 av7110->display_panscan = VID_PAN_SCAN_PREF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 break;
1090
1091 case VIDEO_LETTER_BOX:
Oliver Endrissdefd574e2007-07-12 23:08:07 -03001092 av7110->display_panscan = VID_VC_AND_PS_PREF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 break;
1094
1095 case VIDEO_CENTER_CUT_OUT:
Oliver Endrissdefd574e2007-07-12 23:08:07 -03001096 av7110->display_panscan = VID_CENTRE_CUT_PREF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 break;
1098
1099 default:
1100 ret = -EINVAL;
1101 }
1102 if (ret < 0)
1103 break;
Johannes Stezenbacha65d3bb2005-05-16 21:54:26 -07001104 av7110->videostate.display_format = format;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
Oliver Endrissdefd574e2007-07-12 23:08:07 -03001106 1, av7110->display_panscan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 break;
1108 }
1109
1110 case VIDEO_SET_FORMAT:
1111 if (arg > 1) {
1112 ret = -EINVAL;
1113 break;
1114 }
1115 av7110->display_ar = arg;
1116 ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
1117 1, (u16) arg);
1118 break;
1119
1120 case VIDEO_STILLPICTURE:
1121 {
1122 struct video_still_picture *pic =
1123 (struct video_still_picture *) parg;
1124 av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY;
1125 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
1126 ret = play_iframe(av7110, pic->iFrame, pic->size,
1127 file->f_flags & O_NONBLOCK);
1128 break;
1129 }
1130
1131 case VIDEO_FAST_FORWARD:
1132 //note: arg is ignored by firmware
1133 if (av7110->playing & RP_VIDEO)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001134 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -07001135 __Scan_I, 2, AV_PES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 else
Hans Verkuil2435be12007-04-27 12:31:09 -03001137 ret = vidcom(av7110, AV_VIDEO_CMD_FFWD, arg);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001138 if (!ret) {
1139 av7110->trickmode = TRICK_FAST;
1140 av7110->videostate.play_state = VIDEO_PLAYING;
1141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 break;
1143
1144 case VIDEO_SLOWMOTION:
1145 if (av7110->playing&RP_VIDEO) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001146 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
1147 if (!ret)
Hans Verkuil2435be12007-04-27 12:31:09 -03001148 ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 } else {
Hans Verkuil2435be12007-04-27 12:31:09 -03001150 ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001151 if (!ret)
Hans Verkuil2435be12007-04-27 12:31:09 -03001152 ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 0);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001153 if (!ret)
Hans Verkuil2435be12007-04-27 12:31:09 -03001154 ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 }
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001156 if (!ret) {
1157 av7110->trickmode = TRICK_SLOW;
1158 av7110->videostate.play_state = VIDEO_PLAYING;
1159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 break;
1161
1162 case VIDEO_GET_CAPABILITIES:
1163 *(int *)parg = VIDEO_CAP_MPEG1 | VIDEO_CAP_MPEG2 |
1164 VIDEO_CAP_SYS | VIDEO_CAP_PROG;
1165 break;
1166
1167 case VIDEO_CLEAR_BUFFER:
1168 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
1169 av7110_ipack_reset(&av7110->ipack[1]);
1170
1171 if (av7110->playing == RP_AV) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001172 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -07001173 __Play, 2, AV_PES, 0);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001174 if (ret)
1175 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 if (av7110->trickmode == TRICK_FAST)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001177 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -07001178 __Scan_I, 2, AV_PES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 if (av7110->trickmode == TRICK_SLOW) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001180 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -07001181 __Slow, 2, 0, 0);
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001182 if (!ret)
Hans Verkuil2435be12007-04-27 12:31:09 -03001183 ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 }
1185 if (av7110->trickmode == TRICK_FREEZE)
Hans Verkuil2435be12007-04-27 12:31:09 -03001186 ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 }
1188 break;
1189
1190 case VIDEO_SET_STREAMTYPE:
1191
1192 break;
1193
1194 default:
1195 ret = -ENOIOCTLCMD;
1196 break;
1197 }
1198 return ret;
1199}
1200
1201static int dvb_audio_ioctl(struct inode *inode, struct file *file,
1202 unsigned int cmd, void *parg)
1203{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001204 struct dvb_device *dvbdev = file->private_data;
1205 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 unsigned long arg = (unsigned long) parg;
1207 int ret = 0;
1208
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001209 dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 if (((file->f_flags & O_ACCMODE) == O_RDONLY) &&
1212 (cmd != AUDIO_GET_STATUS))
1213 return -EPERM;
1214
1215 switch (cmd) {
1216 case AUDIO_STOP:
1217 if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001218 ret = av7110_av_stop(av7110, RP_AUDIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 else
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001220 ret = audcom(av7110, AUDIO_CMD_MUTE);
1221 if (!ret)
1222 av7110->audiostate.play_state = AUDIO_STOPPED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 break;
1224
1225 case AUDIO_PLAY:
1226 if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001227 ret = av7110_av_start_play(av7110, RP_AUDIO);
1228 if (!ret)
1229 ret = audcom(av7110, AUDIO_CMD_UNMUTE);
1230 if (!ret)
1231 av7110->audiostate.play_state = AUDIO_PLAYING;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 break;
1233
1234 case AUDIO_PAUSE:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001235 ret = audcom(av7110, AUDIO_CMD_MUTE);
1236 if (!ret)
1237 av7110->audiostate.play_state = AUDIO_PAUSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 break;
1239
1240 case AUDIO_CONTINUE:
1241 if (av7110->audiostate.play_state == AUDIO_PAUSED) {
1242 av7110->audiostate.play_state = AUDIO_PLAYING;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001243 ret = audcom(av7110, AUDIO_CMD_UNMUTE | AUDIO_CMD_PCM16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
1245 break;
1246
1247 case AUDIO_SELECT_SOURCE:
1248 av7110->audiostate.stream_source = (audio_stream_source_t) arg;
1249 break;
1250
1251 case AUDIO_SET_MUTE:
1252 {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001253 ret = audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE);
1254 if (!ret)
1255 av7110->audiostate.mute_state = (int) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 break;
1257 }
1258
1259 case AUDIO_SET_AV_SYNC:
1260 av7110->audiostate.AV_sync_state = (int) arg;
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001261 ret = audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 break;
1263
1264 case AUDIO_SET_BYPASS_MODE:
Dr. Werner Fink47f36922006-01-09 15:25:07 -02001265 if (FW_VERSION(av7110->arm_app) < 0x2621)
1266 ret = -EINVAL;
1267 av7110->audiostate.bypass_mode = (int)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 break;
1269
1270 case AUDIO_CHANNEL_SELECT:
1271 av7110->audiostate.channel_select = (audio_channel_select_t) arg;
1272
1273 switch(av7110->audiostate.channel_select) {
1274 case AUDIO_STEREO:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001275 ret = audcom(av7110, AUDIO_CMD_STEREO);
Tim Kaiser61391e02006-06-25 09:14:07 -03001276 if (!ret) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001277 if (av7110->adac_type == DVB_ADAC_CRYSTAL)
1278 i2c_writereg(av7110, 0x20, 0x02, 0x49);
Tim Kaiser61391e02006-06-25 09:14:07 -03001279 else if (av7110->adac_type == DVB_ADAC_MSP34x5)
1280 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220);
1281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 break;
1283
1284 case AUDIO_MONO_LEFT:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001285 ret = audcom(av7110, AUDIO_CMD_MONO_L);
Tim Kaiser61391e02006-06-25 09:14:07 -03001286 if (!ret) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001287 if (av7110->adac_type == DVB_ADAC_CRYSTAL)
1288 i2c_writereg(av7110, 0x20, 0x02, 0x4a);
Tim Kaiser61391e02006-06-25 09:14:07 -03001289 else if (av7110->adac_type == DVB_ADAC_MSP34x5)
1290 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200);
1291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 break;
1293
1294 case AUDIO_MONO_RIGHT:
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001295 ret = audcom(av7110, AUDIO_CMD_MONO_R);
Tim Kaiser61391e02006-06-25 09:14:07 -03001296 if (!ret) {
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001297 if (av7110->adac_type == DVB_ADAC_CRYSTAL)
1298 i2c_writereg(av7110, 0x20, 0x02, 0x45);
Tim Kaiser61391e02006-06-25 09:14:07 -03001299 else if (av7110->adac_type == DVB_ADAC_MSP34x5)
1300 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210);
1301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 break;
1303
1304 default:
1305 ret = -EINVAL;
1306 break;
1307 }
1308 break;
1309
1310 case AUDIO_GET_STATUS:
1311 memcpy(parg, &av7110->audiostate, sizeof(struct audio_status));
1312 break;
1313
1314 case AUDIO_GET_CAPABILITIES:
Dr. Werner Fink47f36922006-01-09 15:25:07 -02001315 if (FW_VERSION(av7110->arm_app) < 0x2621)
1316 *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
1317 else
1318 *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
1319 AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 break;
1321
1322 case AUDIO_CLEAR_BUFFER:
1323 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
1324 av7110_ipack_reset(&av7110->ipack[0]);
1325 if (av7110->playing == RP_AV)
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001326 ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
Johannes Stezenbach7a2fa902005-07-07 17:58:01 -07001327 __Play, 2, AV_PES, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 break;
1329 case AUDIO_SET_ID:
1330
1331 break;
1332 case AUDIO_SET_MIXER:
1333 {
1334 struct audio_mixer *amix = (struct audio_mixer *)parg;
1335
Wolfgang Rohdewaldce18a222005-07-07 17:57:59 -07001336 ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 break;
1338 }
1339 case AUDIO_SET_STREAMTYPE:
1340 break;
1341 default:
1342 ret = -ENOIOCTLCMD;
1343 }
1344 return ret;
1345}
1346
1347
1348static int dvb_video_open(struct inode *inode, struct file *file)
1349{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001350 struct dvb_device *dvbdev = file->private_data;
1351 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 int err;
1353
1354 dprintk(2, "av7110:%p, \n", av7110);
1355
1356 if ((err = dvb_generic_open(inode, file)) < 0)
1357 return err;
1358
1359 if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
1360 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
1361 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
1362 av7110->video_blank = 1;
1363 av7110->audiostate.AV_sync_state = 1;
1364 av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX;
1365
1366 /* empty event queue */
1367 av7110->video_events.eventr = av7110->video_events.eventw = 0;
1368 }
1369
1370 return 0;
1371}
1372
1373static int dvb_video_release(struct inode *inode, struct file *file)
1374{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001375 struct dvb_device *dvbdev = file->private_data;
1376 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
1378 dprintk(2, "av7110:%p, \n", av7110);
1379
1380 if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
1381 av7110_av_stop(av7110, RP_VIDEO);
1382 }
1383
1384 return dvb_generic_release(inode, file);
1385}
1386
1387static int dvb_audio_open(struct inode *inode, struct file *file)
1388{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001389 struct dvb_device *dvbdev = file->private_data;
1390 struct av7110 *av7110 = dvbdev->priv;
1391 int err = dvb_generic_open(inode, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
1393 dprintk(2, "av7110:%p, \n", av7110);
1394
1395 if (err < 0)
1396 return err;
1397 dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
1398 av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX;
1399 return 0;
1400}
1401
1402static int dvb_audio_release(struct inode *inode, struct file *file)
1403{
Tobias Klauserd9bdf772006-12-26 07:33:48 -03001404 struct dvb_device *dvbdev = file->private_data;
1405 struct av7110 *av7110 = dvbdev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
1407 dprintk(2, "av7110:%p, \n", av7110);
1408
1409 av7110_av_stop(av7110, RP_AUDIO);
1410 return dvb_generic_release(inode, file);
1411}
1412
1413
1414
1415/******************************************************************************
1416 * driver registration
1417 ******************************************************************************/
1418
1419static struct file_operations dvb_video_fops = {
1420 .owner = THIS_MODULE,
1421 .write = dvb_video_write,
1422 .ioctl = dvb_generic_ioctl,
1423 .open = dvb_video_open,
1424 .release = dvb_video_release,
1425 .poll = dvb_video_poll,
1426};
1427
1428static struct dvb_device dvbdev_video = {
1429 .priv = NULL,
1430 .users = 6,
1431 .readers = 5, /* arbitrary */
1432 .writers = 1,
1433 .fops = &dvb_video_fops,
1434 .kernel_ioctl = dvb_video_ioctl,
1435};
1436
1437static struct file_operations dvb_audio_fops = {
1438 .owner = THIS_MODULE,
1439 .write = dvb_audio_write,
1440 .ioctl = dvb_generic_ioctl,
1441 .open = dvb_audio_open,
1442 .release = dvb_audio_release,
1443 .poll = dvb_audio_poll,
1444};
1445
1446static struct dvb_device dvbdev_audio = {
1447 .priv = NULL,
1448 .users = 1,
1449 .writers = 1,
1450 .fops = &dvb_audio_fops,
1451 .kernel_ioctl = dvb_audio_ioctl,
1452};
1453
1454
1455int av7110_av_register(struct av7110 *av7110)
1456{
1457 av7110->audiostate.AV_sync_state = 0;
1458 av7110->audiostate.mute_state = 0;
1459 av7110->audiostate.play_state = AUDIO_STOPPED;
1460 av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX;
1461 av7110->audiostate.channel_select = AUDIO_STEREO;
1462 av7110->audiostate.bypass_mode = 0;
1463
1464 av7110->videostate.video_blank = 0;
1465 av7110->videostate.play_state = VIDEO_STOPPED;
1466 av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX;
1467 av7110->videostate.video_format = VIDEO_FORMAT_4_3;
Oliver Endrissdefd574e2007-07-12 23:08:07 -03001468 av7110->videostate.display_format = VIDEO_LETTER_BOX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 av7110->display_ar = VIDEO_FORMAT_4_3;
Oliver Endrissdefd574e2007-07-12 23:08:07 -03001470 av7110->display_panscan = VID_VC_AND_PS_PREF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 init_waitqueue_head(&av7110->video_events.wait_queue);
1473 spin_lock_init(&av7110->video_events.lock);
1474 av7110->video_events.eventw = av7110->video_events.eventr = 0;
1475 av7110->video_events.overflow = 0;
1476 memset(&av7110->video_size, 0, sizeof (video_size_t));
1477
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001478 dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 &dvbdev_video, av7110, DVB_DEVICE_VIDEO);
1480
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001481 dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 &dvbdev_audio, av7110, DVB_DEVICE_AUDIO);
1483
1484 return 0;
1485}
1486
1487void av7110_av_unregister(struct av7110 *av7110)
1488{
1489 dvb_unregister_device(av7110->audio_dev);
1490 dvb_unregister_device(av7110->video_dev);
1491}
1492
1493int av7110_av_init(struct av7110 *av7110)
1494{
1495 void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
1496 int i, ret;
1497
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 for (i = 0; i < 2; i++) {
1499 struct ipack *ipack = av7110->ipack + i;
1500
1501 ret = av7110_ipack_init(ipack, IPACKS, play[i]);
1502 if (ret < 0) {
1503 if (i)
1504 av7110_ipack_free(--ipack);
1505 goto out;
1506 }
1507 ipack->data = av7110;
1508 }
1509
1510 dvb_ringbuffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN);
1511 dvb_ringbuffer_init(&av7110->aout, av7110->iobuf + AVOUTLEN, AOUTLEN);
1512
1513 av7110->kbuf[0] = (u8 *)(av7110->iobuf + AVOUTLEN + AOUTLEN + BMPLEN);
1514 av7110->kbuf[1] = av7110->kbuf[0] + 2 * IPACKS;
1515out:
1516 return ret;
1517}
1518
1519void av7110_av_exit(struct av7110 *av7110)
1520{
1521 av7110_ipack_free(&av7110->ipack[0]);
1522 av7110_ipack_free(&av7110->ipack[1]);
1523}