summaryrefslogtreecommitdiff
path: root/v4l_experimental/cx88-ivtv.c
blob: 8247d42864f50f3d6ee09f9008e61f2fdee75b23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
 * $Id: cx88-ivtv.c,v 1.1 2005/11/30 17:26:37 mchehab Exp $
 *
 *  IVTV API emulation for the "blackbird" reference design.
 *
 *    (c) 2005 Catalin Climov <catalin@climov.com>
 *
 *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include "compat.h"
#include <media/v4l2-common.h>
#include "cx88.h"

MODULE_DESCRIPTION("ivtv ioctl emulation module for blackbird TV cards");
MODULE_AUTHOR("Catalin Climov <catalin@climov.com>");
MODULE_LICENSE("GPL");

static unsigned int debug = 0;
module_param(debug,int,0644);
MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");

#define dprintk(level,fmt, arg...)	if (debug >= level) \
	printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)

static int (*prev_ioctl_hook)(struct inode *inode, struct file *file,
			      unsigned int cmd, void *arg);
static unsigned int (*prev_ioctl_translator)(unsigned int cmd);

/* --- IVTV data structs -------------------------------------------- */

struct ivtv_ioctl_codec {
	uint32_t aspect;
	uint32_t audio_bitmask;
	uint32_t bframes;
	uint32_t bitrate_mode;
	uint32_t bitrate;
	uint32_t bitrate_peak;
	uint32_t dnr_mode;
	uint32_t dnr_spatial;
	uint32_t dnr_temporal;
	uint32_t dnr_type;
	uint32_t framerate; /* read only, ignored on write */
	uint32_t framespergop;  /* read only, ignored on write */
	uint32_t gop_closure;
	uint32_t pulldown;
	uint32_t stream_type;
};

struct ivtv_sliced_vbi_format {
	unsigned long service_set;  /* one or more of the IVTV_SLICED_ defines */
	unsigned long packet_size;  /* the size in bytes of the ivtv_sliced_data packet */
	unsigned long io_size;      /* maximum number of bytes passed by one read() call */
	unsigned long reserved;
};

#define IVTV_IOC_G_CODEC           _IOR ('@', 48, struct ivtv_ioctl_codec)
#define IVTV_IOC_S_CODEC           _IOW ('@', 49, struct ivtv_ioctl_codec)
#define IVTV_IOC_S_VBI_MODE        _IOWR('@', 35, struct ivtv_sliced_vbi_format)
#define IVTV_IOC_G_VBI_MODE        _IOR ('@', 36, struct ivtv_sliced_vbi_format)
#define IVTV_IOC_S_VBI_EMBED       _IOW ('@', 54, int)

/* ------------------------------------------------------------------ */

static unsigned int ivtv_translate_ioctl(unsigned int cmd)
{
#if 0
	printk( KERN_INFO "ivtv_translate_ioctl\n" );
#endif
	switch( cmd )
	{
		case 0xFFEE7703: cmd = IVTV_IOC_G_CODEC; break;
		case 0xFFEE7704: cmd = IVTV_IOC_S_CODEC; break;
		case 0xFFEE7781: /*cmd = IVTV_IOC_PLAY; break;*/
		case 0xFFEE7782: /*cmd = IVTV_IOC_PAUSE; break;*/
		case 0xFFEE7783: /*cmd = IVTV_IOC_FRAMESYNC; break;*/
		case 0xFFEE7784: /*cmd = IVTV_IOC_GET_TIMING; break;*/
		case 0xFFEE7785: /*cmd = IVTV_IOC_S_SLOW_FAST; break;*/
		case 0xFFEE7786: /*cmd = IVTV_IOC_S_START_DECODE; break;*/
		case 0xFFEE7787: /*cmd = IVTV_IOC_S_STOP_DECODE; break;*/
		case 0xFFEE7789: /*cmd = IVTV_IOC_GET_FB; break;*/
			printk( KERN_INFO "IVTV: 0x%x\n", cmd );
	}
	return prev_ioctl_translator( cmd );
}

static int ivtv_do_ioctl(struct inode *inode, struct file *file,
			 unsigned int cmd, void *arg)
{
	struct cx8802_fh  *fh  = file->private_data;
	struct cx8802_dev *dev = fh->dev;
	/* struct cx88_core  *core = dev->core; */

	/* int err; */

	if (debug > 1)
		v4l_print_ioctl(dev->core->name,cmd);
#if 1
	printk( KERN_INFO "IVTV IOCTL: 0x%x\n", cmd );
	v4l_print_ioctl(dev->core->name,cmd);
#endif
	dprintk( 1, "IVTV IOCTL: 0x%x\n", cmd );

	switch (cmd) {

	/* --- IVTV emulation layer --------------------------- */
	case IVTV_IOC_S_CODEC:
		printk( KERN_INFO "IVTV_IOC_S_CODEC\n" );
	case IVTV_IOC_G_CODEC:
	{
		struct ivtv_ioctl_codec *codec = arg;
#if 1
		printk( KERN_INFO "IVTV_IOC_G/S_CODEC\n" );
		printk( KERN_INFO "CODEC: aspect: %d\n", codec->aspect );
		printk( KERN_INFO "CODEC: audio : %d\n", codec->audio_bitmask );
		printk( KERN_INFO "CODEC: bfrms : %d\n", codec->bframes );
		printk( KERN_INFO "CODEC: br_mod: %d\n", codec->bitrate_mode );
		printk( KERN_INFO "CODEC: btrate: %d\n", codec->bitrate );
		printk( KERN_INFO "CODEC: btr_pk: %d\n", codec->bitrate_peak );
		printk( KERN_INFO "CODEC: dnr_md: %d\n", codec->dnr_mode );
		printk( KERN_INFO "CODEC: dnr_sp: %d\n", codec->dnr_spatial );
		printk( KERN_INFO "CODEC: dnr_tp: %d\n", codec->dnr_temporal );
		printk( KERN_INFO "CODEC: dnr_ty: %d\n", codec->dnr_type );
		printk( KERN_INFO "CODEC: framer: %d\n", codec->framerate );
		printk( KERN_INFO "CODEC: grmgop: %d\n", codec->framespergop );
		printk( KERN_INFO "CODEC: gop_cl: %d\n", codec->gop_closure );
		printk( KERN_INFO "CODEC: pulldn: %d\n", codec->pulldown );
		printk( KERN_INFO "CODEC: strtyp: %d\n\n", codec->stream_type );
#endif

		codec->aspect = 2; /* 4:3 */
		codec->audio_bitmask = (2 << 2) | (14 << 4); /* layer II | 384kbps */
		codec->bframes = 2;
		codec->bitrate_mode = 1; /* cbr */
		codec->bitrate = 4500000; /* bps */
		codec->bitrate_peak = 6000000; /* peak */
		codec->dnr_mode = 0; /* spatial=manual | temporal=manual */
		codec->dnr_spatial = 0;
		codec->dnr_temporal = 0;
		codec->dnr_type = 0; /* disabled */
		codec->framerate = 1; /* 25fps */
		codec->framespergop = 15;
		codec->gop_closure = 0; /* open */
		codec->pulldown = 0; /* enabled */
		codec->stream_type = 0; /* program stream */
#if 1
		printk( KERN_INFO "CODEC: aspect: %d\n", codec->aspect );
		printk( KERN_INFO "CODEC: audio : %d\n", codec->audio_bitmask );
		printk( KERN_INFO "CODEC: bfrms : %d\n", codec->bframes );
		printk( KERN_INFO "CODEC: br_mod: %d\n", codec->bitrate_mode );
		printk( KERN_INFO "CODEC: btrate: %d\n", codec->bitrate );
		printk( KERN_INFO "CODEC: btr_pk: %d\n", codec->bitrate_peak );
		printk( KERN_INFO "CODEC: dnr_md: %d\n", codec->dnr_mode );
		printk( KERN_INFO "CODEC: dnr_sp: %d\n", codec->dnr_spatial );
		printk( KERN_INFO "CODEC: dnr_tp: %d\n", codec->dnr_temporal );
		printk( KERN_INFO "CODEC: dnr_ty: %d\n", codec->dnr_type );
		printk( KERN_INFO "CODEC: framer: %d\n", codec->framerate );
		printk( KERN_INFO "CODEC: grmgop: %d\n", codec->framespergop );
		printk( KERN_INFO "CODEC: gop_cl: %d\n", codec->gop_closure );
		printk( KERN_INFO "CODEC: pulldn: %d\n", codec->pulldown );
		printk( KERN_INFO "CODEC: strtyp: %d\n", codec->stream_type );
#endif
		return 0;
	}
	case IVTV_IOC_S_VBI_MODE:
	{
		struct ivtv_sliced_vbi_format *fmt = arg;
		printk( KERN_INFO "IVTV_IOC_S_VBI_MODE: ss: %ld, ps: %ld, is: %ld\n",
			fmt->service_set, fmt->packet_size, fmt->io_size );
#if 0
		fmt->service_set = 0;  /* one or more of the IVTV_SLICED_ defines */
		fmt->packet_size = 0;  /* the size in bytes of the ivtv_sliced_data packet */
		fmt->io_size = 0;      /* maximum number of bytes passed by one read() call */
#endif
		return 0;
	}
	case IVTV_IOC_G_VBI_MODE:
	{
		struct ivtv_sliced_vbi_format *fmt = arg;

		fmt->service_set = 1;  /* one or more of the IVTV_SLICED_ defines */
		fmt->packet_size = 0;  /* the size in bytes of the ivtv_sliced_data packet */
		fmt->io_size = 0;      /* maximum number of bytes passed by one read() call */
		return 0;
	}
	case IVTV_IOC_S_VBI_EMBED:
	{
		int *embed = arg;
		printk( KERN_INFO "IVTV_IOC_S_VBI_EMBED: %d\n", *embed );
			return 0;
	}

	default:
		if( prev_ioctl_hook )
			return prev_ioctl_hook( inode, file, cmd, arg );
		else
			return -EINVAL;
	}
	return 0;
}

static int __init cx88_ivtv_init(void)
{
	printk(KERN_INFO "ivtv emulation for blackbird version %d.%d.%d loaded\n",
		(CX88_VERSION_CODE >> 16) & 0xff,
		(CX88_VERSION_CODE >>  8) & 0xff,
		CX88_VERSION_CODE & 0xff);
#ifdef SNAPSHOT
	printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
		SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
	request_module( "cx88-blackbird" );
	prev_ioctl_translator = cx88_ioctl_translator;
	cx88_ioctl_translator = ivtv_translate_ioctl;
	prev_ioctl_hook = cx88_ioctl_hook;
	cx88_ioctl_hook = ivtv_do_ioctl;
	return 0;
}

static void __exit cx88_ivtv_fini(void)
{
	cx88_ioctl_hook = prev_ioctl_hook;
	cx88_ioctl_translator = prev_ioctl_translator;
}

module_init(cx88_ivtv_init);
module_exit(cx88_ivtv_fini);

/*
 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
 */