cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ivtv-streams.c (30713B)


      1/*
      2    init/start/stop/exit stream functions
      3    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
      4    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
      5    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
      6
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 2 of the License, or
     10    (at your option) any later version.
     11
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     20 */
     21
     22/* License: GPL
     23 * Author: Kevin Thayer <nufan_wfk at yahoo dot com>
     24 *
     25 * This file will hold API related functions, both internal (firmware api)
     26 * and external (v4l2, etc)
     27 *
     28 * -----
     29 * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
     30 *                      and Takeru KOMORIYA<komoriya@paken.org>
     31 *
     32 * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
     33 *                using information provided by Jiun-Kuei Jung @ AVerMedia.
     34 */
     35
     36#include "ivtv-driver.h"
     37#include "ivtv-fileops.h"
     38#include "ivtv-queue.h"
     39#include "ivtv-mailbox.h"
     40#include "ivtv-ioctl.h"
     41#include "ivtv-irq.h"
     42#include "ivtv-yuv.h"
     43#include "ivtv-cards.h"
     44#include "ivtv-streams.h"
     45#include "ivtv-firmware.h"
     46#include <media/v4l2-event.h>
     47
     48static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
     49	.owner = THIS_MODULE,
     50	.read = ivtv_v4l2_read,
     51	.write = ivtv_v4l2_write,
     52	.open = ivtv_v4l2_open,
     53	.unlocked_ioctl = video_ioctl2,
     54#ifdef CONFIG_COMPAT
     55	.compat_ioctl32 = video_ioctl2, /* for ivtv_default() */
     56#endif
     57	.release = ivtv_v4l2_close,
     58	.poll = ivtv_v4l2_enc_poll,
     59};
     60
     61static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
     62	.owner = THIS_MODULE,
     63	.read = ivtv_v4l2_read,
     64	.write = ivtv_v4l2_write,
     65	.open = ivtv_v4l2_open,
     66	.unlocked_ioctl = video_ioctl2,
     67#ifdef CONFIG_COMPAT
     68	.compat_ioctl32 = video_ioctl2, /* for ivtv_default() */
     69#endif
     70	.release = ivtv_v4l2_close,
     71	.poll = ivtv_v4l2_dec_poll,
     72};
     73
     74static const struct v4l2_file_operations ivtv_v4l2_radio_fops = {
     75	.owner = THIS_MODULE,
     76	.open = ivtv_v4l2_open,
     77	.unlocked_ioctl = video_ioctl2,
     78#ifdef CONFIG_COMPAT
     79	.compat_ioctl32 = video_ioctl2, /* for ivtv_default() */
     80#endif
     81	.release = ivtv_v4l2_close,
     82	.poll = ivtv_v4l2_enc_poll,
     83};
     84
     85#define IVTV_V4L2_DEC_MPG_OFFSET  16	/* offset from 0 to register decoder mpg v4l2 minors on */
     86#define IVTV_V4L2_ENC_PCM_OFFSET  24	/* offset from 0 to register pcm v4l2 minors on */
     87#define IVTV_V4L2_ENC_YUV_OFFSET  32	/* offset from 0 to register yuv v4l2 minors on */
     88#define IVTV_V4L2_DEC_YUV_OFFSET  48	/* offset from 0 to register decoder yuv v4l2 minors on */
     89#define IVTV_V4L2_DEC_VBI_OFFSET   8	/* offset from 0 to register decoder vbi input v4l2 minors on */
     90#define IVTV_V4L2_DEC_VOUT_OFFSET 16	/* offset from 0 to register vbi output v4l2 minors on */
     91
     92static struct {
     93	const char *name;
     94	int vfl_type;
     95	int num_offset;
     96	int dma, pio;
     97	u32 v4l2_caps;
     98	const struct v4l2_file_operations *fops;
     99} ivtv_stream_info[] = {
    100	{	/* IVTV_ENC_STREAM_TYPE_MPG */
    101		"encoder MPG",
    102		VFL_TYPE_VIDEO, 0,
    103		DMA_FROM_DEVICE, 0,
    104		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
    105			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
    106		&ivtv_v4l2_enc_fops
    107	},
    108	{	/* IVTV_ENC_STREAM_TYPE_YUV */
    109		"encoder YUV",
    110		VFL_TYPE_VIDEO, IVTV_V4L2_ENC_YUV_OFFSET,
    111		DMA_FROM_DEVICE, 0,
    112		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
    113			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
    114		&ivtv_v4l2_enc_fops
    115	},
    116	{	/* IVTV_ENC_STREAM_TYPE_VBI */
    117		"encoder VBI",
    118		VFL_TYPE_VBI, 0,
    119		DMA_FROM_DEVICE, 0,
    120		V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER |
    121			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
    122		&ivtv_v4l2_enc_fops
    123	},
    124	{	/* IVTV_ENC_STREAM_TYPE_PCM */
    125		"encoder PCM",
    126		VFL_TYPE_VIDEO, IVTV_V4L2_ENC_PCM_OFFSET,
    127		DMA_FROM_DEVICE, 0,
    128		V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
    129		&ivtv_v4l2_enc_fops
    130	},
    131	{	/* IVTV_ENC_STREAM_TYPE_RAD */
    132		"encoder radio",
    133		VFL_TYPE_RADIO, 0,
    134		DMA_NONE, 1,
    135		V4L2_CAP_RADIO | V4L2_CAP_TUNER,
    136		&ivtv_v4l2_radio_fops
    137	},
    138	{	/* IVTV_DEC_STREAM_TYPE_MPG */
    139		"decoder MPG",
    140		VFL_TYPE_VIDEO, IVTV_V4L2_DEC_MPG_OFFSET,
    141		DMA_TO_DEVICE, 0,
    142		V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
    143		&ivtv_v4l2_dec_fops
    144	},
    145	{	/* IVTV_DEC_STREAM_TYPE_VBI */
    146		"decoder VBI",
    147		VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET,
    148		DMA_NONE, 1,
    149		V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE,
    150		&ivtv_v4l2_enc_fops
    151	},
    152	{	/* IVTV_DEC_STREAM_TYPE_VOUT */
    153		"decoder VOUT",
    154		VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET,
    155		DMA_NONE, 1,
    156		V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
    157		&ivtv_v4l2_dec_fops
    158	},
    159	{	/* IVTV_DEC_STREAM_TYPE_YUV */
    160		"decoder YUV",
    161		VFL_TYPE_VIDEO, IVTV_V4L2_DEC_YUV_OFFSET,
    162		DMA_TO_DEVICE, 0,
    163		V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
    164		&ivtv_v4l2_dec_fops
    165	}
    166};
    167
    168static void ivtv_stream_init(struct ivtv *itv, int type)
    169{
    170	struct ivtv_stream *s = &itv->streams[type];
    171
    172	/* we need to keep vdev, so restore it afterwards */
    173	memset(s, 0, sizeof(*s));
    174
    175	/* initialize ivtv_stream fields */
    176	s->itv = itv;
    177	s->type = type;
    178	s->name = ivtv_stream_info[type].name;
    179	s->vdev.device_caps = ivtv_stream_info[type].v4l2_caps;
    180
    181	if (ivtv_stream_info[type].pio)
    182		s->dma = DMA_NONE;
    183	else
    184		s->dma = ivtv_stream_info[type].dma;
    185	s->buf_size = itv->stream_buf_size[type];
    186	if (s->buf_size)
    187		s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
    188	spin_lock_init(&s->qlock);
    189	init_waitqueue_head(&s->waitq);
    190	s->sg_handle = IVTV_DMA_UNMAPPED;
    191	ivtv_queue_init(&s->q_free);
    192	ivtv_queue_init(&s->q_full);
    193	ivtv_queue_init(&s->q_dma);
    194	ivtv_queue_init(&s->q_predma);
    195	ivtv_queue_init(&s->q_io);
    196}
    197
    198static int ivtv_prep_dev(struct ivtv *itv, int type)
    199{
    200	struct ivtv_stream *s = &itv->streams[type];
    201	int num_offset = ivtv_stream_info[type].num_offset;
    202	int num = itv->instance + ivtv_first_minor + num_offset;
    203
    204	/* These four fields are always initialized. If vdev.v4l2_dev == NULL, then
    205	   this stream is not in use. In that case no other fields but these
    206	   four can be used. */
    207	s->vdev.v4l2_dev = NULL;
    208	s->itv = itv;
    209	s->type = type;
    210	s->name = ivtv_stream_info[type].name;
    211
    212	/* Check whether the radio is supported */
    213	if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO))
    214		return 0;
    215	if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
    216		return 0;
    217
    218	/* User explicitly selected 0 buffers for these streams, so don't
    219	   create them. */
    220	if (ivtv_stream_info[type].dma != DMA_NONE &&
    221	    itv->options.kilobytes[type] == 0) {
    222		IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name);
    223		return 0;
    224	}
    225
    226	ivtv_stream_init(itv, type);
    227
    228	snprintf(s->vdev.name, sizeof(s->vdev.name), "%s %s",
    229			itv->v4l2_dev.name, s->name);
    230
    231	s->vdev.num = num;
    232	s->vdev.v4l2_dev = &itv->v4l2_dev;
    233	if (ivtv_stream_info[type].v4l2_caps &
    234			(V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT))
    235		s->vdev.vfl_dir = VFL_DIR_TX;
    236	s->vdev.fops = ivtv_stream_info[type].fops;
    237	s->vdev.ctrl_handler = itv->v4l2_dev.ctrl_handler;
    238	s->vdev.release = video_device_release_empty;
    239	s->vdev.tvnorms = V4L2_STD_ALL;
    240	s->vdev.lock = &itv->serialize_lock;
    241	if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
    242		v4l2_disable_ioctl(&s->vdev, VIDIOC_S_AUDIO);
    243		v4l2_disable_ioctl(&s->vdev, VIDIOC_G_AUDIO);
    244		v4l2_disable_ioctl(&s->vdev, VIDIOC_ENUMAUDIO);
    245		v4l2_disable_ioctl(&s->vdev, VIDIOC_ENUMINPUT);
    246		v4l2_disable_ioctl(&s->vdev, VIDIOC_S_INPUT);
    247		v4l2_disable_ioctl(&s->vdev, VIDIOC_G_INPUT);
    248		v4l2_disable_ioctl(&s->vdev, VIDIOC_S_FREQUENCY);
    249		v4l2_disable_ioctl(&s->vdev, VIDIOC_G_FREQUENCY);
    250		v4l2_disable_ioctl(&s->vdev, VIDIOC_S_TUNER);
    251		v4l2_disable_ioctl(&s->vdev, VIDIOC_G_TUNER);
    252		v4l2_disable_ioctl(&s->vdev, VIDIOC_S_STD);
    253	}
    254	ivtv_set_funcs(&s->vdev);
    255	return 0;
    256}
    257
    258/* Initialize v4l2 variables and prepare v4l2 devices */
    259int ivtv_streams_setup(struct ivtv *itv)
    260{
    261	int type;
    262
    263	/* Setup V4L2 Devices */
    264	for (type = 0; type < IVTV_MAX_STREAMS; type++) {
    265		/* Prepare device */
    266		if (ivtv_prep_dev(itv, type))
    267			break;
    268
    269		if (itv->streams[type].vdev.v4l2_dev == NULL)
    270			continue;
    271
    272		/* Allocate Stream */
    273		if (ivtv_stream_alloc(&itv->streams[type]))
    274			break;
    275	}
    276	if (type == IVTV_MAX_STREAMS)
    277		return 0;
    278
    279	/* One or more streams could not be initialized. Clean 'em all up. */
    280	ivtv_streams_cleanup(itv);
    281	return -ENOMEM;
    282}
    283
    284static int ivtv_reg_dev(struct ivtv *itv, int type)
    285{
    286	struct ivtv_stream *s = &itv->streams[type];
    287	int vfl_type = ivtv_stream_info[type].vfl_type;
    288	const char *name;
    289	int num;
    290
    291	if (s->vdev.v4l2_dev == NULL)
    292		return 0;
    293
    294	num = s->vdev.num;
    295	/* card number + user defined offset + device offset */
    296	if (type != IVTV_ENC_STREAM_TYPE_MPG) {
    297		struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
    298
    299		if (s_mpg->vdev.v4l2_dev)
    300			num = s_mpg->vdev.num + ivtv_stream_info[type].num_offset;
    301	}
    302	if (itv->osd_video_pbase && (type == IVTV_DEC_STREAM_TYPE_YUV ||
    303				     type == IVTV_DEC_STREAM_TYPE_MPG)) {
    304		s->vdev.device_caps |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
    305		itv->v4l2_cap |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
    306	}
    307	video_set_drvdata(&s->vdev, s);
    308
    309	/* Register device. First try the desired minor, then any free one. */
    310	if (video_register_device_no_warn(&s->vdev, vfl_type, num)) {
    311		IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
    312				s->name, num);
    313		return -ENOMEM;
    314	}
    315	name = video_device_node_name(&s->vdev);
    316
    317	switch (vfl_type) {
    318	case VFL_TYPE_VIDEO:
    319		IVTV_INFO("Registered device %s for %s (%d kB)\n",
    320			name, s->name, itv->options.kilobytes[type]);
    321		break;
    322	case VFL_TYPE_RADIO:
    323		IVTV_INFO("Registered device %s for %s\n",
    324			name, s->name);
    325		break;
    326	case VFL_TYPE_VBI:
    327		if (itv->options.kilobytes[type])
    328			IVTV_INFO("Registered device %s for %s (%d kB)\n",
    329				name, s->name, itv->options.kilobytes[type]);
    330		else
    331			IVTV_INFO("Registered device %s for %s\n",
    332				name, s->name);
    333		break;
    334	}
    335	return 0;
    336}
    337
    338/* Register v4l2 devices */
    339int ivtv_streams_register(struct ivtv *itv)
    340{
    341	int type;
    342	int err = 0;
    343
    344	/* Register V4L2 devices */
    345	for (type = 0; type < IVTV_MAX_STREAMS; type++)
    346		err |= ivtv_reg_dev(itv, type);
    347
    348	if (err == 0)
    349		return 0;
    350
    351	/* One or more streams could not be initialized. Clean 'em all up. */
    352	ivtv_streams_cleanup(itv);
    353	return -ENOMEM;
    354}
    355
    356/* Unregister v4l2 devices */
    357void ivtv_streams_cleanup(struct ivtv *itv)
    358{
    359	int type;
    360
    361	/* Teardown all streams */
    362	for (type = 0; type < IVTV_MAX_STREAMS; type++) {
    363		struct video_device *vdev = &itv->streams[type].vdev;
    364
    365		if (vdev->v4l2_dev == NULL)
    366			continue;
    367
    368		video_unregister_device(vdev);
    369		ivtv_stream_free(&itv->streams[type]);
    370		itv->streams[type].vdev.v4l2_dev = NULL;
    371	}
    372}
    373
    374static void ivtv_vbi_setup(struct ivtv *itv)
    375{
    376	int raw = ivtv_raw_vbi(itv);
    377	u32 data[CX2341X_MBOX_MAX_DATA];
    378	int lines;
    379	int i;
    380
    381	/* Reset VBI */
    382	ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
    383
    384	/* setup VBI registers */
    385	if (raw)
    386		v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi);
    387	else
    388		v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced);
    389
    390	/* determine number of lines and total number of VBI bytes.
    391	   A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
    392	   The '- 1' byte is probably an unused U or V byte. Or something...
    393	   A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
    394	   header, 42 data bytes + checksum (to be confirmed) */
    395	if (raw) {
    396		lines = itv->vbi.count * 2;
    397	} else {
    398		lines = itv->is_60hz ? 24 : 38;
    399		if (itv->is_60hz && (itv->hw_flags & IVTV_HW_CX25840))
    400			lines += 2;
    401	}
    402
    403	itv->vbi.enc_size = lines * (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
    404
    405	/* Note: sliced vs raw flag doesn't seem to have any effect
    406	   TODO: check mode (0x02) value with older ivtv versions. */
    407	data[0] = raw | 0x02 | (0xbd << 8);
    408
    409	/* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */
    410	data[1] = 1;
    411	/* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */
    412	data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size);
    413	/* The start/stop codes determine which VBI lines end up in the raw VBI data area.
    414	   The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line
    415	   is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video)
    416	   code. These values for raw VBI are obtained from a driver disassembly. The sliced
    417	   start/stop codes was deduced from this, but they do not appear in the driver.
    418	   Other code pairs that I found are: 0x250E6249/0x13545454 and 0x25256262/0x38137F54.
    419	   However, I have no idea what these values are for. */
    420	if (itv->hw_flags & IVTV_HW_CX25840) {
    421		/* Setup VBI for the cx25840 digitizer */
    422		if (raw) {
    423			data[3] = 0x20602060;
    424			data[4] = 0x30703070;
    425		} else {
    426			data[3] = 0xB0F0B0F0;
    427			data[4] = 0xA0E0A0E0;
    428		}
    429		/* Lines per frame */
    430		data[5] = lines;
    431		/* bytes per line */
    432		data[6] = (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
    433	} else {
    434		/* Setup VBI for the saa7115 digitizer */
    435		if (raw) {
    436			data[3] = 0x25256262;
    437			data[4] = 0x387F7F7F;
    438		} else {
    439			data[3] = 0xABABECEC;
    440			data[4] = 0xB6F1F1F1;
    441		}
    442		/* Lines per frame */
    443		data[5] = lines;
    444		/* bytes per line */
    445		data[6] = itv->vbi.enc_size / lines;
    446	}
    447
    448	IVTV_DEBUG_INFO(
    449		"Setup VBI API header 0x%08x pkts %d buffs %d ln %d sz %d\n",
    450			data[0], data[1], data[2], data[5], data[6]);
    451
    452	ivtv_api(itv, CX2341X_ENC_SET_VBI_CONFIG, 7, data);
    453
    454	/* returns the VBI encoder memory area. */
    455	itv->vbi.enc_start = data[2];
    456	itv->vbi.fpi = data[0];
    457	if (!itv->vbi.fpi)
    458		itv->vbi.fpi = 1;
    459
    460	IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d\n",
    461		itv->vbi.enc_start, data[1], itv->vbi.fpi);
    462
    463	/* select VBI lines.
    464	   Note that the sliced argument seems to have no effect. */
    465	for (i = 2; i <= 24; i++) {
    466		int valid;
    467
    468		if (itv->is_60hz) {
    469			valid = i >= 10 && i < 22;
    470		} else {
    471			valid = i >= 6 && i < 24;
    472		}
    473		ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, i - 1,
    474				valid, 0 , 0, 0);
    475		ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, (i - 1) | 0x80000000,
    476				valid, 0, 0, 0);
    477	}
    478
    479	/* Remaining VBI questions:
    480	   - Is it possible to select particular VBI lines only for inclusion in the MPEG
    481	   stream? Currently you can only get the first X lines.
    482	   - Is mixed raw and sliced VBI possible?
    483	   - What's the meaning of the raw/sliced flag?
    484	   - What's the meaning of params 2, 3 & 4 of the Select VBI command? */
    485}
    486
    487int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
    488{
    489	u32 data[CX2341X_MBOX_MAX_DATA];
    490	struct ivtv *itv = s->itv;
    491	int captype = 0, subtype = 0;
    492	int enable_passthrough = 0;
    493
    494	if (s->vdev.v4l2_dev == NULL)
    495		return -EINVAL;
    496
    497	IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
    498
    499	switch (s->type) {
    500	case IVTV_ENC_STREAM_TYPE_MPG:
    501		captype = 0;
    502		subtype = 3;
    503
    504		/* Stop Passthrough */
    505		if (itv->output_mode == OUT_PASSTHROUGH) {
    506			ivtv_passthrough_mode(itv, 0);
    507			enable_passthrough = 1;
    508		}
    509		itv->mpg_data_received = itv->vbi_data_inserted = 0;
    510		itv->dualwatch_jiffies = jiffies;
    511		itv->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
    512		itv->search_pack_header = 0;
    513		break;
    514
    515	case IVTV_ENC_STREAM_TYPE_YUV:
    516		if (itv->output_mode == OUT_PASSTHROUGH) {
    517			captype = 2;
    518			subtype = 11;	/* video+audio+decoder */
    519			break;
    520		}
    521		captype = 1;
    522		subtype = 1;
    523		break;
    524	case IVTV_ENC_STREAM_TYPE_PCM:
    525		captype = 1;
    526		subtype = 2;
    527		break;
    528	case IVTV_ENC_STREAM_TYPE_VBI:
    529		captype = 1;
    530		subtype = 4;
    531
    532		itv->vbi.frame = 0;
    533		itv->vbi.inserted_frame = 0;
    534		memset(itv->vbi.sliced_mpeg_size,
    535			0, sizeof(itv->vbi.sliced_mpeg_size));
    536		break;
    537	default:
    538		return -EINVAL;
    539	}
    540	s->subtype = subtype;
    541	s->buffers_stolen = 0;
    542
    543	/* Clear Streamoff flags in case left from last capture */
    544	clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
    545
    546	if (atomic_read(&itv->capturing) == 0) {
    547		int digitizer;
    548
    549		/* Always use frame based mode. Experiments have demonstrated that byte
    550		   stream based mode results in dropped frames and corruption. Not often,
    551		   but occasionally. Many thanks go to Leonard Orb who spent a lot of
    552		   effort and time trying to trace the cause of the drop outs. */
    553		/* 1 frame per DMA */
    554		/*ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 128, 0); */
    555		ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 1, 1);
    556
    557		/* Stuff from Windows, we don't know what it is */
    558		ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, 0);
    559		/* According to the docs, this should be correct. However, this is
    560		   untested. I don't dare enable this without having tested it.
    561		   Only very few old cards actually have this hardware combination.
    562		ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1,
    563			((itv->hw_flags & IVTV_HW_SAA7114) && itv->is_60hz) ? 10001 : 0);
    564		*/
    565		ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 3, !itv->has_cx23415);
    566		ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 8, 0);
    567		ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 4, 1);
    568		ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
    569
    570		/* assign placeholder */
    571		ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12,
    572			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    573
    574		if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X))
    575		    digitizer = 0xF1;
    576		else if (itv->card->hw_all & IVTV_HW_SAA7114)
    577		    digitizer = 0xEF;
    578		else /* cx25840 */
    579		    digitizer = 0x140;
    580
    581		ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, digitizer, digitizer);
    582
    583		/* Setup VBI */
    584		if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) {
    585			ivtv_vbi_setup(itv);
    586		}
    587
    588		/* assign program index info. Mask 7: select I/P/B, Num_req: 400 max */
    589		ivtv_vapi_result(itv, data, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, 7, 400);
    590		itv->pgm_info_offset = data[0];
    591		itv->pgm_info_num = data[1];
    592		itv->pgm_info_write_idx = 0;
    593		itv->pgm_info_read_idx = 0;
    594
    595		IVTV_DEBUG_INFO("PGM Index at 0x%08x with %d elements\n",
    596				itv->pgm_info_offset, itv->pgm_info_num);
    597
    598		/* Setup API for Stream */
    599		cx2341x_handler_setup(&itv->cxhdl);
    600
    601		/* mute if capturing radio */
    602		if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
    603			ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
    604				1 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
    605	}
    606
    607	/* Vsync Setup */
    608	if (itv->has_cx23415 && !test_and_set_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
    609		/* event notification (on) */
    610		ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_ENC_VIM_RST, -1);
    611		ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
    612	}
    613
    614	if (atomic_read(&itv->capturing) == 0) {
    615		/* Clear all Pending Interrupts */
    616		ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
    617
    618		clear_bit(IVTV_F_I_EOS, &itv->i_flags);
    619
    620		cx2341x_handler_set_busy(&itv->cxhdl, 1);
    621
    622		/* Initialize Digitizer for Capture */
    623		/* Avoid tinny audio problem - ensure audio clocks are going */
    624		v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1);
    625		/* Avoid unpredictable PCI bus hang - disable video clocks */
    626		v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
    627		ivtv_msleep_timeout(300, 0);
    628		ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
    629		v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
    630	}
    631
    632	/* begin_capture */
    633	if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype))
    634	{
    635		IVTV_DEBUG_WARN( "Error starting capture!\n");
    636		return -EINVAL;
    637	}
    638
    639	/* Start Passthrough */
    640	if (enable_passthrough) {
    641		ivtv_passthrough_mode(itv, 1);
    642	}
    643
    644	if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
    645		ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
    646	else
    647		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
    648
    649	/* you're live! sit back and await interrupts :) */
    650	atomic_inc(&itv->capturing);
    651	return 0;
    652}
    653EXPORT_SYMBOL(ivtv_start_v4l2_encode_stream);
    654
    655static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
    656{
    657	u32 data[CX2341X_MBOX_MAX_DATA];
    658	struct ivtv *itv = s->itv;
    659	int datatype;
    660	u16 width;
    661	u16 height;
    662
    663	if (s->vdev.v4l2_dev == NULL)
    664		return -EINVAL;
    665
    666	IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
    667
    668	width = itv->cxhdl.width;
    669	height = itv->cxhdl.height;
    670
    671	/* set audio mode to left/stereo  for dual/stereo mode. */
    672	ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
    673
    674	/* set number of internal decoder buffers */
    675	ivtv_vapi(itv, CX2341X_DEC_SET_DISPLAY_BUFFERS, 1, 0);
    676
    677	/* prebuffering */
    678	ivtv_vapi(itv, CX2341X_DEC_SET_PREBUFFERING, 1, 1);
    679
    680	/* extract from user packets */
    681	ivtv_vapi_result(itv, data, CX2341X_DEC_EXTRACT_VBI, 1, 1);
    682	itv->vbi.dec_start = data[0];
    683
    684	IVTV_DEBUG_INFO("Decoder VBI RE-Insert start 0x%08x size 0x%08x\n",
    685		itv->vbi.dec_start, data[1]);
    686
    687	/* set decoder source settings */
    688	/* Data type: 0 = mpeg from host,
    689	   1 = yuv from encoder,
    690	   2 = yuv_from_host */
    691	switch (s->type) {
    692	case IVTV_DEC_STREAM_TYPE_YUV:
    693		if (itv->output_mode == OUT_PASSTHROUGH) {
    694			datatype = 1;
    695		} else {
    696			/* Fake size to avoid switching video standard */
    697			datatype = 2;
    698			width = 720;
    699			height = itv->is_out_50hz ? 576 : 480;
    700		}
    701		IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
    702		break;
    703	case IVTV_DEC_STREAM_TYPE_MPG:
    704	default:
    705		datatype = 0;
    706		break;
    707	}
    708	if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
    709			width, height, itv->cxhdl.audio_properties)) {
    710		IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
    711	}
    712
    713	/* Decoder sometimes dies here, so wait a moment */
    714	ivtv_msleep_timeout(10, 0);
    715
    716	/* Known failure point for firmware, so check */
    717	return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream");
    718}
    719
    720int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
    721{
    722	struct ivtv *itv = s->itv;
    723	int rc;
    724
    725	if (s->vdev.v4l2_dev == NULL)
    726		return -EINVAL;
    727
    728	if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags))
    729		return 0;	/* already started */
    730
    731	IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset);
    732
    733	rc = ivtv_setup_v4l2_decode_stream(s);
    734	if (rc < 0) {
    735		clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
    736		return rc;
    737	}
    738
    739	/* set dma size to 65536 bytes */
    740	ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536);
    741
    742	/* Clear Streamoff */
    743	clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
    744
    745	/* Zero out decoder counters */
    746	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[0]);
    747	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[1]);
    748	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[2]);
    749	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[3]);
    750	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]);
    751	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]);
    752	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]);
    753	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[3]);
    754
    755	/* turn on notification of dual/stereo mode change */
    756	ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
    757
    758	/* start playback */
    759	ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
    760
    761	/* Let things settle before we actually start */
    762	ivtv_msleep_timeout(10, 0);
    763
    764	/* Clear the following Interrupt mask bits for decoding */
    765	ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
    766	IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
    767
    768	/* you're live! sit back and await interrupts :) */
    769	atomic_inc(&itv->decoding);
    770	return 0;
    771}
    772
    773void ivtv_stop_all_captures(struct ivtv *itv)
    774{
    775	int i;
    776
    777	for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) {
    778		struct ivtv_stream *s = &itv->streams[i];
    779
    780		if (s->vdev.v4l2_dev == NULL)
    781			continue;
    782		if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
    783			ivtv_stop_v4l2_encode_stream(s, 0);
    784		}
    785	}
    786}
    787
    788int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
    789{
    790	struct ivtv *itv = s->itv;
    791	DECLARE_WAITQUEUE(wait, current);
    792	int cap_type;
    793	int stopmode;
    794
    795	if (s->vdev.v4l2_dev == NULL)
    796		return -EINVAL;
    797
    798	/* This function assumes that you are allowed to stop the capture
    799	   and that we are actually capturing */
    800
    801	IVTV_DEBUG_INFO("Stop Capture\n");
    802
    803	if (s->type == IVTV_DEC_STREAM_TYPE_VOUT)
    804		return 0;
    805	if (atomic_read(&itv->capturing) == 0)
    806		return 0;
    807
    808	switch (s->type) {
    809	case IVTV_ENC_STREAM_TYPE_YUV:
    810		cap_type = 1;
    811		break;
    812	case IVTV_ENC_STREAM_TYPE_PCM:
    813		cap_type = 1;
    814		break;
    815	case IVTV_ENC_STREAM_TYPE_VBI:
    816		cap_type = 1;
    817		break;
    818	case IVTV_ENC_STREAM_TYPE_MPG:
    819	default:
    820		cap_type = 0;
    821		break;
    822	}
    823
    824	/* Stop Capture Mode */
    825	if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
    826		stopmode = 0;
    827	} else {
    828		stopmode = 1;
    829	}
    830
    831	/* end_capture */
    832	/* when: 0 =  end of GOP  1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
    833	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);
    834
    835	if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
    836		if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
    837			/* only run these if we're shutting down the last cap */
    838			unsigned long duration;
    839			unsigned long then = jiffies;
    840
    841			add_wait_queue(&itv->eos_waitq, &wait);
    842
    843			set_current_state(TASK_INTERRUPTIBLE);
    844
    845			/* wait 2s for EOS interrupt */
    846			while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
    847				time_before(jiffies,
    848					    then + msecs_to_jiffies(2000))) {
    849				schedule_timeout(msecs_to_jiffies(10));
    850			}
    851
    852			/* To convert jiffies to ms, we must multiply by 1000
    853			 * and divide by HZ.  To avoid runtime division, we
    854			 * convert this to multiplication by 1000/HZ.
    855			 * Since integer division truncates, we get the best
    856			 * accuracy if we do a rounding calculation of the constant.
    857			 * Think of the case where HZ is 1024.
    858			 */
    859			duration = ((1000 + HZ / 2) / HZ) * (jiffies - then);
    860
    861			if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) {
    862				IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name);
    863				IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration);
    864			} else {
    865				IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
    866			}
    867			set_current_state(TASK_RUNNING);
    868			remove_wait_queue(&itv->eos_waitq, &wait);
    869			set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
    870		}
    871
    872		/* Handle any pending interrupts */
    873		ivtv_msleep_timeout(100, 0);
    874	}
    875
    876	atomic_dec(&itv->capturing);
    877
    878	/* Clear capture and no-read bits */
    879	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
    880
    881	if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
    882		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
    883
    884	if (atomic_read(&itv->capturing) > 0) {
    885		return 0;
    886	}
    887
    888	cx2341x_handler_set_busy(&itv->cxhdl, 0);
    889
    890	/* Set the following Interrupt mask bits for capture */
    891	ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
    892	del_timer(&itv->dma_timer);
    893
    894	/* event notification (off) */
    895	if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
    896		/* type: 0 = refresh */
    897		/* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
    898		ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
    899		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
    900	}
    901
    902	/* Raw-passthrough is implied on start. Make sure it's stopped so
    903	   the encoder will re-initialize when next started */
    904	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7);
    905
    906	wake_up(&s->waitq);
    907
    908	return 0;
    909}
    910EXPORT_SYMBOL(ivtv_stop_v4l2_encode_stream);
    911
    912int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
    913{
    914	static const struct v4l2_event ev = {
    915		.type = V4L2_EVENT_EOS,
    916	};
    917	struct ivtv *itv = s->itv;
    918
    919	if (s->vdev.v4l2_dev == NULL)
    920		return -EINVAL;
    921
    922	if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG)
    923		return -EINVAL;
    924
    925	if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
    926		return 0;
    927
    928	IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
    929
    930	/* Stop Decoder */
    931	if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) {
    932		u32 tmp = 0;
    933
    934		/* Wait until the decoder is no longer running */
    935		if (pts) {
    936			ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3,
    937				0, (u32)(pts & 0xffffffff), (u32)(pts >> 32));
    938		}
    939		while (1) {
    940			u32 data[CX2341X_MBOX_MAX_DATA];
    941			ivtv_vapi_result(itv, data, CX2341X_DEC_GET_XFER_INFO, 0);
    942			if (s->q_full.buffers + s->q_dma.buffers == 0) {
    943				if (tmp == data[3])
    944					break;
    945				tmp = data[3];
    946			}
    947			if (ivtv_msleep_timeout(100, 1))
    948				break;
    949		}
    950	}
    951	ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0);
    952
    953	/* turn off notification of dual/stereo mode change */
    954	ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
    955
    956	ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
    957	del_timer(&itv->dma_timer);
    958
    959	clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
    960	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
    961	ivtv_flush_queues(s);
    962
    963	/* decoder needs time to settle */
    964	ivtv_msleep_timeout(40, 0);
    965
    966	/* decrement decoding */
    967	atomic_dec(&itv->decoding);
    968
    969	set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
    970	wake_up(&itv->event_waitq);
    971	v4l2_event_queue(&s->vdev, &ev);
    972
    973	/* wake up wait queues */
    974	wake_up(&s->waitq);
    975
    976	return 0;
    977}
    978
    979int ivtv_passthrough_mode(struct ivtv *itv, int enable)
    980{
    981	struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV];
    982	struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
    983
    984	if (yuv_stream->vdev.v4l2_dev == NULL || dec_stream->vdev.v4l2_dev == NULL)
    985		return -EINVAL;
    986
    987	IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n");
    988
    989	/* Prevent others from starting/stopping streams while we
    990	   initiate/terminate passthrough mode */
    991	if (enable) {
    992		if (itv->output_mode == OUT_PASSTHROUGH) {
    993			return 0;
    994		}
    995		if (ivtv_set_output_mode(itv, OUT_PASSTHROUGH) != OUT_PASSTHROUGH)
    996			return -EBUSY;
    997
    998		/* Fully initialize stream, and then unflag init */
    999		set_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
   1000		set_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
   1001
   1002		/* Setup YUV Decoder */
   1003		ivtv_setup_v4l2_decode_stream(dec_stream);
   1004
   1005		/* Start Decoder */
   1006		ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1);
   1007		atomic_inc(&itv->decoding);
   1008
   1009		/* Setup capture if not already done */
   1010		if (atomic_read(&itv->capturing) == 0) {
   1011			cx2341x_handler_setup(&itv->cxhdl);
   1012			cx2341x_handler_set_busy(&itv->cxhdl, 1);
   1013		}
   1014
   1015		/* Start Passthrough Mode */
   1016		ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, 2, 11);
   1017		atomic_inc(&itv->capturing);
   1018		return 0;
   1019	}
   1020
   1021	if (itv->output_mode != OUT_PASSTHROUGH)
   1022		return 0;
   1023
   1024	/* Stop Passthrough Mode */
   1025	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 11);
   1026	ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, 1, 0, 0);
   1027
   1028	atomic_dec(&itv->capturing);
   1029	atomic_dec(&itv->decoding);
   1030	clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
   1031	clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
   1032	itv->output_mode = OUT_NONE;
   1033	if (atomic_read(&itv->capturing) == 0)
   1034		cx2341x_handler_set_busy(&itv->cxhdl, 0);
   1035
   1036	return 0;
   1037}