18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * av7110_av.c: audio and video MPEG decoder stuff 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1999-2002 Ralph Metzler 68c2ecf20Sopenharmony_ci * & Marcus Metzler for convergence integrated media GmbH 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * originally based on code by: 98c2ecf20Sopenharmony_ci * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de> 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * the project's page is at https://linuxtv.org 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/types.h> 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/string.h> 178c2ecf20Sopenharmony_ci#include <linux/delay.h> 188c2ecf20Sopenharmony_ci#include <linux/fs.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "av7110.h" 218c2ecf20Sopenharmony_ci#include "av7110_hw.h" 228c2ecf20Sopenharmony_ci#include "av7110_av.h" 238c2ecf20Sopenharmony_ci#include "av7110_ipack.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* MPEG-2 (ISO 13818 / H.222.0) stream types */ 268c2ecf20Sopenharmony_ci#define PROG_STREAM_MAP 0xBC 278c2ecf20Sopenharmony_ci#define PRIVATE_STREAM1 0xBD 288c2ecf20Sopenharmony_ci#define PADDING_STREAM 0xBE 298c2ecf20Sopenharmony_ci#define PRIVATE_STREAM2 0xBF 308c2ecf20Sopenharmony_ci#define AUDIO_STREAM_S 0xC0 318c2ecf20Sopenharmony_ci#define AUDIO_STREAM_E 0xDF 328c2ecf20Sopenharmony_ci#define VIDEO_STREAM_S 0xE0 338c2ecf20Sopenharmony_ci#define VIDEO_STREAM_E 0xEF 348c2ecf20Sopenharmony_ci#define ECM_STREAM 0xF0 358c2ecf20Sopenharmony_ci#define EMM_STREAM 0xF1 368c2ecf20Sopenharmony_ci#define DSM_CC_STREAM 0xF2 378c2ecf20Sopenharmony_ci#define ISO13522_STREAM 0xF3 388c2ecf20Sopenharmony_ci#define PROG_STREAM_DIR 0xFF 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define PTS_DTS_FLAGS 0xC0 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci//pts_dts flags 438c2ecf20Sopenharmony_ci#define PTS_ONLY 0x80 448c2ecf20Sopenharmony_ci#define PTS_DTS 0xC0 458c2ecf20Sopenharmony_ci#define TS_SIZE 188 468c2ecf20Sopenharmony_ci#define TRANS_ERROR 0x80 478c2ecf20Sopenharmony_ci#define PAY_START 0x40 488c2ecf20Sopenharmony_ci#define TRANS_PRIO 0x20 498c2ecf20Sopenharmony_ci#define PID_MASK_HI 0x1F 508c2ecf20Sopenharmony_ci//flags 518c2ecf20Sopenharmony_ci#define TRANS_SCRMBL1 0x80 528c2ecf20Sopenharmony_ci#define TRANS_SCRMBL2 0x40 538c2ecf20Sopenharmony_ci#define ADAPT_FIELD 0x20 548c2ecf20Sopenharmony_ci#define PAYLOAD 0x10 558c2ecf20Sopenharmony_ci#define COUNT_MASK 0x0F 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci// adaptation flags 588c2ecf20Sopenharmony_ci#define DISCON_IND 0x80 598c2ecf20Sopenharmony_ci#define RAND_ACC_IND 0x40 608c2ecf20Sopenharmony_ci#define ES_PRI_IND 0x20 618c2ecf20Sopenharmony_ci#define PCR_FLAG 0x10 628c2ecf20Sopenharmony_ci#define OPCR_FLAG 0x08 638c2ecf20Sopenharmony_ci#define SPLICE_FLAG 0x04 648c2ecf20Sopenharmony_ci#define TRANS_PRIV 0x02 658c2ecf20Sopenharmony_ci#define ADAP_EXT_FLAG 0x01 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci// adaptation extension flags 688c2ecf20Sopenharmony_ci#define LTW_FLAG 0x80 698c2ecf20Sopenharmony_ci#define PIECE_RATE 0x40 708c2ecf20Sopenharmony_ci#define SEAM_SPLICE 0x20 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic void p_to_t(u8 const *buf, long int length, u16 pid, 748c2ecf20Sopenharmony_ci u8 *counter, struct dvb_demux_feed *feed); 758c2ecf20Sopenharmony_cistatic int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciint av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (!(dvbdmxfeed->ts_type & TS_PACKET)) 838c2ecf20Sopenharmony_ci return 0; 848c2ecf20Sopenharmony_ci if (buf[3] == 0xe0) // video PES do not have a length in TS 858c2ecf20Sopenharmony_ci buf[4] = buf[5] = 0; 868c2ecf20Sopenharmony_ci if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) 878c2ecf20Sopenharmony_ci return dvbdmxfeed->cb.ts(buf, len, NULL, 0, 888c2ecf20Sopenharmony_ci &dvbdmxfeed->feed.ts, NULL); 898c2ecf20Sopenharmony_ci else 908c2ecf20Sopenharmony_ci return dvb_filter_pes2ts(p2t, buf, len, 1); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic int dvb_filter_pes2ts_cb(void *priv, unsigned char *data) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci dvbdmxfeed->cb.ts(data, 188, NULL, 0, 988c2ecf20Sopenharmony_ci &dvbdmxfeed->feed.ts, NULL); 998c2ecf20Sopenharmony_ci return 0; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciint av7110_av_start_record(struct av7110 *av7110, int av, 1038c2ecf20Sopenharmony_ci struct dvb_demux_feed *dvbdmxfeed) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci int ret = 0; 1068c2ecf20Sopenharmony_ci struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (av7110->playing || (av7110->rec_mode & av)) 1118c2ecf20Sopenharmony_ci return -EBUSY; 1128c2ecf20Sopenharmony_ci av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0); 1138c2ecf20Sopenharmony_ci dvbdmx->recording = 1; 1148c2ecf20Sopenharmony_ci av7110->rec_mode |= av; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci switch (av7110->rec_mode) { 1178c2ecf20Sopenharmony_ci case RP_AUDIO: 1188c2ecf20Sopenharmony_ci dvb_filter_pes2ts_init(&av7110->p2t[0], 1198c2ecf20Sopenharmony_ci dvbdmx->pesfilter[0]->pid, 1208c2ecf20Sopenharmony_ci dvb_filter_pes2ts_cb, 1218c2ecf20Sopenharmony_ci (void *) dvbdmx->pesfilter[0]); 1228c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0); 1238c2ecf20Sopenharmony_ci break; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci case RP_VIDEO: 1268c2ecf20Sopenharmony_ci dvb_filter_pes2ts_init(&av7110->p2t[1], 1278c2ecf20Sopenharmony_ci dvbdmx->pesfilter[1]->pid, 1288c2ecf20Sopenharmony_ci dvb_filter_pes2ts_cb, 1298c2ecf20Sopenharmony_ci (void *) dvbdmx->pesfilter[1]); 1308c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0); 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci case RP_AV: 1348c2ecf20Sopenharmony_ci dvb_filter_pes2ts_init(&av7110->p2t[0], 1358c2ecf20Sopenharmony_ci dvbdmx->pesfilter[0]->pid, 1368c2ecf20Sopenharmony_ci dvb_filter_pes2ts_cb, 1378c2ecf20Sopenharmony_ci (void *) dvbdmx->pesfilter[0]); 1388c2ecf20Sopenharmony_ci dvb_filter_pes2ts_init(&av7110->p2t[1], 1398c2ecf20Sopenharmony_ci dvbdmx->pesfilter[1]->pid, 1408c2ecf20Sopenharmony_ci dvb_filter_pes2ts_cb, 1418c2ecf20Sopenharmony_ci (void *) dvbdmx->pesfilter[1]); 1428c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0); 1438c2ecf20Sopenharmony_ci break; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci return ret; 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ciint av7110_av_start_play(struct av7110 *av7110, int av) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci int ret = 0; 1518c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (av7110->rec_mode) 1548c2ecf20Sopenharmony_ci return -EBUSY; 1558c2ecf20Sopenharmony_ci if (av7110->playing & av) 1568c2ecf20Sopenharmony_ci return -EBUSY; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (av7110->playing == RP_NONE) { 1618c2ecf20Sopenharmony_ci av7110_ipack_reset(&av7110->ipack[0]); 1628c2ecf20Sopenharmony_ci av7110_ipack_reset(&av7110->ipack[1]); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci av7110->playing |= av; 1668c2ecf20Sopenharmony_ci switch (av7110->playing) { 1678c2ecf20Sopenharmony_ci case RP_AUDIO: 1688c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0); 1698c2ecf20Sopenharmony_ci break; 1708c2ecf20Sopenharmony_ci case RP_VIDEO: 1718c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0); 1728c2ecf20Sopenharmony_ci av7110->sinfo = 0; 1738c2ecf20Sopenharmony_ci break; 1748c2ecf20Sopenharmony_ci case RP_AV: 1758c2ecf20Sopenharmony_ci av7110->sinfo = 0; 1768c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci return ret; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ciint av7110_av_stop(struct av7110 *av7110, int av) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci int ret = 0; 1858c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (!(av7110->playing & av) && !(av7110->rec_mode & av)) 1888c2ecf20Sopenharmony_ci return 0; 1898c2ecf20Sopenharmony_ci av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0); 1908c2ecf20Sopenharmony_ci if (av7110->playing) { 1918c2ecf20Sopenharmony_ci av7110->playing &= ~av; 1928c2ecf20Sopenharmony_ci switch (av7110->playing) { 1938c2ecf20Sopenharmony_ci case RP_AUDIO: 1948c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0); 1958c2ecf20Sopenharmony_ci break; 1968c2ecf20Sopenharmony_ci case RP_VIDEO: 1978c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0); 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci case RP_NONE: 2008c2ecf20Sopenharmony_ci ret = av7110_set_vidmode(av7110, av7110->vidmode); 2018c2ecf20Sopenharmony_ci break; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci } else { 2048c2ecf20Sopenharmony_ci av7110->rec_mode &= ~av; 2058c2ecf20Sopenharmony_ci switch (av7110->rec_mode) { 2068c2ecf20Sopenharmony_ci case RP_AUDIO: 2078c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0); 2088c2ecf20Sopenharmony_ci break; 2098c2ecf20Sopenharmony_ci case RP_VIDEO: 2108c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0); 2118c2ecf20Sopenharmony_ci break; 2128c2ecf20Sopenharmony_ci case RP_NONE: 2138c2ecf20Sopenharmony_ci break; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci return ret; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciint av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci int len; 2238c2ecf20Sopenharmony_ci u32 sync; 2248c2ecf20Sopenharmony_ci u16 blen; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (!dlen) { 2278c2ecf20Sopenharmony_ci wake_up(&buf->queue); 2288c2ecf20Sopenharmony_ci return -1; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci while (1) { 2318c2ecf20Sopenharmony_ci len = dvb_ringbuffer_avail(buf); 2328c2ecf20Sopenharmony_ci if (len < 6) { 2338c2ecf20Sopenharmony_ci wake_up(&buf->queue); 2348c2ecf20Sopenharmony_ci return -1; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci sync = DVB_RINGBUFFER_PEEK(buf, 0) << 24; 2378c2ecf20Sopenharmony_ci sync |= DVB_RINGBUFFER_PEEK(buf, 1) << 16; 2388c2ecf20Sopenharmony_ci sync |= DVB_RINGBUFFER_PEEK(buf, 2) << 8; 2398c2ecf20Sopenharmony_ci sync |= DVB_RINGBUFFER_PEEK(buf, 3); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (((sync &~ 0x0f) == 0x000001e0) || 2428c2ecf20Sopenharmony_ci ((sync &~ 0x1f) == 0x000001c0) || 2438c2ecf20Sopenharmony_ci (sync == 0x000001bd)) 2448c2ecf20Sopenharmony_ci break; 2458c2ecf20Sopenharmony_ci printk("resync\n"); 2468c2ecf20Sopenharmony_ci DVB_RINGBUFFER_SKIP(buf, 1); 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci blen = DVB_RINGBUFFER_PEEK(buf, 4) << 8; 2498c2ecf20Sopenharmony_ci blen |= DVB_RINGBUFFER_PEEK(buf, 5); 2508c2ecf20Sopenharmony_ci blen += 6; 2518c2ecf20Sopenharmony_ci if (len < blen || blen > dlen) { 2528c2ecf20Sopenharmony_ci //printk("buffer empty - avail %d blen %u dlen %d\n", len, blen, dlen); 2538c2ecf20Sopenharmony_ci wake_up(&buf->queue); 2548c2ecf20Sopenharmony_ci return -1; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci dvb_ringbuffer_read(buf, dest, (size_t) blen); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n", 2608c2ecf20Sopenharmony_ci (unsigned long) buf->pread, (unsigned long) buf->pwrite); 2618c2ecf20Sopenharmony_ci wake_up(&buf->queue); 2628c2ecf20Sopenharmony_ci return blen; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ciint av7110_set_volume(struct av7110 *av7110, unsigned int volleft, 2678c2ecf20Sopenharmony_ci unsigned int volright) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci unsigned int vol, val, balance = 0; 2708c2ecf20Sopenharmony_ci int err; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci av7110->mixer.volume_left = volleft; 2758c2ecf20Sopenharmony_ci av7110->mixer.volume_right = volright; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci switch (av7110->adac_type) { 2788c2ecf20Sopenharmony_ci case DVB_ADAC_TI: 2798c2ecf20Sopenharmony_ci volleft = (volleft * 256) / 1036; 2808c2ecf20Sopenharmony_ci volright = (volright * 256) / 1036; 2818c2ecf20Sopenharmony_ci if (volleft > 0x3f) 2828c2ecf20Sopenharmony_ci volleft = 0x3f; 2838c2ecf20Sopenharmony_ci if (volright > 0x3f) 2848c2ecf20Sopenharmony_ci volright = 0x3f; 2858c2ecf20Sopenharmony_ci if ((err = SendDAC(av7110, 3, 0x80 + volleft))) 2868c2ecf20Sopenharmony_ci return err; 2878c2ecf20Sopenharmony_ci return SendDAC(av7110, 4, volright); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci case DVB_ADAC_CRYSTAL: 2908c2ecf20Sopenharmony_ci volleft = 127 - volleft / 2; 2918c2ecf20Sopenharmony_ci volright = 127 - volright / 2; 2928c2ecf20Sopenharmony_ci i2c_writereg(av7110, 0x20, 0x03, volleft); 2938c2ecf20Sopenharmony_ci i2c_writereg(av7110, 0x20, 0x04, volright); 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci case DVB_ADAC_MSP34x0: 2978c2ecf20Sopenharmony_ci vol = (volleft > volright) ? volleft : volright; 2988c2ecf20Sopenharmony_ci val = (vol * 0x73 / 255) << 8; 2998c2ecf20Sopenharmony_ci if (vol > 0) 3008c2ecf20Sopenharmony_ci balance = ((volright - volleft) * 127) / vol; 3018c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8); 3028c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */ 3038c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0006, val); /* headphonesr */ 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci case DVB_ADAC_MSP34x5: 3078c2ecf20Sopenharmony_ci vol = (volleft > volright) ? volleft : volright; 3088c2ecf20Sopenharmony_ci val = (vol * 0x73 / 255) << 8; 3098c2ecf20Sopenharmony_ci if (vol > 0) 3108c2ecf20Sopenharmony_ci balance = ((volright - volleft) * 127) / vol; 3118c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8); 3128c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */ 3138c2ecf20Sopenharmony_ci return 0; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci return 0; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ciint av7110_set_vidmode(struct av7110 *av7110, enum av7110_video_mode mode) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci int ret; 3228c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (!ret && !av7110->playing) { 3278c2ecf20Sopenharmony_ci ret = ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO], 3288c2ecf20Sopenharmony_ci av7110->pids[DMX_PES_AUDIO], 3298c2ecf20Sopenharmony_ci av7110->pids[DMX_PES_TELETEXT], 3308c2ecf20Sopenharmony_ci 0, av7110->pids[DMX_PES_PCR]); 3318c2ecf20Sopenharmony_ci if (!ret) 3328c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci return ret; 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic enum av7110_video_mode sw2mode[16] = { 3398c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC, 3408c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_PAL, 3418c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_NTSC, 3428c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC, 3438c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL, 3448c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL, 3458c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL, 3468c2ecf20Sopenharmony_ci AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL, 3478c2ecf20Sopenharmony_ci}; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic int get_video_format(struct av7110 *av7110, u8 *buf, int count) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci int i; 3528c2ecf20Sopenharmony_ci int hsize, vsize; 3538c2ecf20Sopenharmony_ci int sw; 3548c2ecf20Sopenharmony_ci u8 *p; 3558c2ecf20Sopenharmony_ci int ret = 0; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (av7110->sinfo) 3608c2ecf20Sopenharmony_ci return 0; 3618c2ecf20Sopenharmony_ci for (i = 7; i < count - 10; i++) { 3628c2ecf20Sopenharmony_ci p = buf + i; 3638c2ecf20Sopenharmony_ci if (p[0] || p[1] || p[2] != 0x01 || p[3] != 0xb3) 3648c2ecf20Sopenharmony_ci continue; 3658c2ecf20Sopenharmony_ci p += 4; 3668c2ecf20Sopenharmony_ci hsize = ((p[1] &0xF0) >> 4) | (p[0] << 4); 3678c2ecf20Sopenharmony_ci vsize = ((p[1] &0x0F) << 8) | (p[2]); 3688c2ecf20Sopenharmony_ci sw = (p[3] & 0x0F); 3698c2ecf20Sopenharmony_ci ret = av7110_set_vidmode(av7110, sw2mode[sw]); 3708c2ecf20Sopenharmony_ci if (!ret) { 3718c2ecf20Sopenharmony_ci dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw); 3728c2ecf20Sopenharmony_ci av7110->sinfo = 1; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci break; 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci return ret; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/**************************************************************************** 3818c2ecf20Sopenharmony_ci * I/O buffer management and control 3828c2ecf20Sopenharmony_ci ****************************************************************************/ 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf, 3858c2ecf20Sopenharmony_ci const u8 *buf, unsigned long count) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci unsigned long todo = count; 3888c2ecf20Sopenharmony_ci int free; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci while (todo > 0) { 3918c2ecf20Sopenharmony_ci if (dvb_ringbuffer_free(rbuf) < 2048) { 3928c2ecf20Sopenharmony_ci if (wait_event_interruptible(rbuf->queue, 3938c2ecf20Sopenharmony_ci (dvb_ringbuffer_free(rbuf) >= 2048))) 3948c2ecf20Sopenharmony_ci return count - todo; 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci free = dvb_ringbuffer_free(rbuf); 3978c2ecf20Sopenharmony_ci if (free > todo) 3988c2ecf20Sopenharmony_ci free = todo; 3998c2ecf20Sopenharmony_ci dvb_ringbuffer_write(rbuf, buf, free); 4008c2ecf20Sopenharmony_ci todo -= free; 4018c2ecf20Sopenharmony_ci buf += free; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci return count - todo; 4058c2ecf20Sopenharmony_ci} 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cistatic void play_video_cb(u8 *buf, int count, void *priv) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci struct av7110 *av7110 = (struct av7110 *) priv; 4108c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci if ((buf[3] & 0xe0) == 0xe0) { 4138c2ecf20Sopenharmony_ci get_video_format(av7110, buf, count); 4148c2ecf20Sopenharmony_ci aux_ring_buffer_write(&av7110->avout, buf, count); 4158c2ecf20Sopenharmony_ci } else 4168c2ecf20Sopenharmony_ci aux_ring_buffer_write(&av7110->aout, buf, count); 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic void play_audio_cb(u8 *buf, int count, void *priv) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci struct av7110 *av7110 = (struct av7110 *) priv; 4228c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci aux_ring_buffer_write(&av7110->aout, buf, count); 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci#define FREE_COND_TS (dvb_ringbuffer_free(rb) >= 4096) 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic ssize_t ts_play(struct av7110 *av7110, const char __user *buf, 4318c2ecf20Sopenharmony_ci unsigned long count, int nonblock, int type) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci struct dvb_ringbuffer *rb; 4348c2ecf20Sopenharmony_ci u8 *kb; 4358c2ecf20Sopenharmony_ci unsigned long todo = count; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci dprintk(2, "%s: type %d cnt %lu\n", __func__, type, count); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci rb = (type) ? &av7110->avout : &av7110->aout; 4408c2ecf20Sopenharmony_ci kb = av7110->kbuf[type]; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci if (!kb) 4438c2ecf20Sopenharmony_ci return -ENOBUFS; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (nonblock && !FREE_COND_TS) 4468c2ecf20Sopenharmony_ci return -EWOULDBLOCK; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci while (todo >= TS_SIZE) { 4498c2ecf20Sopenharmony_ci if (!FREE_COND_TS) { 4508c2ecf20Sopenharmony_ci if (nonblock) 4518c2ecf20Sopenharmony_ci return count - todo; 4528c2ecf20Sopenharmony_ci if (wait_event_interruptible(rb->queue, FREE_COND_TS)) 4538c2ecf20Sopenharmony_ci return count - todo; 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci if (copy_from_user(kb, buf, TS_SIZE)) 4568c2ecf20Sopenharmony_ci return -EFAULT; 4578c2ecf20Sopenharmony_ci write_ts_to_decoder(av7110, type, kb, TS_SIZE); 4588c2ecf20Sopenharmony_ci todo -= TS_SIZE; 4598c2ecf20Sopenharmony_ci buf += TS_SIZE; 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci return count - todo; 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci#define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \ 4678c2ecf20Sopenharmony_ci dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024) 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic ssize_t dvb_play(struct av7110 *av7110, const char __user *buf, 4708c2ecf20Sopenharmony_ci unsigned long count, int nonblock, int type) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci unsigned long todo = count, n; 4738c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (!av7110->kbuf[type]) 4768c2ecf20Sopenharmony_ci return -ENOBUFS; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci if (nonblock && !FREE_COND) 4798c2ecf20Sopenharmony_ci return -EWOULDBLOCK; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci while (todo > 0) { 4828c2ecf20Sopenharmony_ci if (!FREE_COND) { 4838c2ecf20Sopenharmony_ci if (nonblock) 4848c2ecf20Sopenharmony_ci return count - todo; 4858c2ecf20Sopenharmony_ci if (wait_event_interruptible(av7110->avout.queue, 4868c2ecf20Sopenharmony_ci FREE_COND)) 4878c2ecf20Sopenharmony_ci return count - todo; 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci n = todo; 4908c2ecf20Sopenharmony_ci if (n > IPACKS * 2) 4918c2ecf20Sopenharmony_ci n = IPACKS * 2; 4928c2ecf20Sopenharmony_ci if (copy_from_user(av7110->kbuf[type], buf, n)) 4938c2ecf20Sopenharmony_ci return -EFAULT; 4948c2ecf20Sopenharmony_ci av7110_ipack_instant_repack(av7110->kbuf[type], n, 4958c2ecf20Sopenharmony_ci &av7110->ipack[type]); 4968c2ecf20Sopenharmony_ci todo -= n; 4978c2ecf20Sopenharmony_ci buf += n; 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci return count - todo; 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic ssize_t dvb_play_kernel(struct av7110 *av7110, const u8 *buf, 5038c2ecf20Sopenharmony_ci unsigned long count, int nonblock, int type) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci unsigned long todo = count, n; 5068c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (!av7110->kbuf[type]) 5098c2ecf20Sopenharmony_ci return -ENOBUFS; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci if (nonblock && !FREE_COND) 5128c2ecf20Sopenharmony_ci return -EWOULDBLOCK; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci while (todo > 0) { 5158c2ecf20Sopenharmony_ci if (!FREE_COND) { 5168c2ecf20Sopenharmony_ci if (nonblock) 5178c2ecf20Sopenharmony_ci return count - todo; 5188c2ecf20Sopenharmony_ci if (wait_event_interruptible(av7110->avout.queue, 5198c2ecf20Sopenharmony_ci FREE_COND)) 5208c2ecf20Sopenharmony_ci return count - todo; 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci n = todo; 5238c2ecf20Sopenharmony_ci if (n > IPACKS * 2) 5248c2ecf20Sopenharmony_ci n = IPACKS * 2; 5258c2ecf20Sopenharmony_ci av7110_ipack_instant_repack(buf, n, &av7110->ipack[type]); 5268c2ecf20Sopenharmony_ci todo -= n; 5278c2ecf20Sopenharmony_ci buf += n; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci return count - todo; 5308c2ecf20Sopenharmony_ci} 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_cistatic ssize_t dvb_aplay(struct av7110 *av7110, const char __user *buf, 5338c2ecf20Sopenharmony_ci unsigned long count, int nonblock, int type) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci unsigned long todo = count, n; 5368c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci if (!av7110->kbuf[type]) 5398c2ecf20Sopenharmony_ci return -ENOBUFS; 5408c2ecf20Sopenharmony_ci if (nonblock && dvb_ringbuffer_free(&av7110->aout) < 20 * 1024) 5418c2ecf20Sopenharmony_ci return -EWOULDBLOCK; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci while (todo > 0) { 5448c2ecf20Sopenharmony_ci if (dvb_ringbuffer_free(&av7110->aout) < 20 * 1024) { 5458c2ecf20Sopenharmony_ci if (nonblock) 5468c2ecf20Sopenharmony_ci return count - todo; 5478c2ecf20Sopenharmony_ci if (wait_event_interruptible(av7110->aout.queue, 5488c2ecf20Sopenharmony_ci (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024))) 5498c2ecf20Sopenharmony_ci return count-todo; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci n = todo; 5528c2ecf20Sopenharmony_ci if (n > IPACKS * 2) 5538c2ecf20Sopenharmony_ci n = IPACKS * 2; 5548c2ecf20Sopenharmony_ci if (copy_from_user(av7110->kbuf[type], buf, n)) 5558c2ecf20Sopenharmony_ci return -EFAULT; 5568c2ecf20Sopenharmony_ci av7110_ipack_instant_repack(av7110->kbuf[type], n, 5578c2ecf20Sopenharmony_ci &av7110->ipack[type]); 5588c2ecf20Sopenharmony_ci todo -= n; 5598c2ecf20Sopenharmony_ci buf += n; 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci return count - todo; 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_civoid av7110_p2t_init(struct av7110_p2t *p, struct dvb_demux_feed *feed) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci memset(p->pes, 0, TS_SIZE); 5678c2ecf20Sopenharmony_ci p->counter = 0; 5688c2ecf20Sopenharmony_ci p->pos = 0; 5698c2ecf20Sopenharmony_ci p->frags = 0; 5708c2ecf20Sopenharmony_ci if (feed) 5718c2ecf20Sopenharmony_ci p->feed = feed; 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_cistatic void clear_p2t(struct av7110_p2t *p) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci memset(p->pes, 0, TS_SIZE); 5778c2ecf20Sopenharmony_ci// p->counter = 0; 5788c2ecf20Sopenharmony_ci p->pos = 0; 5798c2ecf20Sopenharmony_ci p->frags = 0; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cistatic int find_pes_header(u8 const *buf, long int length, int *frags) 5848c2ecf20Sopenharmony_ci{ 5858c2ecf20Sopenharmony_ci int c = 0; 5868c2ecf20Sopenharmony_ci int found = 0; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci *frags = 0; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci while (c < length - 3 && !found) { 5918c2ecf20Sopenharmony_ci if (buf[c] == 0x00 && buf[c + 1] == 0x00 && 5928c2ecf20Sopenharmony_ci buf[c + 2] == 0x01) { 5938c2ecf20Sopenharmony_ci switch ( buf[c + 3] ) { 5948c2ecf20Sopenharmony_ci case PROG_STREAM_MAP: 5958c2ecf20Sopenharmony_ci case PRIVATE_STREAM2: 5968c2ecf20Sopenharmony_ci case PROG_STREAM_DIR: 5978c2ecf20Sopenharmony_ci case ECM_STREAM : 5988c2ecf20Sopenharmony_ci case EMM_STREAM : 5998c2ecf20Sopenharmony_ci case PADDING_STREAM : 6008c2ecf20Sopenharmony_ci case DSM_CC_STREAM : 6018c2ecf20Sopenharmony_ci case ISO13522_STREAM: 6028c2ecf20Sopenharmony_ci case PRIVATE_STREAM1: 6038c2ecf20Sopenharmony_ci case AUDIO_STREAM_S ... AUDIO_STREAM_E: 6048c2ecf20Sopenharmony_ci case VIDEO_STREAM_S ... VIDEO_STREAM_E: 6058c2ecf20Sopenharmony_ci found = 1; 6068c2ecf20Sopenharmony_ci break; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci default: 6098c2ecf20Sopenharmony_ci c++; 6108c2ecf20Sopenharmony_ci break; 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci } else 6138c2ecf20Sopenharmony_ci c++; 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci if (c == length - 3 && !found) { 6168c2ecf20Sopenharmony_ci if (buf[length - 1] == 0x00) 6178c2ecf20Sopenharmony_ci *frags = 1; 6188c2ecf20Sopenharmony_ci if (buf[length - 2] == 0x00 && 6198c2ecf20Sopenharmony_ci buf[length - 1] == 0x00) 6208c2ecf20Sopenharmony_ci *frags = 2; 6218c2ecf20Sopenharmony_ci if (buf[length - 3] == 0x00 && 6228c2ecf20Sopenharmony_ci buf[length - 2] == 0x00 && 6238c2ecf20Sopenharmony_ci buf[length - 1] == 0x01) 6248c2ecf20Sopenharmony_ci *frags = 3; 6258c2ecf20Sopenharmony_ci return -1; 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci return c; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_civoid av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci int c, c2, l, add; 6348c2ecf20Sopenharmony_ci int check, rest; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci c = 0; 6378c2ecf20Sopenharmony_ci c2 = 0; 6388c2ecf20Sopenharmony_ci if (p->frags){ 6398c2ecf20Sopenharmony_ci check = 0; 6408c2ecf20Sopenharmony_ci switch(p->frags) { 6418c2ecf20Sopenharmony_ci case 1: 6428c2ecf20Sopenharmony_ci if (buf[c] == 0x00 && buf[c + 1] == 0x01) { 6438c2ecf20Sopenharmony_ci check = 1; 6448c2ecf20Sopenharmony_ci c += 2; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci break; 6478c2ecf20Sopenharmony_ci case 2: 6488c2ecf20Sopenharmony_ci if (buf[c] == 0x01) { 6498c2ecf20Sopenharmony_ci check = 1; 6508c2ecf20Sopenharmony_ci c++; 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci break; 6538c2ecf20Sopenharmony_ci case 3: 6548c2ecf20Sopenharmony_ci check = 1; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci if (check) { 6578c2ecf20Sopenharmony_ci switch (buf[c]) { 6588c2ecf20Sopenharmony_ci case PROG_STREAM_MAP: 6598c2ecf20Sopenharmony_ci case PRIVATE_STREAM2: 6608c2ecf20Sopenharmony_ci case PROG_STREAM_DIR: 6618c2ecf20Sopenharmony_ci case ECM_STREAM : 6628c2ecf20Sopenharmony_ci case EMM_STREAM : 6638c2ecf20Sopenharmony_ci case PADDING_STREAM : 6648c2ecf20Sopenharmony_ci case DSM_CC_STREAM : 6658c2ecf20Sopenharmony_ci case ISO13522_STREAM: 6668c2ecf20Sopenharmony_ci case PRIVATE_STREAM1: 6678c2ecf20Sopenharmony_ci case AUDIO_STREAM_S ... AUDIO_STREAM_E: 6688c2ecf20Sopenharmony_ci case VIDEO_STREAM_S ... VIDEO_STREAM_E: 6698c2ecf20Sopenharmony_ci p->pes[0] = 0x00; 6708c2ecf20Sopenharmony_ci p->pes[1] = 0x00; 6718c2ecf20Sopenharmony_ci p->pes[2] = 0x01; 6728c2ecf20Sopenharmony_ci p->pes[3] = buf[c]; 6738c2ecf20Sopenharmony_ci p->pos = 4; 6748c2ecf20Sopenharmony_ci memcpy(p->pes + p->pos, buf + c, (TS_SIZE - 4) - p->pos); 6758c2ecf20Sopenharmony_ci c += (TS_SIZE - 4) - p->pos; 6768c2ecf20Sopenharmony_ci p_to_t(p->pes, (TS_SIZE - 4), pid, &p->counter, p->feed); 6778c2ecf20Sopenharmony_ci clear_p2t(p); 6788c2ecf20Sopenharmony_ci break; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci default: 6818c2ecf20Sopenharmony_ci c = 0; 6828c2ecf20Sopenharmony_ci break; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci p->frags = 0; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci if (p->pos) { 6898c2ecf20Sopenharmony_ci c2 = find_pes_header(buf + c, length - c, &p->frags); 6908c2ecf20Sopenharmony_ci if (c2 >= 0 && c2 < (TS_SIZE - 4) - p->pos) 6918c2ecf20Sopenharmony_ci l = c2+c; 6928c2ecf20Sopenharmony_ci else 6938c2ecf20Sopenharmony_ci l = (TS_SIZE - 4) - p->pos; 6948c2ecf20Sopenharmony_ci memcpy(p->pes + p->pos, buf, l); 6958c2ecf20Sopenharmony_ci c += l; 6968c2ecf20Sopenharmony_ci p->pos += l; 6978c2ecf20Sopenharmony_ci p_to_t(p->pes, p->pos, pid, &p->counter, p->feed); 6988c2ecf20Sopenharmony_ci clear_p2t(p); 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci add = 0; 7028c2ecf20Sopenharmony_ci while (c < length) { 7038c2ecf20Sopenharmony_ci c2 = find_pes_header(buf + c + add, length - c - add, &p->frags); 7048c2ecf20Sopenharmony_ci if (c2 >= 0) { 7058c2ecf20Sopenharmony_ci c2 += c + add; 7068c2ecf20Sopenharmony_ci if (c2 > c){ 7078c2ecf20Sopenharmony_ci p_to_t(buf + c, c2 - c, pid, &p->counter, p->feed); 7088c2ecf20Sopenharmony_ci c = c2; 7098c2ecf20Sopenharmony_ci clear_p2t(p); 7108c2ecf20Sopenharmony_ci add = 0; 7118c2ecf20Sopenharmony_ci } else 7128c2ecf20Sopenharmony_ci add = 1; 7138c2ecf20Sopenharmony_ci } else { 7148c2ecf20Sopenharmony_ci l = length - c; 7158c2ecf20Sopenharmony_ci rest = l % (TS_SIZE - 4); 7168c2ecf20Sopenharmony_ci l -= rest; 7178c2ecf20Sopenharmony_ci p_to_t(buf + c, l, pid, &p->counter, p->feed); 7188c2ecf20Sopenharmony_ci memcpy(p->pes, buf + c + l, rest); 7198c2ecf20Sopenharmony_ci p->pos = rest; 7208c2ecf20Sopenharmony_ci c = length; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci} 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length) 7278c2ecf20Sopenharmony_ci{ 7288c2ecf20Sopenharmony_ci int i; 7298c2ecf20Sopenharmony_ci int c = 0; 7308c2ecf20Sopenharmony_ci int fill; 7318c2ecf20Sopenharmony_ci u8 tshead[4] = { 0x47, 0x00, 0x00, 0x10 }; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci fill = (TS_SIZE - 4) - length; 7348c2ecf20Sopenharmony_ci if (pes_start) 7358c2ecf20Sopenharmony_ci tshead[1] = 0x40; 7368c2ecf20Sopenharmony_ci if (fill) 7378c2ecf20Sopenharmony_ci tshead[3] = 0x30; 7388c2ecf20Sopenharmony_ci tshead[1] |= (u8)((pid & 0x1F00) >> 8); 7398c2ecf20Sopenharmony_ci tshead[2] |= (u8)(pid & 0x00FF); 7408c2ecf20Sopenharmony_ci tshead[3] |= ((*counter)++ & 0x0F); 7418c2ecf20Sopenharmony_ci memcpy(buf, tshead, 4); 7428c2ecf20Sopenharmony_ci c += 4; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci if (fill) { 7458c2ecf20Sopenharmony_ci buf[4] = fill - 1; 7468c2ecf20Sopenharmony_ci c++; 7478c2ecf20Sopenharmony_ci if (fill > 1) { 7488c2ecf20Sopenharmony_ci buf[5] = 0x00; 7498c2ecf20Sopenharmony_ci c++; 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci for (i = 6; i < fill + 4; i++) { 7528c2ecf20Sopenharmony_ci buf[i] = 0xFF; 7538c2ecf20Sopenharmony_ci c++; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci return c; 7588c2ecf20Sopenharmony_ci} 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_cistatic void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, 7628c2ecf20Sopenharmony_ci struct dvb_demux_feed *feed) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci int l, pes_start; 7658c2ecf20Sopenharmony_ci u8 obuf[TS_SIZE]; 7668c2ecf20Sopenharmony_ci long c = 0; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci pes_start = 0; 7698c2ecf20Sopenharmony_ci if (length > 3 && 7708c2ecf20Sopenharmony_ci buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01) 7718c2ecf20Sopenharmony_ci switch (buf[3]) { 7728c2ecf20Sopenharmony_ci case PROG_STREAM_MAP: 7738c2ecf20Sopenharmony_ci case PRIVATE_STREAM2: 7748c2ecf20Sopenharmony_ci case PROG_STREAM_DIR: 7758c2ecf20Sopenharmony_ci case ECM_STREAM : 7768c2ecf20Sopenharmony_ci case EMM_STREAM : 7778c2ecf20Sopenharmony_ci case PADDING_STREAM : 7788c2ecf20Sopenharmony_ci case DSM_CC_STREAM : 7798c2ecf20Sopenharmony_ci case ISO13522_STREAM: 7808c2ecf20Sopenharmony_ci case PRIVATE_STREAM1: 7818c2ecf20Sopenharmony_ci case AUDIO_STREAM_S ... AUDIO_STREAM_E: 7828c2ecf20Sopenharmony_ci case VIDEO_STREAM_S ... VIDEO_STREAM_E: 7838c2ecf20Sopenharmony_ci pes_start = 1; 7848c2ecf20Sopenharmony_ci break; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci default: 7878c2ecf20Sopenharmony_ci break; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci while (c < length) { 7918c2ecf20Sopenharmony_ci memset(obuf, 0, TS_SIZE); 7928c2ecf20Sopenharmony_ci if (length - c >= (TS_SIZE - 4)){ 7938c2ecf20Sopenharmony_ci l = write_ts_header2(pid, counter, pes_start, 7948c2ecf20Sopenharmony_ci obuf, (TS_SIZE - 4)); 7958c2ecf20Sopenharmony_ci memcpy(obuf + l, buf + c, TS_SIZE - l); 7968c2ecf20Sopenharmony_ci c += TS_SIZE - l; 7978c2ecf20Sopenharmony_ci } else { 7988c2ecf20Sopenharmony_ci l = write_ts_header2(pid, counter, pes_start, 7998c2ecf20Sopenharmony_ci obuf, length - c); 8008c2ecf20Sopenharmony_ci memcpy(obuf + l, buf + c, TS_SIZE - l); 8018c2ecf20Sopenharmony_ci c = length; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, NULL); 8048c2ecf20Sopenharmony_ci pes_start = 0; 8058c2ecf20Sopenharmony_ci } 8068c2ecf20Sopenharmony_ci} 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cistatic int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci struct ipack *ipack = &av7110->ipack[type]; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci if (buf[1] & TRANS_ERROR) { 8148c2ecf20Sopenharmony_ci av7110_ipack_reset(ipack); 8158c2ecf20Sopenharmony_ci return -1; 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci if (!(buf[3] & PAYLOAD)) 8198c2ecf20Sopenharmony_ci return -1; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci if (buf[1] & PAY_START) 8228c2ecf20Sopenharmony_ci av7110_ipack_flush(ipack); 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci if (buf[3] & ADAPT_FIELD) { 8258c2ecf20Sopenharmony_ci len -= buf[4] + 1; 8268c2ecf20Sopenharmony_ci buf += buf[4] + 1; 8278c2ecf20Sopenharmony_ci if (!len) 8288c2ecf20Sopenharmony_ci return 0; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci av7110_ipack_instant_repack(buf + 4, len - 4, ipack); 8328c2ecf20Sopenharmony_ci return 0; 8338c2ecf20Sopenharmony_ci} 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ciint av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci struct dvb_demux *demux = feed->demux; 8398c2ecf20Sopenharmony_ci struct av7110 *av7110 = (struct av7110 *) demux->priv; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci if (av7110->full_ts && demux->dmx.frontend->source != DMX_MEMORY_FE) 8448c2ecf20Sopenharmony_ci return 0; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci switch (feed->pes_type) { 8478c2ecf20Sopenharmony_ci case 0: 8488c2ecf20Sopenharmony_ci if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY) 8498c2ecf20Sopenharmony_ci return -EINVAL; 8508c2ecf20Sopenharmony_ci break; 8518c2ecf20Sopenharmony_ci case 1: 8528c2ecf20Sopenharmony_ci if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) 8538c2ecf20Sopenharmony_ci return -EINVAL; 8548c2ecf20Sopenharmony_ci break; 8558c2ecf20Sopenharmony_ci default: 8568c2ecf20Sopenharmony_ci return -1; 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci return write_ts_to_decoder(av7110, feed->pes_type, buf, len); 8608c2ecf20Sopenharmony_ci} 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci/****************************************************************************** 8658c2ecf20Sopenharmony_ci * Video MPEG decoder events 8668c2ecf20Sopenharmony_ci ******************************************************************************/ 8678c2ecf20Sopenharmony_civoid dvb_video_add_event(struct av7110 *av7110, struct video_event *event) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci struct dvb_video_events *events = &av7110->video_events; 8708c2ecf20Sopenharmony_ci int wp; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci spin_lock_bh(&events->lock); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci wp = (events->eventw + 1) % MAX_VIDEO_EVENT; 8758c2ecf20Sopenharmony_ci if (wp == events->eventr) { 8768c2ecf20Sopenharmony_ci events->overflow = 1; 8778c2ecf20Sopenharmony_ci events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT; 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci //FIXME: timestamp? 8818c2ecf20Sopenharmony_ci memcpy(&events->events[events->eventw], event, sizeof(struct video_event)); 8828c2ecf20Sopenharmony_ci events->eventw = wp; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci spin_unlock_bh(&events->lock); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci wake_up_interruptible(&events->wait_queue); 8878c2ecf20Sopenharmony_ci} 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic int dvb_video_get_event (struct av7110 *av7110, struct video_event *event, int flags) 8918c2ecf20Sopenharmony_ci{ 8928c2ecf20Sopenharmony_ci struct dvb_video_events *events = &av7110->video_events; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (events->overflow) { 8958c2ecf20Sopenharmony_ci events->overflow = 0; 8968c2ecf20Sopenharmony_ci return -EOVERFLOW; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci if (events->eventw == events->eventr) { 8998c2ecf20Sopenharmony_ci int ret; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (flags & O_NONBLOCK) 9028c2ecf20Sopenharmony_ci return -EWOULDBLOCK; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci ret = wait_event_interruptible(events->wait_queue, 9058c2ecf20Sopenharmony_ci events->eventw != events->eventr); 9068c2ecf20Sopenharmony_ci if (ret < 0) 9078c2ecf20Sopenharmony_ci return ret; 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci spin_lock_bh(&events->lock); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci memcpy(event, &events->events[events->eventr], 9138c2ecf20Sopenharmony_ci sizeof(struct video_event)); 9148c2ecf20Sopenharmony_ci events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci spin_unlock_bh(&events->lock); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci return 0; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci/****************************************************************************** 9228c2ecf20Sopenharmony_ci * DVB device file operations 9238c2ecf20Sopenharmony_ci ******************************************************************************/ 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic __poll_t dvb_video_poll(struct file *file, poll_table *wait) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 9288c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 9298c2ecf20Sopenharmony_ci __poll_t mask = 0; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci if ((file->f_flags & O_ACCMODE) != O_RDONLY) 9348c2ecf20Sopenharmony_ci poll_wait(file, &av7110->avout.queue, wait); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci poll_wait(file, &av7110->video_events.wait_queue, wait); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (av7110->video_events.eventw != av7110->video_events.eventr) 9398c2ecf20Sopenharmony_ci mask = EPOLLPRI; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci if ((file->f_flags & O_ACCMODE) != O_RDONLY) { 9428c2ecf20Sopenharmony_ci if (av7110->playing) { 9438c2ecf20Sopenharmony_ci if (FREE_COND) 9448c2ecf20Sopenharmony_ci mask |= (EPOLLOUT | EPOLLWRNORM); 9458c2ecf20Sopenharmony_ci } else { 9468c2ecf20Sopenharmony_ci /* if not playing: may play if asked for */ 9478c2ecf20Sopenharmony_ci mask |= (EPOLLOUT | EPOLLWRNORM); 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci return mask; 9528c2ecf20Sopenharmony_ci} 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_cistatic ssize_t dvb_video_write(struct file *file, const char __user *buf, 9558c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 9568c2ecf20Sopenharmony_ci{ 9578c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 9588c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 9598c2ecf20Sopenharmony_ci unsigned char c; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci if ((file->f_flags & O_ACCMODE) == O_RDONLY) 9648c2ecf20Sopenharmony_ci return -EPERM; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) 9678c2ecf20Sopenharmony_ci return -EPERM; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (get_user(c, buf)) 9708c2ecf20Sopenharmony_ci return -EFAULT; 9718c2ecf20Sopenharmony_ci if (c == 0x47 && count % TS_SIZE == 0) 9728c2ecf20Sopenharmony_ci return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); 9738c2ecf20Sopenharmony_ci else 9748c2ecf20Sopenharmony_ci return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic __poll_t dvb_audio_poll(struct file *file, poll_table *wait) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 9808c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 9818c2ecf20Sopenharmony_ci __poll_t mask = 0; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci poll_wait(file, &av7110->aout.queue, wait); 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci if (av7110->playing) { 9888c2ecf20Sopenharmony_ci if (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024) 9898c2ecf20Sopenharmony_ci mask |= (EPOLLOUT | EPOLLWRNORM); 9908c2ecf20Sopenharmony_ci } else /* if not playing: may play if asked for */ 9918c2ecf20Sopenharmony_ci mask = (EPOLLOUT | EPOLLWRNORM); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci return mask; 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_cistatic ssize_t dvb_audio_write(struct file *file, const char __user *buf, 9978c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 9988c2ecf20Sopenharmony_ci{ 9998c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 10008c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 10018c2ecf20Sopenharmony_ci unsigned char c; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) { 10068c2ecf20Sopenharmony_ci printk(KERN_ERR "not audio source memory\n"); 10078c2ecf20Sopenharmony_ci return -EPERM; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (get_user(c, buf)) 10118c2ecf20Sopenharmony_ci return -EFAULT; 10128c2ecf20Sopenharmony_ci if (c == 0x47 && count % TS_SIZE == 0) 10138c2ecf20Sopenharmony_ci return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); 10148c2ecf20Sopenharmony_ci else 10158c2ecf20Sopenharmony_ci return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); 10168c2ecf20Sopenharmony_ci} 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_cistatic u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 }; 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci#define MIN_IFRAME 400000 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_cistatic int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock) 10238c2ecf20Sopenharmony_ci{ 10248c2ecf20Sopenharmony_ci unsigned i, n; 10258c2ecf20Sopenharmony_ci int progressive = 0; 10268c2ecf20Sopenharmony_ci int match = 0; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci if (len == 0) 10318c2ecf20Sopenharmony_ci return 0; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci if (!(av7110->playing & RP_VIDEO)) { 10348c2ecf20Sopenharmony_ci if (av7110_av_start_play(av7110, RP_VIDEO) < 0) 10358c2ecf20Sopenharmony_ci return -EBUSY; 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci /* search in buf for instances of 00 00 01 b5 1? */ 10398c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 10408c2ecf20Sopenharmony_ci unsigned char c; 10418c2ecf20Sopenharmony_ci if (get_user(c, buf + i)) 10428c2ecf20Sopenharmony_ci return -EFAULT; 10438c2ecf20Sopenharmony_ci if (match == 5) { 10448c2ecf20Sopenharmony_ci progressive = c & 0x08; 10458c2ecf20Sopenharmony_ci match = 0; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci if (c == 0x00) { 10488c2ecf20Sopenharmony_ci match = (match == 1 || match == 2) ? 2 : 1; 10498c2ecf20Sopenharmony_ci continue; 10508c2ecf20Sopenharmony_ci } 10518c2ecf20Sopenharmony_ci switch (match++) { 10528c2ecf20Sopenharmony_ci case 2: if (c == 0x01) 10538c2ecf20Sopenharmony_ci continue; 10548c2ecf20Sopenharmony_ci break; 10558c2ecf20Sopenharmony_ci case 3: if (c == 0xb5) 10568c2ecf20Sopenharmony_ci continue; 10578c2ecf20Sopenharmony_ci break; 10588c2ecf20Sopenharmony_ci case 4: if ((c & 0xf0) == 0x10) 10598c2ecf20Sopenharmony_ci continue; 10608c2ecf20Sopenharmony_ci break; 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci match = 0; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci /* setting n always > 1, fixes problems when playing stillframes 10668c2ecf20Sopenharmony_ci consisting of I- and P-Frames */ 10678c2ecf20Sopenharmony_ci n = MIN_IFRAME / len + 1; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci /* FIXME: nonblock? */ 10708c2ecf20Sopenharmony_ci dvb_play_kernel(av7110, iframe_header, sizeof(iframe_header), 0, 1); 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) 10738c2ecf20Sopenharmony_ci dvb_play(av7110, buf, len, 0, 1); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci av7110_ipack_flush(&av7110->ipack[1]); 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci if (progressive) 10788c2ecf20Sopenharmony_ci return vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1); 10798c2ecf20Sopenharmony_ci else 10808c2ecf20Sopenharmony_ci return 0; 10818c2ecf20Sopenharmony_ci} 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 10848c2ecf20Sopenharmony_cistruct compat_video_still_picture { 10858c2ecf20Sopenharmony_ci compat_uptr_t iFrame; 10868c2ecf20Sopenharmony_ci int32_t size; 10878c2ecf20Sopenharmony_ci}; 10888c2ecf20Sopenharmony_ci#define VIDEO_STILLPICTURE32 _IOW('o', 30, struct compat_video_still_picture) 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_cistruct compat_video_event { 10918c2ecf20Sopenharmony_ci __s32 type; 10928c2ecf20Sopenharmony_ci /* unused, make sure to use atomic time for y2038 if it ever gets used */ 10938c2ecf20Sopenharmony_ci compat_long_t timestamp; 10948c2ecf20Sopenharmony_ci union { 10958c2ecf20Sopenharmony_ci video_size_t size; 10968c2ecf20Sopenharmony_ci unsigned int frame_rate; /* in frames per 1000sec */ 10978c2ecf20Sopenharmony_ci unsigned char vsync_field; /* unknown/odd/even/progressive */ 10988c2ecf20Sopenharmony_ci } u; 10998c2ecf20Sopenharmony_ci}; 11008c2ecf20Sopenharmony_ci#define VIDEO_GET_EVENT32 _IOR('o', 28, struct compat_video_event) 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_cistatic int dvb_compat_video_get_event(struct av7110 *av7110, 11038c2ecf20Sopenharmony_ci struct compat_video_event *event, int flags) 11048c2ecf20Sopenharmony_ci{ 11058c2ecf20Sopenharmony_ci struct video_event ev; 11068c2ecf20Sopenharmony_ci int ret; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci ret = dvb_video_get_event(av7110, &ev, flags); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci *event = (struct compat_video_event) { 11118c2ecf20Sopenharmony_ci .type = ev.type, 11128c2ecf20Sopenharmony_ci .timestamp = ev.timestamp, 11138c2ecf20Sopenharmony_ci .u.size = ev.u.size, 11148c2ecf20Sopenharmony_ci }; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci return ret; 11178c2ecf20Sopenharmony_ci} 11188c2ecf20Sopenharmony_ci#endif 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_cistatic int dvb_video_ioctl(struct file *file, 11218c2ecf20Sopenharmony_ci unsigned int cmd, void *parg) 11228c2ecf20Sopenharmony_ci{ 11238c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 11248c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 11258c2ecf20Sopenharmony_ci unsigned long arg = (unsigned long) parg; 11268c2ecf20Sopenharmony_ci int ret = 0; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd); 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci if ((file->f_flags & O_ACCMODE) == O_RDONLY) { 11318c2ecf20Sopenharmony_ci if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT && 11328c2ecf20Sopenharmony_ci cmd != VIDEO_GET_SIZE ) { 11338c2ecf20Sopenharmony_ci return -EPERM; 11348c2ecf20Sopenharmony_ci } 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&av7110->ioctl_mutex)) 11388c2ecf20Sopenharmony_ci return -ERESTARTSYS; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci switch (cmd) { 11418c2ecf20Sopenharmony_ci case VIDEO_STOP: 11428c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_STOPPED; 11438c2ecf20Sopenharmony_ci if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) 11448c2ecf20Sopenharmony_ci ret = av7110_av_stop(av7110, RP_VIDEO); 11458c2ecf20Sopenharmony_ci else 11468c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 11478c2ecf20Sopenharmony_ci av7110->videostate.video_blank ? 0 : 1); 11488c2ecf20Sopenharmony_ci if (!ret) 11498c2ecf20Sopenharmony_ci av7110->trickmode = TRICK_NONE; 11508c2ecf20Sopenharmony_ci break; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci case VIDEO_PLAY: 11538c2ecf20Sopenharmony_ci av7110->trickmode = TRICK_NONE; 11548c2ecf20Sopenharmony_ci if (av7110->videostate.play_state == VIDEO_FREEZED) { 11558c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_PLAYING; 11568c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0); 11578c2ecf20Sopenharmony_ci if (ret) 11588c2ecf20Sopenharmony_ci break; 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) { 11618c2ecf20Sopenharmony_ci if (av7110->playing == RP_AV) { 11628c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0); 11638c2ecf20Sopenharmony_ci if (ret) 11648c2ecf20Sopenharmony_ci break; 11658c2ecf20Sopenharmony_ci av7110->playing &= ~RP_VIDEO; 11668c2ecf20Sopenharmony_ci } 11678c2ecf20Sopenharmony_ci ret = av7110_av_start_play(av7110, RP_VIDEO); 11688c2ecf20Sopenharmony_ci } 11698c2ecf20Sopenharmony_ci if (!ret) 11708c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0); 11718c2ecf20Sopenharmony_ci if (!ret) 11728c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_PLAYING; 11738c2ecf20Sopenharmony_ci break; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci case VIDEO_FREEZE: 11768c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_FREEZED; 11778c2ecf20Sopenharmony_ci if (av7110->playing & RP_VIDEO) 11788c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0); 11798c2ecf20Sopenharmony_ci else 11808c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1); 11818c2ecf20Sopenharmony_ci if (!ret) 11828c2ecf20Sopenharmony_ci av7110->trickmode = TRICK_FREEZE; 11838c2ecf20Sopenharmony_ci break; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci case VIDEO_CONTINUE: 11868c2ecf20Sopenharmony_ci if (av7110->playing & RP_VIDEO) 11878c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0); 11888c2ecf20Sopenharmony_ci if (!ret) 11898c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0); 11908c2ecf20Sopenharmony_ci if (!ret) { 11918c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_PLAYING; 11928c2ecf20Sopenharmony_ci av7110->trickmode = TRICK_NONE; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci break; 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci case VIDEO_SELECT_SOURCE: 11978c2ecf20Sopenharmony_ci av7110->videostate.stream_source = (video_stream_source_t) arg; 11988c2ecf20Sopenharmony_ci break; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci case VIDEO_SET_BLANK: 12018c2ecf20Sopenharmony_ci av7110->videostate.video_blank = (int) arg; 12028c2ecf20Sopenharmony_ci break; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci case VIDEO_GET_STATUS: 12058c2ecf20Sopenharmony_ci memcpy(parg, &av7110->videostate, sizeof(struct video_status)); 12068c2ecf20Sopenharmony_ci break; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 12098c2ecf20Sopenharmony_ci case VIDEO_GET_EVENT32: 12108c2ecf20Sopenharmony_ci ret = dvb_compat_video_get_event(av7110, parg, file->f_flags); 12118c2ecf20Sopenharmony_ci break; 12128c2ecf20Sopenharmony_ci#endif 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci case VIDEO_GET_EVENT: 12158c2ecf20Sopenharmony_ci ret = dvb_video_get_event(av7110, parg, file->f_flags); 12168c2ecf20Sopenharmony_ci break; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci case VIDEO_GET_SIZE: 12198c2ecf20Sopenharmony_ci memcpy(parg, &av7110->video_size, sizeof(video_size_t)); 12208c2ecf20Sopenharmony_ci break; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci case VIDEO_SET_DISPLAY_FORMAT: 12238c2ecf20Sopenharmony_ci { 12248c2ecf20Sopenharmony_ci video_displayformat_t format = (video_displayformat_t) arg; 12258c2ecf20Sopenharmony_ci switch (format) { 12268c2ecf20Sopenharmony_ci case VIDEO_PAN_SCAN: 12278c2ecf20Sopenharmony_ci av7110->display_panscan = VID_PAN_SCAN_PREF; 12288c2ecf20Sopenharmony_ci break; 12298c2ecf20Sopenharmony_ci case VIDEO_LETTER_BOX: 12308c2ecf20Sopenharmony_ci av7110->display_panscan = VID_VC_AND_PS_PREF; 12318c2ecf20Sopenharmony_ci break; 12328c2ecf20Sopenharmony_ci case VIDEO_CENTER_CUT_OUT: 12338c2ecf20Sopenharmony_ci av7110->display_panscan = VID_CENTRE_CUT_PREF; 12348c2ecf20Sopenharmony_ci break; 12358c2ecf20Sopenharmony_ci default: 12368c2ecf20Sopenharmony_ci ret = -EINVAL; 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci if (ret < 0) 12398c2ecf20Sopenharmony_ci break; 12408c2ecf20Sopenharmony_ci av7110->videostate.display_format = format; 12418c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType, 12428c2ecf20Sopenharmony_ci 1, av7110->display_panscan); 12438c2ecf20Sopenharmony_ci break; 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci case VIDEO_SET_FORMAT: 12478c2ecf20Sopenharmony_ci if (arg > 1) { 12488c2ecf20Sopenharmony_ci ret = -EINVAL; 12498c2ecf20Sopenharmony_ci break; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_ci av7110->display_ar = arg; 12528c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType, 12538c2ecf20Sopenharmony_ci 1, (u16) arg); 12548c2ecf20Sopenharmony_ci break; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 12578c2ecf20Sopenharmony_ci case VIDEO_STILLPICTURE32: 12588c2ecf20Sopenharmony_ci { 12598c2ecf20Sopenharmony_ci struct compat_video_still_picture *pic = 12608c2ecf20Sopenharmony_ci (struct compat_video_still_picture *) parg; 12618c2ecf20Sopenharmony_ci av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY; 12628c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); 12638c2ecf20Sopenharmony_ci ret = play_iframe(av7110, compat_ptr(pic->iFrame), 12648c2ecf20Sopenharmony_ci pic->size, file->f_flags & O_NONBLOCK); 12658c2ecf20Sopenharmony_ci break; 12668c2ecf20Sopenharmony_ci } 12678c2ecf20Sopenharmony_ci#endif 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci case VIDEO_STILLPICTURE: 12708c2ecf20Sopenharmony_ci { 12718c2ecf20Sopenharmony_ci struct video_still_picture *pic = 12728c2ecf20Sopenharmony_ci (struct video_still_picture *) parg; 12738c2ecf20Sopenharmony_ci av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY; 12748c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); 12758c2ecf20Sopenharmony_ci ret = play_iframe(av7110, pic->iFrame, pic->size, 12768c2ecf20Sopenharmony_ci file->f_flags & O_NONBLOCK); 12778c2ecf20Sopenharmony_ci break; 12788c2ecf20Sopenharmony_ci } 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci case VIDEO_FAST_FORWARD: 12818c2ecf20Sopenharmony_ci //note: arg is ignored by firmware 12828c2ecf20Sopenharmony_ci if (av7110->playing & RP_VIDEO) 12838c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, 12848c2ecf20Sopenharmony_ci __Scan_I, 2, AV_PES, 0); 12858c2ecf20Sopenharmony_ci else 12868c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_FFWD, arg); 12878c2ecf20Sopenharmony_ci if (!ret) { 12888c2ecf20Sopenharmony_ci av7110->trickmode = TRICK_FAST; 12898c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_PLAYING; 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci break; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci case VIDEO_SLOWMOTION: 12948c2ecf20Sopenharmony_ci if (av7110->playing&RP_VIDEO) { 12958c2ecf20Sopenharmony_ci if (av7110->trickmode != TRICK_SLOW) 12968c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0); 12978c2ecf20Sopenharmony_ci if (!ret) 12988c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg); 12998c2ecf20Sopenharmony_ci } else { 13008c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0); 13018c2ecf20Sopenharmony_ci if (!ret) 13028c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 0); 13038c2ecf20Sopenharmony_ci if (!ret) 13048c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg); 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci if (!ret) { 13078c2ecf20Sopenharmony_ci av7110->trickmode = TRICK_SLOW; 13088c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_PLAYING; 13098c2ecf20Sopenharmony_ci } 13108c2ecf20Sopenharmony_ci break; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci case VIDEO_GET_CAPABILITIES: 13138c2ecf20Sopenharmony_ci *(int *)parg = VIDEO_CAP_MPEG1 | VIDEO_CAP_MPEG2 | 13148c2ecf20Sopenharmony_ci VIDEO_CAP_SYS | VIDEO_CAP_PROG; 13158c2ecf20Sopenharmony_ci break; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci case VIDEO_CLEAR_BUFFER: 13188c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); 13198c2ecf20Sopenharmony_ci av7110_ipack_reset(&av7110->ipack[1]); 13208c2ecf20Sopenharmony_ci if (av7110->playing == RP_AV) { 13218c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, 13228c2ecf20Sopenharmony_ci __Play, 2, AV_PES, 0); 13238c2ecf20Sopenharmony_ci if (ret) 13248c2ecf20Sopenharmony_ci break; 13258c2ecf20Sopenharmony_ci if (av7110->trickmode == TRICK_FAST) 13268c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, 13278c2ecf20Sopenharmony_ci __Scan_I, 2, AV_PES, 0); 13288c2ecf20Sopenharmony_ci if (av7110->trickmode == TRICK_SLOW) { 13298c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, 13308c2ecf20Sopenharmony_ci __Slow, 2, 0, 0); 13318c2ecf20Sopenharmony_ci if (!ret) 13328c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg); 13338c2ecf20Sopenharmony_ci } 13348c2ecf20Sopenharmony_ci if (av7110->trickmode == TRICK_FREEZE) 13358c2ecf20Sopenharmony_ci ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 1); 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci break; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci case VIDEO_SET_STREAMTYPE: 13408c2ecf20Sopenharmony_ci break; 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci default: 13438c2ecf20Sopenharmony_ci ret = -ENOIOCTLCMD; 13448c2ecf20Sopenharmony_ci break; 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci mutex_unlock(&av7110->ioctl_mutex); 13488c2ecf20Sopenharmony_ci return ret; 13498c2ecf20Sopenharmony_ci} 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_cistatic int dvb_audio_ioctl(struct file *file, 13528c2ecf20Sopenharmony_ci unsigned int cmd, void *parg) 13538c2ecf20Sopenharmony_ci{ 13548c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 13558c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 13568c2ecf20Sopenharmony_ci unsigned long arg = (unsigned long) parg; 13578c2ecf20Sopenharmony_ci int ret = 0; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci if (((file->f_flags & O_ACCMODE) == O_RDONLY) && 13628c2ecf20Sopenharmony_ci (cmd != AUDIO_GET_STATUS)) 13638c2ecf20Sopenharmony_ci return -EPERM; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&av7110->ioctl_mutex)) 13668c2ecf20Sopenharmony_ci return -ERESTARTSYS; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci switch (cmd) { 13698c2ecf20Sopenharmony_ci case AUDIO_STOP: 13708c2ecf20Sopenharmony_ci if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY) 13718c2ecf20Sopenharmony_ci ret = av7110_av_stop(av7110, RP_AUDIO); 13728c2ecf20Sopenharmony_ci else 13738c2ecf20Sopenharmony_ci ret = audcom(av7110, AUDIO_CMD_MUTE); 13748c2ecf20Sopenharmony_ci if (!ret) 13758c2ecf20Sopenharmony_ci av7110->audiostate.play_state = AUDIO_STOPPED; 13768c2ecf20Sopenharmony_ci break; 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci case AUDIO_PLAY: 13798c2ecf20Sopenharmony_ci if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY) 13808c2ecf20Sopenharmony_ci ret = av7110_av_start_play(av7110, RP_AUDIO); 13818c2ecf20Sopenharmony_ci if (!ret) 13828c2ecf20Sopenharmony_ci ret = audcom(av7110, AUDIO_CMD_UNMUTE); 13838c2ecf20Sopenharmony_ci if (!ret) 13848c2ecf20Sopenharmony_ci av7110->audiostate.play_state = AUDIO_PLAYING; 13858c2ecf20Sopenharmony_ci break; 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci case AUDIO_PAUSE: 13888c2ecf20Sopenharmony_ci ret = audcom(av7110, AUDIO_CMD_MUTE); 13898c2ecf20Sopenharmony_ci if (!ret) 13908c2ecf20Sopenharmony_ci av7110->audiostate.play_state = AUDIO_PAUSED; 13918c2ecf20Sopenharmony_ci break; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci case AUDIO_CONTINUE: 13948c2ecf20Sopenharmony_ci if (av7110->audiostate.play_state == AUDIO_PAUSED) { 13958c2ecf20Sopenharmony_ci av7110->audiostate.play_state = AUDIO_PLAYING; 13968c2ecf20Sopenharmony_ci ret = audcom(av7110, AUDIO_CMD_UNMUTE | AUDIO_CMD_PCM16); 13978c2ecf20Sopenharmony_ci } 13988c2ecf20Sopenharmony_ci break; 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci case AUDIO_SELECT_SOURCE: 14018c2ecf20Sopenharmony_ci av7110->audiostate.stream_source = (audio_stream_source_t) arg; 14028c2ecf20Sopenharmony_ci break; 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci case AUDIO_SET_MUTE: 14058c2ecf20Sopenharmony_ci { 14068c2ecf20Sopenharmony_ci ret = audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE); 14078c2ecf20Sopenharmony_ci if (!ret) 14088c2ecf20Sopenharmony_ci av7110->audiostate.mute_state = (int) arg; 14098c2ecf20Sopenharmony_ci break; 14108c2ecf20Sopenharmony_ci } 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci case AUDIO_SET_AV_SYNC: 14138c2ecf20Sopenharmony_ci av7110->audiostate.AV_sync_state = (int) arg; 14148c2ecf20Sopenharmony_ci ret = audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF); 14158c2ecf20Sopenharmony_ci break; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci case AUDIO_SET_BYPASS_MODE: 14188c2ecf20Sopenharmony_ci if (FW_VERSION(av7110->arm_app) < 0x2621) 14198c2ecf20Sopenharmony_ci ret = -EINVAL; 14208c2ecf20Sopenharmony_ci av7110->audiostate.bypass_mode = (int)arg; 14218c2ecf20Sopenharmony_ci break; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci case AUDIO_CHANNEL_SELECT: 14248c2ecf20Sopenharmony_ci av7110->audiostate.channel_select = (audio_channel_select_t) arg; 14258c2ecf20Sopenharmony_ci switch(av7110->audiostate.channel_select) { 14268c2ecf20Sopenharmony_ci case AUDIO_STEREO: 14278c2ecf20Sopenharmony_ci ret = audcom(av7110, AUDIO_CMD_STEREO); 14288c2ecf20Sopenharmony_ci if (!ret) { 14298c2ecf20Sopenharmony_ci if (av7110->adac_type == DVB_ADAC_CRYSTAL) 14308c2ecf20Sopenharmony_ci i2c_writereg(av7110, 0x20, 0x02, 0x49); 14318c2ecf20Sopenharmony_ci else if (av7110->adac_type == DVB_ADAC_MSP34x5) 14328c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); 14338c2ecf20Sopenharmony_ci } 14348c2ecf20Sopenharmony_ci break; 14358c2ecf20Sopenharmony_ci case AUDIO_MONO_LEFT: 14368c2ecf20Sopenharmony_ci ret = audcom(av7110, AUDIO_CMD_MONO_L); 14378c2ecf20Sopenharmony_ci if (!ret) { 14388c2ecf20Sopenharmony_ci if (av7110->adac_type == DVB_ADAC_CRYSTAL) 14398c2ecf20Sopenharmony_ci i2c_writereg(av7110, 0x20, 0x02, 0x4a); 14408c2ecf20Sopenharmony_ci else if (av7110->adac_type == DVB_ADAC_MSP34x5) 14418c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200); 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci break; 14448c2ecf20Sopenharmony_ci case AUDIO_MONO_RIGHT: 14458c2ecf20Sopenharmony_ci ret = audcom(av7110, AUDIO_CMD_MONO_R); 14468c2ecf20Sopenharmony_ci if (!ret) { 14478c2ecf20Sopenharmony_ci if (av7110->adac_type == DVB_ADAC_CRYSTAL) 14488c2ecf20Sopenharmony_ci i2c_writereg(av7110, 0x20, 0x02, 0x45); 14498c2ecf20Sopenharmony_ci else if (av7110->adac_type == DVB_ADAC_MSP34x5) 14508c2ecf20Sopenharmony_ci msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210); 14518c2ecf20Sopenharmony_ci } 14528c2ecf20Sopenharmony_ci break; 14538c2ecf20Sopenharmony_ci default: 14548c2ecf20Sopenharmony_ci ret = -EINVAL; 14558c2ecf20Sopenharmony_ci break; 14568c2ecf20Sopenharmony_ci } 14578c2ecf20Sopenharmony_ci break; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci case AUDIO_GET_STATUS: 14608c2ecf20Sopenharmony_ci memcpy(parg, &av7110->audiostate, sizeof(struct audio_status)); 14618c2ecf20Sopenharmony_ci break; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci case AUDIO_GET_CAPABILITIES: 14648c2ecf20Sopenharmony_ci if (FW_VERSION(av7110->arm_app) < 0x2621) 14658c2ecf20Sopenharmony_ci *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2; 14668c2ecf20Sopenharmony_ci else 14678c2ecf20Sopenharmony_ci *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 | 14688c2ecf20Sopenharmony_ci AUDIO_CAP_MP1 | AUDIO_CAP_MP2; 14698c2ecf20Sopenharmony_ci break; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci case AUDIO_CLEAR_BUFFER: 14728c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout); 14738c2ecf20Sopenharmony_ci av7110_ipack_reset(&av7110->ipack[0]); 14748c2ecf20Sopenharmony_ci if (av7110->playing == RP_AV) 14758c2ecf20Sopenharmony_ci ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, 14768c2ecf20Sopenharmony_ci __Play, 2, AV_PES, 0); 14778c2ecf20Sopenharmony_ci break; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci case AUDIO_SET_ID: 14808c2ecf20Sopenharmony_ci break; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci case AUDIO_SET_MIXER: 14838c2ecf20Sopenharmony_ci { 14848c2ecf20Sopenharmony_ci struct audio_mixer *amix = (struct audio_mixer *)parg; 14858c2ecf20Sopenharmony_ci ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right); 14868c2ecf20Sopenharmony_ci break; 14878c2ecf20Sopenharmony_ci } 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci case AUDIO_SET_STREAMTYPE: 14908c2ecf20Sopenharmony_ci break; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci default: 14938c2ecf20Sopenharmony_ci ret = -ENOIOCTLCMD; 14948c2ecf20Sopenharmony_ci } 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci mutex_unlock(&av7110->ioctl_mutex); 14978c2ecf20Sopenharmony_ci return ret; 14988c2ecf20Sopenharmony_ci} 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_cistatic int dvb_video_open(struct inode *inode, struct file *file) 15028c2ecf20Sopenharmony_ci{ 15038c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 15048c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 15058c2ecf20Sopenharmony_ci int err; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci if ((err = dvb_generic_open(inode, file)) < 0) 15108c2ecf20Sopenharmony_ci return err; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if ((file->f_flags & O_ACCMODE) != O_RDONLY) { 15138c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout); 15148c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); 15158c2ecf20Sopenharmony_ci av7110->video_blank = 1; 15168c2ecf20Sopenharmony_ci av7110->audiostate.AV_sync_state = 1; 15178c2ecf20Sopenharmony_ci av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci /* empty event queue */ 15208c2ecf20Sopenharmony_ci av7110->video_events.eventr = av7110->video_events.eventw = 0; 15218c2ecf20Sopenharmony_ci } 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci return 0; 15248c2ecf20Sopenharmony_ci} 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_cistatic int dvb_video_release(struct inode *inode, struct file *file) 15278c2ecf20Sopenharmony_ci{ 15288c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 15298c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci if ((file->f_flags & O_ACCMODE) != O_RDONLY) { 15348c2ecf20Sopenharmony_ci av7110_av_stop(av7110, RP_VIDEO); 15358c2ecf20Sopenharmony_ci } 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci return dvb_generic_release(inode, file); 15388c2ecf20Sopenharmony_ci} 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_cistatic int dvb_audio_open(struct inode *inode, struct file *file) 15418c2ecf20Sopenharmony_ci{ 15428c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 15438c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 15448c2ecf20Sopenharmony_ci int err = dvb_generic_open(inode, file); 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci if (err < 0) 15498c2ecf20Sopenharmony_ci return err; 15508c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout); 15518c2ecf20Sopenharmony_ci av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX; 15528c2ecf20Sopenharmony_ci return 0; 15538c2ecf20Sopenharmony_ci} 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_cistatic int dvb_audio_release(struct inode *inode, struct file *file) 15568c2ecf20Sopenharmony_ci{ 15578c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 15588c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci dprintk(2, "av7110:%p, \n", av7110); 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci av7110_av_stop(av7110, RP_AUDIO); 15638c2ecf20Sopenharmony_ci return dvb_generic_release(inode, file); 15648c2ecf20Sopenharmony_ci} 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci/****************************************************************************** 15698c2ecf20Sopenharmony_ci * driver registration 15708c2ecf20Sopenharmony_ci ******************************************************************************/ 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_cistatic const struct file_operations dvb_video_fops = { 15738c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 15748c2ecf20Sopenharmony_ci .write = dvb_video_write, 15758c2ecf20Sopenharmony_ci .unlocked_ioctl = dvb_generic_ioctl, 15768c2ecf20Sopenharmony_ci .compat_ioctl = dvb_generic_ioctl, 15778c2ecf20Sopenharmony_ci .open = dvb_video_open, 15788c2ecf20Sopenharmony_ci .release = dvb_video_release, 15798c2ecf20Sopenharmony_ci .poll = dvb_video_poll, 15808c2ecf20Sopenharmony_ci .llseek = noop_llseek, 15818c2ecf20Sopenharmony_ci}; 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_cistatic struct dvb_device dvbdev_video = { 15848c2ecf20Sopenharmony_ci .priv = NULL, 15858c2ecf20Sopenharmony_ci .users = 6, 15868c2ecf20Sopenharmony_ci .readers = 5, /* arbitrary */ 15878c2ecf20Sopenharmony_ci .writers = 1, 15888c2ecf20Sopenharmony_ci .fops = &dvb_video_fops, 15898c2ecf20Sopenharmony_ci .kernel_ioctl = dvb_video_ioctl, 15908c2ecf20Sopenharmony_ci}; 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_cistatic const struct file_operations dvb_audio_fops = { 15938c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 15948c2ecf20Sopenharmony_ci .write = dvb_audio_write, 15958c2ecf20Sopenharmony_ci .unlocked_ioctl = dvb_generic_ioctl, 15968c2ecf20Sopenharmony_ci .compat_ioctl = dvb_generic_ioctl, 15978c2ecf20Sopenharmony_ci .open = dvb_audio_open, 15988c2ecf20Sopenharmony_ci .release = dvb_audio_release, 15998c2ecf20Sopenharmony_ci .poll = dvb_audio_poll, 16008c2ecf20Sopenharmony_ci .llseek = noop_llseek, 16018c2ecf20Sopenharmony_ci}; 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_cistatic struct dvb_device dvbdev_audio = { 16048c2ecf20Sopenharmony_ci .priv = NULL, 16058c2ecf20Sopenharmony_ci .users = 1, 16068c2ecf20Sopenharmony_ci .writers = 1, 16078c2ecf20Sopenharmony_ci .fops = &dvb_audio_fops, 16088c2ecf20Sopenharmony_ci .kernel_ioctl = dvb_audio_ioctl, 16098c2ecf20Sopenharmony_ci}; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ciint av7110_av_register(struct av7110 *av7110) 16138c2ecf20Sopenharmony_ci{ 16148c2ecf20Sopenharmony_ci av7110->audiostate.AV_sync_state = 0; 16158c2ecf20Sopenharmony_ci av7110->audiostate.mute_state = 0; 16168c2ecf20Sopenharmony_ci av7110->audiostate.play_state = AUDIO_STOPPED; 16178c2ecf20Sopenharmony_ci av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX; 16188c2ecf20Sopenharmony_ci av7110->audiostate.channel_select = AUDIO_STEREO; 16198c2ecf20Sopenharmony_ci av7110->audiostate.bypass_mode = 0; 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci av7110->videostate.video_blank = 0; 16228c2ecf20Sopenharmony_ci av7110->videostate.play_state = VIDEO_STOPPED; 16238c2ecf20Sopenharmony_ci av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX; 16248c2ecf20Sopenharmony_ci av7110->videostate.video_format = VIDEO_FORMAT_4_3; 16258c2ecf20Sopenharmony_ci av7110->videostate.display_format = VIDEO_LETTER_BOX; 16268c2ecf20Sopenharmony_ci av7110->display_ar = VIDEO_FORMAT_4_3; 16278c2ecf20Sopenharmony_ci av7110->display_panscan = VID_VC_AND_PS_PREF; 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci init_waitqueue_head(&av7110->video_events.wait_queue); 16308c2ecf20Sopenharmony_ci spin_lock_init(&av7110->video_events.lock); 16318c2ecf20Sopenharmony_ci av7110->video_events.eventw = av7110->video_events.eventr = 0; 16328c2ecf20Sopenharmony_ci av7110->video_events.overflow = 0; 16338c2ecf20Sopenharmony_ci memset(&av7110->video_size, 0, sizeof (video_size_t)); 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev, 16368c2ecf20Sopenharmony_ci &dvbdev_video, av7110, DVB_DEVICE_VIDEO, 0); 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev, 16398c2ecf20Sopenharmony_ci &dvbdev_audio, av7110, DVB_DEVICE_AUDIO, 0); 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci return 0; 16428c2ecf20Sopenharmony_ci} 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_civoid av7110_av_unregister(struct av7110 *av7110) 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci dvb_unregister_device(av7110->audio_dev); 16478c2ecf20Sopenharmony_ci dvb_unregister_device(av7110->video_dev); 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ciint av7110_av_init(struct av7110 *av7110) 16518c2ecf20Sopenharmony_ci{ 16528c2ecf20Sopenharmony_ci void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb }; 16538c2ecf20Sopenharmony_ci int i, ret; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 16568c2ecf20Sopenharmony_ci struct ipack *ipack = av7110->ipack + i; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci ret = av7110_ipack_init(ipack, IPACKS, play[i]); 16598c2ecf20Sopenharmony_ci if (ret < 0) { 16608c2ecf20Sopenharmony_ci if (i) 16618c2ecf20Sopenharmony_ci av7110_ipack_free(--ipack); 16628c2ecf20Sopenharmony_ci goto out; 16638c2ecf20Sopenharmony_ci } 16648c2ecf20Sopenharmony_ci ipack->data = av7110; 16658c2ecf20Sopenharmony_ci } 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci dvb_ringbuffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN); 16688c2ecf20Sopenharmony_ci dvb_ringbuffer_init(&av7110->aout, av7110->iobuf + AVOUTLEN, AOUTLEN); 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci av7110->kbuf[0] = (u8 *)(av7110->iobuf + AVOUTLEN + AOUTLEN + BMPLEN); 16718c2ecf20Sopenharmony_ci av7110->kbuf[1] = av7110->kbuf[0] + 2 * IPACKS; 16728c2ecf20Sopenharmony_ciout: 16738c2ecf20Sopenharmony_ci return ret; 16748c2ecf20Sopenharmony_ci} 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_civoid av7110_av_exit(struct av7110 *av7110) 16778c2ecf20Sopenharmony_ci{ 16788c2ecf20Sopenharmony_ci av7110_ipack_free(&av7110->ipack[0]); 16798c2ecf20Sopenharmony_ci av7110_ipack_free(&av7110->ipack[1]); 16808c2ecf20Sopenharmony_ci} 1681