]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/media/video/cx88/cx88-blackbird.c
V4L/DVB (3982): Cx88-blackbird: use encoder firmware filename defined in cx2341x.h
[karo-tx-linux.git] / drivers / media / video / cx88 / cx88-blackbird.c
1 /*
2  *
3  *  Support for a cx23416 mpeg encoder via cx2388x host port.
4  *  "blackbird" reference design.
5  *
6  *    (c) 2004 Jelle Foks <jelle@foks.8m.com>
7  *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
8  *
9  *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/init.h>
29 #include <linux/fs.h>
30 #include <linux/delay.h>
31 #include <linux/device.h>
32 #include <linux/firmware.h>
33 #include <media/v4l2-common.h>
34 #include <media/cx2341x.h>
35
36 #include "cx88.h"
37
38 MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
39 MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
40 MODULE_LICENSE("GPL");
41
42 static unsigned int mpegbufs = 32;
43 module_param(mpegbufs,int,0644);
44 MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
45
46 static unsigned int debug = 0;
47 module_param(debug,int,0644);
48 MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
49
50 #define dprintk(level,fmt, arg...)      if (debug >= level) \
51         printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
52
53 static LIST_HEAD(cx8802_devlist);
54
55 /* ------------------------------------------------------------------ */
56
57 #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
58
59 /* defines below are from ivtv-driver.h */
60
61 #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
62
63 /* Firmware API commands */
64 #define IVTV_API_STD_TIMEOUT 500
65
66 enum blackbird_capture_type {
67         BLACKBIRD_MPEG_CAPTURE,
68         BLACKBIRD_RAW_CAPTURE,
69         BLACKBIRD_RAW_PASSTHRU_CAPTURE
70 };
71 enum blackbird_capture_bits {
72         BLACKBIRD_RAW_BITS_NONE             = 0x00,
73         BLACKBIRD_RAW_BITS_YUV_CAPTURE      = 0x01,
74         BLACKBIRD_RAW_BITS_PCM_CAPTURE      = 0x02,
75         BLACKBIRD_RAW_BITS_VBI_CAPTURE      = 0x04,
76         BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
77         BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
78 };
79 enum blackbird_capture_end {
80         BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
81         BLACKBIRD_END_NOW, /* stop immediately, no irq */
82 };
83 enum blackbird_framerate {
84         BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
85         BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
86 };
87 enum blackbird_video_bitrate_type {
88         BLACKBIRD_VIDEO_VBR,
89         BLACKBIRD_VIDEO_CBR
90 };
91 #define BLACKBIRD_PEAK_RATE_DIVISOR 400
92 enum blackbird_mux_rate {
93         BLACKBIRD_MUX_RATE_DEFAULT,
94          /* dvd mux rate: multiply by 400 to get the actual rate */
95         BLACKBIRD_MUX_RATE_DVD = 25200
96 };
97 enum blackbird_aspect_ratio {
98         BLACKBIRD_ASPECT_RATIO_FORBIDDEN,
99         BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
100         BLACKBIRD_ASPECT_RATIO_4_3,
101         BLACKBIRD_ASPECT_RATIO_16_9,
102         BLACKBIRD_ASPECT_RATIO_221_100,
103         BLACKBIRD_ASPECT_RATIO_RESERVED
104 };
105 enum blackbird_dnr_bits {
106         BLACKBIRD_DNR_BITS_MANUAL,
107         BLACKBIRD_DNR_BITS_AUTO_SPATIAL,
108         BLACKBIRD_DNR_BITS_AUTO_TEMPORAL,
109         BLACKBIRD_DNR_BITS_AUTO
110 };
111 enum blackbird_median_filter {
112         BLACKBIRD_MEDIAN_FILTER_DISABLED,
113         BLACKBIRD_MEDIAN_FILTER_HORIZONTAL,
114         BLACKBIRD_MEDIAN_FILTER_VERTICAL,
115         BLACKBIRD_MEDIAN_FILTER_HV,
116         BLACKBIRD_MEDIAN_FILTER_DIAGONAL
117 };
118 enum blackbird_spatial_filter_luma {
119         BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED,
120         BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
121         BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT,
122         BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */
123         BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */
124 };
125 enum blackbird_spatial_filter_chroma {
126         BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED,
127         BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */
128 };
129 enum blackbird_pulldown {
130         BLACKBIRD_3_2_PULLDOWN_DISABLED,
131         BLACKBIRD_3_2_PULLDOWN_ENABLED
132 };
133 enum blackbird_vbi_line_bits {
134         BLACKBIRD_VBI_LINE_BITS_TOP_FIELD,
135         BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31),
136         BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF
137 };
138 enum blackbird_vbi_line {
139         BLACKBIRD_VBI_LINE_DISABLED,
140         BLACKBIRD_VBI_LINE_ENABLED
141 };
142 enum blackbird_vbi_slicing {
143         BLACKBIRD_VBI_SLICING_NONE,
144         BLACKBIRD_VBI_SLICING_CLOSED_CAPTION
145 };
146 enum blackbird_stream_type {
147         BLACKBIRD_STREAM_PROGRAM,
148         BLACKBIRD_STREAM_TRANSPORT,
149         BLACKBIRD_STREAM_MPEG1,
150         BLACKBIRD_STREAM_PES_AV,
151         BLACKBIRD_STREAM_UNKNOWN4,
152         BLACKBIRD_STREAM_PES_VIDEO,
153         BLACKBIRD_STREAM_UNKNOWN6,
154         BLACKBIRD_STREAM_PES_AUDIO,
155         BLACKBIRD_STREAM_UNKNOWN8,
156         BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */
157         BLACKBIRD_STREAM_DVD,
158         BLACKBIRD_STREAM_VCD,
159         BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */
160 };
161 enum blackbird_stream_port {
162         BLACKBIRD_OUTPUT_PORT_MEMORY,
163         BLACKBIRD_OUTPUT_PORT_STREAMING,
164         BLACKBIRD_OUTPUT_PORT_SERIAL
165 };
166 enum blackbird_audio_bits_sample_rate {
167         BLACKBIRD_AUDIO_BITS_44100HZ,
168         BLACKBIRD_AUDIO_BITS_48000HZ,
169         BLACKBIRD_AUDIO_BITS_32000HZ,
170         BLACKBIRD_AUDIO_BITS_RESERVED_HZ,
171 };
172 enum blackbird_audio_bits_encoding {
173         BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2,
174         BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2,
175 };
176 enum blackbird_audio_bits_bitrate_layer_1 {
177         BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT,
178         BLACKBIRD_AUDIO_BITS_LAYER_1_32  = 0x01 << 4,
179         BLACKBIRD_AUDIO_BITS_LAYER_1_64  = 0x02 << 4,
180         BLACKBIRD_AUDIO_BITS_LAYER_1_96  = 0x03 << 4,
181         BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4,
182         BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4,
183         BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4,
184         BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4,
185         BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4,
186         BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4,
187         BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4,
188         BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4,
189         BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4,
190         BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4,
191         BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4,
192 };
193 enum blackbird_audio_bits_bitrate_layer_2 {
194         BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT,
195         BLACKBIRD_AUDIO_BITS_LAYER_2_32  = 0x01 << 4,
196         BLACKBIRD_AUDIO_BITS_LAYER_2_48  = 0x02 << 4,
197         BLACKBIRD_AUDIO_BITS_LAYER_2_56  = 0x03 << 4,
198         BLACKBIRD_AUDIO_BITS_LAYER_2_64  = 0x04 << 4,
199         BLACKBIRD_AUDIO_BITS_LAYER_2_80  = 0x05 << 4,
200         BLACKBIRD_AUDIO_BITS_LAYER_2_96  = 0x06 << 4,
201         BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4,
202         BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4,
203         BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4,
204         BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4,
205         BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4,
206         BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4,
207         BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4,
208         BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4,
209 };
210 enum blackbird_audio_bits_mode {
211         BLACKBIRD_AUDIO_BITS_STEREO,
212         BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8,
213         BLACKBIRD_AUDIO_BITS_DUAL         = 0x2 << 8,
214         BLACKBIRD_AUDIO_BITS_MONO         = 0x3 << 8,
215 };
216 enum blackbird_audio_bits_mode_extension {
217         BLACKBIRD_AUDIO_BITS_BOUND_4,
218         BLACKBIRD_AUDIO_BITS_BOUND_8  = 0x1 << 10,
219         BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10,
220         BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10,
221 };
222 enum blackbird_audio_bits_emphasis {
223         BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE,
224         BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15     = 0x1 << 12,
225         BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED  = 0x2 << 12,
226         BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12,
227 };
228 enum blackbird_audio_bits_crc {
229         BLACKBIRD_AUDIO_BITS_CRC_OFF,
230         BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14,
231 };
232 enum blackbird_audio_bits_copyright {
233         BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF,
234         BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15,
235 };
236 enum blackbird_audio_bits_original {
237         BLACKBIRD_AUDIO_BITS_COPY,
238         BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16,
239 };
240 enum blackbird_gop_closure {
241         BLACKBIRD_GOP_CLOSURE_OFF,
242         BLACKBIRD_GOP_CLOSURE_ON,
243 };
244 enum blackbird_data_xfer_status {
245         BLACKBIRD_MORE_BUFFERS_FOLLOW,
246         BLACKBIRD_LAST_BUFFER,
247 };
248 enum blackbird_picture_mask {
249         BLACKBIRD_PICTURE_MASK_NONE,
250         BLACKBIRD_PICTURE_MASK_I_FRAMES,
251         BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
252         BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
253 };
254 enum blackbird_vbi_mode_bits {
255         BLACKBIRD_VBI_BITS_SLICED,
256         BLACKBIRD_VBI_BITS_RAW,
257 };
258 enum blackbird_vbi_insertion_bits {
259         BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
260         BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
261         BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
262         BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
263         BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
264 };
265 enum blackbird_dma_unit {
266         BLACKBIRD_DMA_BYTES,
267         BLACKBIRD_DMA_FRAMES,
268 };
269 enum blackbird_dma_transfer_status_bits {
270         BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
271         BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
272         BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
273 };
274 enum blackbird_pause {
275         BLACKBIRD_PAUSE_ENCODING,
276         BLACKBIRD_RESUME_ENCODING,
277 };
278 enum blackbird_copyright {
279         BLACKBIRD_COPYRIGHT_OFF,
280         BLACKBIRD_COPYRIGHT_ON,
281 };
282 enum blackbird_notification_type {
283         BLACKBIRD_NOTIFICATION_REFRESH,
284 };
285 enum blackbird_notification_status {
286         BLACKBIRD_NOTIFICATION_OFF,
287         BLACKBIRD_NOTIFICATION_ON,
288 };
289 enum blackbird_notification_mailbox {
290         BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
291 };
292 enum blackbird_field1_lines {
293         BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
294         BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
295         BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
296 };
297 enum blackbird_field2_lines {
298         BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
299         BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
300         BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
301 };
302 enum blackbird_custom_data_type {
303         BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
304         BLACKBIRD_CUSTOM_PRIVATE_PACKET,
305 };
306 enum blackbird_mute {
307         BLACKBIRD_UNMUTE,
308         BLACKBIRD_MUTE,
309 };
310 enum blackbird_mute_video_mask {
311         BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
312         BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
313         BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
314 };
315 enum blackbird_mute_video_shift {
316         BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
317         BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
318         BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
319 };
320
321 /* Registers */
322 #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
323 #define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
324 #define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
325 #define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
326 #define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
327 #define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
328
329 /* ------------------------------------------------------------------ */
330
331 static void host_setup(struct cx88_core *core)
332 {
333         /* toggle reset of the host */
334         cx_write(MO_GPHST_SOFT_RST, 1);
335         udelay(100);
336         cx_write(MO_GPHST_SOFT_RST, 0);
337         udelay(100);
338
339         /* host port setup */
340         cx_write(MO_GPHST_WSC, 0x44444444U);
341         cx_write(MO_GPHST_XFR, 0);
342         cx_write(MO_GPHST_WDTH, 15);
343         cx_write(MO_GPHST_HDSHK, 0);
344         cx_write(MO_GPHST_MUX16, 0x44448888U);
345         cx_write(MO_GPHST_MODE, 0);
346 }
347
348 /* ------------------------------------------------------------------ */
349
350 #define P1_MDATA0 0x390000
351 #define P1_MDATA1 0x390001
352 #define P1_MDATA2 0x390002
353 #define P1_MDATA3 0x390003
354 #define P1_MADDR2 0x390004
355 #define P1_MADDR1 0x390005
356 #define P1_MADDR0 0x390006
357 #define P1_RDATA0 0x390008
358 #define P1_RDATA1 0x390009
359 #define P1_RDATA2 0x39000A
360 #define P1_RDATA3 0x39000B
361 #define P1_RADDR0 0x39000C
362 #define P1_RADDR1 0x39000D
363 #define P1_RRDWR  0x39000E
364
365 static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
366 {
367         unsigned long timeout = jiffies + msecs_to_jiffies(1);
368         u32 gpio0,need;
369
370         need = state ? 2 : 0;
371         for (;;) {
372                 gpio0 = cx_read(MO_GP0_IO) & 2;
373                 if (need == gpio0)
374                         return 0;
375                 if (time_after(jiffies,timeout))
376                         return -1;
377                 udelay(1);
378         }
379 }
380
381 static int memory_write(struct cx88_core *core, u32 address, u32 value)
382 {
383         /* Warning: address is dword address (4 bytes) */
384         cx_writeb(P1_MDATA0, (unsigned int)value);
385         cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
386         cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
387         cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
388         cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
389         cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
390         cx_writeb(P1_MADDR0, (unsigned int)address);
391         cx_read(P1_MDATA0);
392         cx_read(P1_MADDR0);
393
394         return wait_ready_gpio0_bit1(core,1);
395 }
396
397 static int memory_read(struct cx88_core *core, u32 address, u32 *value)
398 {
399         int retval;
400         u32 val;
401
402         /* Warning: address is dword address (4 bytes) */
403         cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
404         cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
405         cx_writeb(P1_MADDR0, (unsigned int)address);
406         cx_read(P1_MADDR0);
407
408         retval = wait_ready_gpio0_bit1(core,1);
409
410         cx_writeb(P1_MDATA3, 0);
411         val     = (unsigned char)cx_read(P1_MDATA3) << 24;
412         cx_writeb(P1_MDATA2, 0);
413         val    |= (unsigned char)cx_read(P1_MDATA2) << 16;
414         cx_writeb(P1_MDATA1, 0);
415         val    |= (unsigned char)cx_read(P1_MDATA1) << 8;
416         cx_writeb(P1_MDATA0, 0);
417         val    |= (unsigned char)cx_read(P1_MDATA0);
418
419         *value  = val;
420         return retval;
421 }
422
423 static int register_write(struct cx88_core *core, u32 address, u32 value)
424 {
425         cx_writeb(P1_RDATA0, (unsigned int)value);
426         cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
427         cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
428         cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
429         cx_writeb(P1_RADDR0, (unsigned int)address);
430         cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
431         cx_writeb(P1_RRDWR, 1);
432         cx_read(P1_RDATA0);
433         cx_read(P1_RADDR0);
434
435         return wait_ready_gpio0_bit1(core,1);
436 }
437
438
439 static int register_read(struct cx88_core *core, u32 address, u32 *value)
440 {
441         int retval;
442         u32 val;
443
444         cx_writeb(P1_RADDR0, (unsigned int)address);
445         cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
446         cx_writeb(P1_RRDWR, 0);
447         cx_read(P1_RADDR0);
448
449         retval  = wait_ready_gpio0_bit1(core,1);
450         val     = (unsigned char)cx_read(P1_RDATA0);
451         val    |= (unsigned char)cx_read(P1_RDATA1) << 8;
452         val    |= (unsigned char)cx_read(P1_RDATA2) << 16;
453         val    |= (unsigned char)cx_read(P1_RDATA3) << 24;
454
455         *value  = val;
456         return retval;
457 }
458
459 /* ------------------------------------------------------------------ */
460
461 /* We don't need to call the API often, so using just one mailbox will probably suffice */
462 static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
463                              u32 inputcnt, u32 outputcnt, ...)
464 {
465         unsigned long timeout;
466         u32 value, flag, retval;
467         int i;
468         va_list args;
469         va_start(args, outputcnt);
470
471         dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
472
473         /* this may not be 100% safe if we can't read any memory location
474            without side effects */
475         memory_read(dev->core, dev->mailbox - 4, &value);
476         if (value != 0x12345678) {
477                 dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
478                 return -1;
479         }
480
481         memory_read(dev->core, dev->mailbox, &flag);
482         if (flag) {
483                 dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
484                 return -1;
485         }
486
487         flag |= 1; /* tell 'em we're working on it */
488         memory_write(dev->core, dev->mailbox, flag);
489
490         /* write command + args + fill remaining with zeros */
491         memory_write(dev->core, dev->mailbox + 1, command); /* command code */
492         memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
493         for (i = 0; i < inputcnt ; i++) {
494                 value = va_arg(args, int);
495                 memory_write(dev->core, dev->mailbox + 4 + i, value);
496                 dprintk(1, "API Input %d = %d\n", i, value);
497         }
498         for (; i < 16 ; i++)
499                 memory_write(dev->core, dev->mailbox + 4 + i, 0);
500
501         flag |= 3; /* tell 'em we're done writing */
502         memory_write(dev->core, dev->mailbox, flag);
503
504         /* wait for firmware to handle the API command */
505         timeout = jiffies + msecs_to_jiffies(10);
506         for (;;) {
507                 memory_read(dev->core, dev->mailbox, &flag);
508                 if (0 != (flag & 4))
509                         break;
510                 if (time_after(jiffies,timeout)) {
511                         dprintk(0, "ERROR: API Mailbox timeout\n");
512                         return -1;
513                 }
514                 udelay(10);
515         }
516
517         /* read output values */
518         for (i = 0; i < outputcnt ; i++) {
519                 int *vptr = va_arg(args, int *);
520                 memory_read(dev->core, dev->mailbox + 4 + i, vptr);
521                 dprintk(1, "API Output %d = %d\n", i, *vptr);
522         }
523         va_end(args);
524
525         memory_read(dev->core, dev->mailbox + 2, &retval);
526         dprintk(1, "API result = %d\n",retval);
527
528         flag = 0;
529         memory_write(dev->core, dev->mailbox, flag);
530         return retval;
531 }
532
533
534 static int blackbird_find_mailbox(struct cx8802_dev *dev)
535 {
536         u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
537         int signaturecnt=0;
538         u32 value;
539         int i;
540
541         for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
542                 memory_read(dev->core, i, &value);
543                 if (value == signature[signaturecnt])
544                         signaturecnt++;
545                 else
546                         signaturecnt = 0;
547                 if (4 == signaturecnt) {
548                         dprintk(1, "Mailbox signature found\n");
549                         return i+1;
550                 }
551         }
552         dprintk(0, "Mailbox signature values not found!\n");
553         return -1;
554 }
555
556 static int blackbird_load_firmware(struct cx8802_dev *dev)
557 {
558         static const unsigned char magic[8] = {
559                 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
560         };
561         const struct firmware *firmware;
562         int i, retval = 0;
563         u32 value = 0;
564         u32 checksum = 0;
565         u32 *dataptr;
566
567         retval  = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
568         retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
569         retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
570         retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
571         msleep(1);
572         retval |= register_write(dev->core, IVTV_REG_APU, 0);
573
574         if (retval < 0)
575                 dprintk(0, "Error with register_write\n");
576
577         retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
578                                   &dev->pci->dev);
579
580
581         if (retval != 0) {
582                 dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
583                         CX2341X_FIRM_ENC_FILENAME);
584                 dprintk(0, "Please fix your hotplug setup, the board will "
585                         "not work without firmware loaded!\n");
586                 return -1;
587         }
588
589         if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
590                 dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
591                         firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
592                 return -1;
593         }
594
595         if (0 != memcmp(firmware->data, magic, 8)) {
596                 dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
597                 return -1;
598         }
599
600         /* transfer to the chip */
601         dprintk(1,"Loading firmware ...\n");
602         dataptr = (u32*)firmware->data;
603         for (i = 0; i < (firmware->size >> 2); i++) {
604                 value = *dataptr;
605                 checksum += ~value;
606                 memory_write(dev->core, i, value);
607                 dataptr++;
608         }
609
610         /* read back to verify with the checksum */
611         for (i--; i >= 0; i--) {
612                 memory_read(dev->core, i, &value);
613                 checksum -= ~value;
614         }
615         if (checksum) {
616                 dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
617                 return -1;
618         }
619         release_firmware(firmware);
620         dprintk(0, "Firmware upload successful.\n");
621
622         retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
623         retval |= register_read(dev->core, IVTV_REG_SPU, &value);
624         retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
625         msleep(1);
626
627         retval |= register_read(dev->core, IVTV_REG_VPU, &value);
628         retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
629
630         if (retval < 0)
631                 dprintk(0, "Error with register_write\n");
632         return 0;
633 }
634
635 /**
636  Settings used by the windows tv app for PVR2000:
637 =================================================================================================================
638 Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
639 -----------------------------------------------------------------------------------------------------------------
640 MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
641 MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
642 VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
643 DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
644 DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
645 =================================================================================================================
646 *DB: "DirectBurn"
647 */
648
649 static struct blackbird_dnr default_dnr_params = {
650         .mode     = BLACKBIRD_DNR_BITS_MANUAL,
651         .type     = BLACKBIRD_MEDIAN_FILTER_DISABLED,
652         .spatial  = 0,
653         .temporal = 0
654 };
655 static struct v4l2_mpeg_compression default_mpeg_params = {
656         .st_type          = V4L2_MPEG_PS_2,
657         .st_bitrate       = {
658                 .mode     = V4L2_BITRATE_CBR,
659                 .min      = 0,
660                 .target   = 0,
661                 .max      = 0
662         },
663         .ts_pid_pmt       = 16,
664         .ts_pid_audio     = 260,
665         .ts_pid_video     = 256,
666         .ts_pid_pcr       = 259,
667         .ps_size          = 0,
668         .au_type          = V4L2_MPEG_AU_2_II,
669         .au_bitrate       = {
670                 .mode     = V4L2_BITRATE_CBR,
671                 .min      = 224,
672                 .target   = 224,
673                 .max      = 224
674         },
675         .au_sample_rate    = 44100,
676         .au_pesid          = 0,
677         .vi_type           = V4L2_MPEG_VI_2,
678         .vi_aspect_ratio   = V4L2_MPEG_ASPECT_4_3,
679         .vi_bitrate        = {
680                 .mode      = V4L2_BITRATE_CBR,
681                 .min       = 4000,
682                 .target    = 4500,
683                 .max       = 6000
684         },
685         .vi_frame_rate     = 25,
686         .vi_frames_per_gop = 15,
687         .vi_bframes_count  = 2,
688         .vi_pesid          = 0,
689         .closed_gops       = 0,
690         .pulldown          = 0
691 };
692
693 static enum blackbird_stream_type mpeg_stream_types[] = {
694         [V4L2_MPEG_SS_1]   = BLACKBIRD_STREAM_MPEG1,
695         [V4L2_MPEG_PS_2]   = BLACKBIRD_STREAM_PROGRAM,
696         [V4L2_MPEG_TS_2]   = BLACKBIRD_STREAM_TRANSPORT,
697         [V4L2_MPEG_PS_DVD] = BLACKBIRD_STREAM_DVD,
698 };
699 static enum blackbird_aspect_ratio mpeg_stream_ratios[] = {
700         [V4L2_MPEG_ASPECT_SQUARE] = BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
701         [V4L2_MPEG_ASPECT_4_3]    = BLACKBIRD_ASPECT_RATIO_4_3,
702         [V4L2_MPEG_ASPECT_16_9]   = BLACKBIRD_ASPECT_RATIO_16_9,
703         [V4L2_MPEG_ASPECT_1_221]  = BLACKBIRD_ASPECT_RATIO_221_100,
704 };
705 static enum blackbird_video_bitrate_type mpeg_video_bitrates[] = {
706         [V4L2_BITRATE_NONE] = BLACKBIRD_VIDEO_CBR,
707         [V4L2_BITRATE_CBR]  = BLACKBIRD_VIDEO_CBR,
708         [V4L2_BITRATE_VBR]  = BLACKBIRD_VIDEO_VBR,
709 };
710 /* find the best layer I/II bitrate to fit a given numeric value */
711 struct bitrate_bits {
712         u32 bits; /* layer bits for the best fit */
713         u32 rate; /* actual numeric value for the layer best fit */
714 };
715 struct bitrate_approximation {
716         u32                 target;   /* numeric value of the rate we want */
717         struct bitrate_bits layer[2];
718 };
719 static struct bitrate_approximation mpeg_audio_bitrates[] = {
720         /* target  layer[0].bits           layer[0].rate       layer[1].bits           layer[1].rate */
721         {   0, { {                                0,   0, }, {                                0,   0, }, }, },
722         {  32, { { BLACKBIRD_AUDIO_BITS_LAYER_1_32 ,  32, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_32 ,  32, }, }, },
723         {  48, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_48 ,  48, }, }, },
724         {  56, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_56 ,  56, }, }, },
725         {  64, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_64 ,  64, }, }, },
726         {  80, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 ,  96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_80 ,  80, }, }, },
727         {  96, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 ,  96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_96 ,  96, }, }, },
728         { 112, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_112, 112, }, }, },
729         { 128, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_128, 128, }, }, },
730         { 160, { { BLACKBIRD_AUDIO_BITS_LAYER_1_160, 160, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_160, 160, }, }, },
731         { 192, { { BLACKBIRD_AUDIO_BITS_LAYER_1_192, 192, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_192, 192, }, }, },
732         { 224, { { BLACKBIRD_AUDIO_BITS_LAYER_1_224, 224, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_224, 224, }, }, },
733         { 256, { { BLACKBIRD_AUDIO_BITS_LAYER_1_256, 256, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_256, 256, }, }, },
734         { 288, { { BLACKBIRD_AUDIO_BITS_LAYER_1_288, 288, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, },
735         { 320, { { BLACKBIRD_AUDIO_BITS_LAYER_1_320, 320, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, },
736         { 352, { { BLACKBIRD_AUDIO_BITS_LAYER_1_352, 352, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
737         { 384, { { BLACKBIRD_AUDIO_BITS_LAYER_1_384, 384, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
738         { 416, { { BLACKBIRD_AUDIO_BITS_LAYER_1_416, 416, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
739         { 448, { { BLACKBIRD_AUDIO_BITS_LAYER_1_448, 448, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
740 };
741 static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates);
742
743 static void blackbird_set_default_params(struct cx8802_dev *dev)
744 {
745         struct v4l2_mpeg_compression *params = &dev->params;
746         u32 au_params;
747
748         /* assign stream type */
749         if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) )
750                 params->st_type = V4L2_MPEG_PS_2;
751         if( params->st_type == V4L2_MPEG_SS_1 )
752                 params->vi_type = V4L2_MPEG_VI_1;
753         else
754                 params->vi_type = V4L2_MPEG_VI_2;
755         blackbird_api_cmd(dev, CX2341X_ENC_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]);
756
757         /* assign framerate */
758         if( params->vi_frame_rate <= 25 )
759         {
760                 params->vi_frame_rate = 25;
761                 blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_RATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
762         }
763         else
764         {
765                 params->vi_frame_rate = 30;
766                 blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_RATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30);
767         }
768
769         /* assign aspect ratio */
770         if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) )
771                 params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3;
772         blackbird_api_cmd(dev, CX2341X_ENC_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]);
773
774         /* assign gop properties */
775         blackbird_api_cmd(dev, CX2341X_ENC_SET_GOP_PROPERTIES, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1);
776
777         /* assign gop closure */
778         blackbird_api_cmd(dev, CX2341X_ENC_SET_GOP_CLOSURE, 1, 0, params->closed_gops);
779
780         /* assign 3 2 pulldown */
781         blackbird_api_cmd(dev, CX2341X_ENC_SET_3_2_PULLDOWN, 1, 0, params->pulldown);
782
783         /* make sure the params are within bounds */
784         if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
785                 params->vi_bitrate.mode = V4L2_BITRATE_NONE;
786         if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
787                 params->vi_bitrate.mode = V4L2_BITRATE_NONE;
788         if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
789                 params->au_bitrate.mode = V4L2_BITRATE_NONE;
790
791         /* assign audio properties */
792         /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
793         au_params = BLACKBIRD_AUDIO_BITS_STEREO |
794                         /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
795                         BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
796                         BLACKBIRD_AUDIO_BITS_CRC_OFF |
797                         BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
798                         BLACKBIRD_AUDIO_BITS_COPY |
799                         0;
800         if( params->au_sample_rate <= 32000 )
801         {
802                 params->au_sample_rate = 32000;
803                 au_params |= BLACKBIRD_AUDIO_BITS_32000HZ;
804         }
805         else if( params->au_sample_rate <= 44100 )
806         {
807                 params->au_sample_rate = 44100;
808                 au_params |= BLACKBIRD_AUDIO_BITS_44100HZ;
809         }
810         else
811         {
812                 params->au_sample_rate = 48000;
813                 au_params |= BLACKBIRD_AUDIO_BITS_48000HZ;
814         }
815         if( params->au_type == V4L2_MPEG_AU_2_I )
816         {
817                 au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1;
818         }
819         else
820         {
821                 /* TODO: try to handle the other formats more gracefully */
822                 params->au_type = V4L2_MPEG_AU_2_II;
823                 au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2;
824         }
825         if( params->au_bitrate.mode )
826         {
827                 int layer;
828
829                 if( params->au_bitrate.mode == V4L2_BITRATE_CBR )
830                         params->au_bitrate.max = params->vi_bitrate.target;
831                 else
832                         params->au_bitrate.target = params->vi_bitrate.max;
833
834                 layer = params->au_type;
835                 if( params->au_bitrate.target == 0 )
836                 {
837                         /* TODO: use the minimum possible bitrate instead of 0 ? */
838                         au_params |= 0;
839                 }
840                 else if( params->au_bitrate.target >=
841                          mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate )
842                 {
843                         /* clamp the bitrate to the max supported by the standard */
844                         params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate;
845                         params->au_bitrate.max = params->au_bitrate.target;
846                         au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits;
847                 }
848                 else
849                 {
850                         /* round up to the nearest supported bitrate */
851                         int i;
852                         for(i = 1; i < BITRATES_SIZE; i++)
853                         {
854                                 if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate &&
855                                     params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate )
856                                 {
857                                         params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate;
858                                         params->au_bitrate.max = params->au_bitrate.target;
859                                         au_params |= mpeg_audio_bitrates[i].layer[layer].bits;
860                                         break;
861                                 }
862                         }
863                 }
864         }
865         else
866         {
867                 /* TODO: ??? */
868                 params->au_bitrate.target = params->au_bitrate.max = 0;
869                 au_params |= 0;
870         }
871         blackbird_api_cmd(dev, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, 0, au_params );
872
873         /* assign bitrates */
874         if( params->vi_bitrate.mode )
875         {
876                 /* bitrate is set, let's figure out the cbr/vbr mess */
877                 if( params->vi_bitrate.max < params->vi_bitrate.target )
878                 {
879                         if( params->vi_bitrate.mode == V4L2_BITRATE_CBR )
880                                 params->vi_bitrate.max = params->vi_bitrate.target;
881                         else
882                                 params->vi_bitrate.target = params->vi_bitrate.max;
883                 }
884         }
885         else
886         {
887                 if( params->st_bitrate.max < params->st_bitrate.target )
888                 {
889                         if( params->st_bitrate.mode == V4L2_BITRATE_VBR )
890                                 params->st_bitrate.target = params->st_bitrate.max;
891                         else
892                                 params->st_bitrate.max = params->st_bitrate.target;
893                 }
894                 /* calculate vi_bitrate = st_bitrate - au_bitrate */
895                 params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max;
896                 params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target;
897         }
898         blackbird_api_cmd(dev, CX2341X_ENC_SET_BIT_RATE, 4, 0,
899                                 mpeg_video_bitrates[params->vi_bitrate.mode],
900                                 params->vi_bitrate.target * 1000, /* kbps -> bps */
901                                 params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
902                                 BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
903
904         /* TODO: implement the stream ID stuff:
905                 ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr,
906                 ps_size, au_pesid, vi_pesid
907         */
908 }
909 #define CHECK_PARAM( name ) ( dev->params.name != params->name )
910 #define IF_PARAM( name ) if( CHECK_PARAM( name ) )
911 #define UPDATE_PARAM( name ) dev->params.name = params->name
912 void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params)
913 {
914         u32 au_params;
915
916         /* assign stream type */
917         if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) )
918                 params->st_type = V4L2_MPEG_PS_2;
919         if( params->st_type == V4L2_MPEG_SS_1 )
920                 params->vi_type = V4L2_MPEG_VI_1;
921         else
922                 params->vi_type = V4L2_MPEG_VI_2;
923         if( CHECK_PARAM( st_type ) || CHECK_PARAM( vi_type ) )
924         {
925                 UPDATE_PARAM( st_type );
926                 UPDATE_PARAM( vi_type );
927                 blackbird_api_cmd(dev, CX2341X_ENC_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]);
928         }
929
930         /* assign framerate */
931         if( params->vi_frame_rate <= 25 )
932                 params->vi_frame_rate = 25;
933         else
934                 params->vi_frame_rate = 30;
935         IF_PARAM( vi_frame_rate )
936         {
937                 UPDATE_PARAM( vi_frame_rate );
938                 if( params->vi_frame_rate == 25 )
939                         blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_RATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
940                 else
941                         blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_RATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30);
942         }
943
944         /* assign aspect ratio */
945         if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) )
946                 params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3;
947         IF_PARAM( vi_aspect_ratio )
948         {
949                 UPDATE_PARAM( vi_aspect_ratio );
950                 blackbird_api_cmd(dev, CX2341X_ENC_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]);
951         }
952
953         /* assign gop properties */
954         if( CHECK_PARAM( vi_frames_per_gop ) || CHECK_PARAM( vi_bframes_count ) )
955         {
956                 UPDATE_PARAM( vi_frames_per_gop );
957                 UPDATE_PARAM( vi_bframes_count );
958                 blackbird_api_cmd(dev, CX2341X_ENC_SET_GOP_PROPERTIES, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1);
959         }
960
961         /* assign gop closure */
962         IF_PARAM( closed_gops )
963         {
964                 UPDATE_PARAM( closed_gops );
965                 blackbird_api_cmd(dev, CX2341X_ENC_SET_GOP_CLOSURE, 1, 0, params->closed_gops);
966         }
967
968         /* assign 3 2 pulldown */
969         IF_PARAM( pulldown )
970         {
971                 UPDATE_PARAM( pulldown );
972                 blackbird_api_cmd(dev, CX2341X_ENC_SET_3_2_PULLDOWN, 1, 0, params->pulldown);
973         }
974
975         /* make sure the params are within bounds */
976         if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
977                 params->vi_bitrate.mode = V4L2_BITRATE_NONE;
978         if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
979                 params->vi_bitrate.mode = V4L2_BITRATE_NONE;
980         if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
981                 params->au_bitrate.mode = V4L2_BITRATE_NONE;
982
983         /* assign audio properties */
984         /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
985         au_params = BLACKBIRD_AUDIO_BITS_STEREO |
986                         /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
987         BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
988                 BLACKBIRD_AUDIO_BITS_CRC_OFF |
989                 BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
990                 BLACKBIRD_AUDIO_BITS_COPY |
991                 0;
992         if( params->au_sample_rate < 32000 )
993         {
994                 params->au_sample_rate = 32000;
995                 au_params |= BLACKBIRD_AUDIO_BITS_32000HZ;
996         }
997         else if( params->au_sample_rate < 44100 )
998         {
999                 params->au_sample_rate = 44100;
1000                 au_params |= BLACKBIRD_AUDIO_BITS_44100HZ;
1001         }
1002         else
1003         {
1004                 params->au_sample_rate = 48000;
1005                 au_params |= BLACKBIRD_AUDIO_BITS_48000HZ;
1006         }
1007         if( params->au_type == V4L2_MPEG_AU_2_I )
1008         {
1009                 au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1;
1010         }
1011         else
1012         {
1013                 /* TODO: try to handle the other formats more gracefully */
1014                 params->au_type = V4L2_MPEG_AU_2_II;
1015                 au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2;
1016         }
1017         if( params->au_bitrate.mode )
1018         {
1019                 int layer;
1020
1021                 if( params->au_bitrate.mode == V4L2_BITRATE_CBR )
1022                         params->au_bitrate.max = params->vi_bitrate.target;
1023                 else
1024                         params->au_bitrate.target = params->vi_bitrate.max;
1025
1026                 layer = params->au_type;
1027                 if( params->au_bitrate.target == 0 )
1028                 {
1029                         /* TODO: use the minimum possible bitrate instead of 0 ? */
1030                         au_params |= 0;
1031                 }
1032                 else if( params->au_bitrate.target >=
1033                          mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate )
1034                 {
1035                         /* clamp the bitrate to the max supported by the standard */
1036                         params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate;
1037                         params->au_bitrate.max = params->au_bitrate.target;
1038                         au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits;
1039                 }
1040                 else
1041                 {
1042                         /* round up to the nearest supported bitrate */
1043                         int i;
1044                         for(i = 1; i < BITRATES_SIZE; i++)
1045                         {
1046                                 if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate &&
1047                                     params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate )
1048                                 {
1049                                         params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate;
1050                                         params->au_bitrate.max = params->au_bitrate.target;
1051                                         au_params |= mpeg_audio_bitrates[i].layer[layer].bits;
1052                                         break;
1053                                 }
1054                         }
1055                 }
1056         }
1057         else
1058         {
1059                 /* TODO: ??? */
1060                 params->au_bitrate.target = params->au_bitrate.max = 0;
1061                 au_params |= 0;
1062         }
1063         if( CHECK_PARAM( au_type ) || CHECK_PARAM( au_sample_rate )
1064                 || CHECK_PARAM( au_bitrate.mode ) || CHECK_PARAM( au_bitrate.max )
1065                 || CHECK_PARAM( au_bitrate.target )
1066         )
1067         {
1068                 UPDATE_PARAM( au_type );
1069                 UPDATE_PARAM( au_sample_rate );
1070                 UPDATE_PARAM( au_bitrate );
1071                 blackbird_api_cmd(dev, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, 0, au_params );
1072         }
1073
1074         /* assign bitrates */
1075         if( params->vi_bitrate.mode )
1076         {
1077                 /* bitrate is set, let's figure out the cbr/vbr mess */
1078                 if( params->vi_bitrate.max < params->vi_bitrate.target )
1079                 {
1080                         if( params->vi_bitrate.mode == V4L2_BITRATE_CBR )
1081                                 params->vi_bitrate.max = params->vi_bitrate.target;
1082                         else
1083                                 params->vi_bitrate.target = params->vi_bitrate.max;
1084                 }
1085         }
1086         else
1087         {
1088                 if( params->st_bitrate.max < params->st_bitrate.target )
1089                 {
1090                         if( params->st_bitrate.mode == V4L2_BITRATE_VBR )
1091                                 params->st_bitrate.target = params->st_bitrate.max;
1092                         else
1093                                 params->st_bitrate.max = params->st_bitrate.target;
1094                 }
1095                 /* calculate vi_bitrate = st_bitrate - au_bitrate */
1096                 params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max;
1097                 params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target;
1098         }
1099         UPDATE_PARAM( st_bitrate );
1100         if( CHECK_PARAM( vi_bitrate.mode ) || CHECK_PARAM( vi_bitrate.max )
1101                 || CHECK_PARAM( vi_bitrate.target )
1102         )
1103         {
1104                 UPDATE_PARAM( vi_bitrate );
1105                 blackbird_api_cmd(dev, CX2341X_ENC_SET_BIT_RATE, 4, 0,
1106                                 mpeg_video_bitrates[params->vi_bitrate.mode],
1107                                 params->vi_bitrate.target * 1000, /* kbps -> bps */
1108                                 params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
1109                                 BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
1110         }
1111
1112         /* TODO: implement the stream ID stuff:
1113                 ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr,
1114                 ps_size, au_pesid, vi_pesid
1115         */
1116         UPDATE_PARAM( ts_pid_pmt );
1117         UPDATE_PARAM( ts_pid_audio );
1118         UPDATE_PARAM( ts_pid_video );
1119         UPDATE_PARAM( ts_pid_pcr );
1120         UPDATE_PARAM( ps_size );
1121         UPDATE_PARAM( au_pesid );
1122         UPDATE_PARAM( vi_pesid );
1123 }
1124
1125 static void blackbird_set_default_dnr_params(struct cx8802_dev *dev)
1126 {
1127         /* assign dnr filter mode */
1128         if( dev->dnr_params.mode > BLACKBIRD_DNR_BITS_AUTO )
1129                 dev->dnr_params.mode = BLACKBIRD_DNR_BITS_MANUAL;
1130         if( dev->dnr_params.type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL )
1131                 dev->dnr_params.type = BLACKBIRD_MEDIAN_FILTER_DISABLED;
1132         blackbird_api_cmd(dev, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, 0,
1133                                 dev->dnr_params.mode,
1134                                 dev->dnr_params.type
1135                         );
1136
1137         /* assign dnr filter props*/
1138         if( dev->dnr_params.spatial > 15 )
1139                 dev->dnr_params.spatial = 15;
1140         if( dev->dnr_params.temporal > 31 )
1141                 dev->dnr_params.temporal = 31;
1142         blackbird_api_cmd(dev, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, 0,
1143                                 dev->dnr_params.spatial,
1144                                 dev->dnr_params.temporal
1145                         );
1146 }
1147 #define CHECK_DNR_PARAM( name ) ( dev->dnr_params.name != dnr_params->name )
1148 #define UPDATE_DNR_PARAM( name ) dev->dnr_params.name = dnr_params->name
1149 void blackbird_set_dnr_params(struct cx8802_dev *dev, struct blackbird_dnr* dnr_params)
1150 {
1151         /* assign dnr filter mode */
1152         /* clamp values */
1153         if( dnr_params->mode > BLACKBIRD_DNR_BITS_AUTO )
1154                 dnr_params->mode = BLACKBIRD_DNR_BITS_MANUAL;
1155         if( dnr_params->type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL )
1156                 dnr_params->type = BLACKBIRD_MEDIAN_FILTER_DISABLED;
1157         /* check if the params actually changed */
1158         if( CHECK_DNR_PARAM( mode ) || CHECK_DNR_PARAM( type ) )
1159         {
1160                 UPDATE_DNR_PARAM( mode );
1161                 UPDATE_DNR_PARAM( type );
1162                 blackbird_api_cmd(dev, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, 0, dnr_params->mode, dnr_params->type);
1163         }
1164
1165         /* assign dnr filter props*/
1166         if( dnr_params->spatial > 15 )
1167                 dnr_params->spatial = 15;
1168         if( dnr_params->temporal > 31 )
1169                 dnr_params->temporal = 31;
1170         if( CHECK_DNR_PARAM( spatial ) || CHECK_DNR_PARAM( temporal ) )
1171         {
1172                 UPDATE_DNR_PARAM( spatial );
1173                 UPDATE_DNR_PARAM( temporal );
1174                 blackbird_api_cmd(dev, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, 0, dnr_params->spatial, dnr_params->temporal);
1175         }
1176 }
1177
1178 static void blackbird_codec_settings(struct cx8802_dev *dev)
1179 {
1180
1181         /* assign output port */
1182         blackbird_api_cmd(dev, CX2341X_ENC_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
1183
1184         /* assign frame size */
1185         blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
1186                                 dev->height, dev->width);
1187
1188         /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
1189         blackbird_api_cmd(dev, CX2341X_ENC_SET_CORING_LEVELS, 4, 0, 0, 255, 0, 255);
1190
1191         /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */
1192         blackbird_api_cmd(dev, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, 0,
1193                                 BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
1194                                 BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ
1195                         );
1196
1197         /* assign frame drop rate */
1198         /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */
1199
1200         blackbird_set_default_params(dev);
1201         blackbird_set_default_dnr_params(dev);
1202 }
1203
1204 static int blackbird_initialize_codec(struct cx8802_dev *dev)
1205 {
1206         struct cx88_core *core = dev->core;
1207         int version;
1208         int retval;
1209
1210         dprintk(1,"Initialize codec\n");
1211         retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
1212         if (retval < 0) {
1213                 /* ping was not successful, reset and upload firmware */
1214                 cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
1215                 msleep(1);
1216                 cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
1217                 msleep(1);
1218                 retval = blackbird_load_firmware(dev);
1219                 if (retval < 0)
1220                         return retval;
1221
1222                 dev->mailbox = blackbird_find_mailbox(dev);
1223                 if (dev->mailbox < 0)
1224                         return -1;
1225
1226                 retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
1227                 if (retval < 0) {
1228                         dprintk(0, "ERROR: Firmware ping failed!\n");
1229                         return -1;
1230                 }
1231
1232                 retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
1233                 if (retval < 0) {
1234                         dprintk(0, "ERROR: Firmware get encoder version failed!\n");
1235                         return -1;
1236                 }
1237                 dprintk(0, "Firmware version is 0x%08x\n", version);
1238         }
1239         msleep(1);
1240
1241         cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
1242         cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
1243         cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */
1244         cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
1245
1246         blackbird_codec_settings(dev);
1247         msleep(1);
1248
1249         /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
1250            blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
1251            blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */
1252         blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
1253                         BLACKBIRD_FIELD1_SAA7115,
1254                         BLACKBIRD_FIELD2_SAA7115
1255                 );
1256
1257         /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */
1258         blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
1259                         BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
1260                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1261
1262         /* initialize the video input */
1263         blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
1264
1265         msleep(1);
1266
1267         blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
1268         msleep(1);
1269         blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
1270         msleep(1);
1271
1272         /* start capturing to the host interface */
1273         /* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */
1274         blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
1275                         BLACKBIRD_MPEG_CAPTURE,
1276                         BLACKBIRD_RAW_BITS_NONE
1277                 );
1278         msleep(10);
1279
1280         blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0);
1281         return 0;
1282 }
1283
1284 /* ------------------------------------------------------------------ */
1285
1286 static int bb_buf_setup(struct videobuf_queue *q,
1287                         unsigned int *count, unsigned int *size)
1288 {
1289         struct cx8802_fh *fh = q->priv_data;
1290
1291         fh->dev->ts_packet_size  = 188 * 4; /* was: 512 */
1292         fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
1293
1294         *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
1295         *count = fh->dev->ts_packet_count;
1296         return 0;
1297 }
1298
1299 static int
1300 bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1301                enum v4l2_field field)
1302 {
1303         struct cx8802_fh *fh = q->priv_data;
1304         return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
1305 }
1306
1307 static void
1308 bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1309 {
1310         struct cx8802_fh *fh = q->priv_data;
1311         cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
1312 }
1313
1314 static void
1315 bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1316 {
1317         cx88_free_buffer(q, (struct cx88_buffer*)vb);
1318 }
1319
1320 static struct videobuf_queue_ops blackbird_qops = {
1321         .buf_setup    = bb_buf_setup,
1322         .buf_prepare  = bb_buf_prepare,
1323         .buf_queue    = bb_buf_queue,
1324         .buf_release  = bb_buf_release,
1325 };
1326
1327 /* ------------------------------------------------------------------ */
1328
1329 static int mpeg_do_ioctl(struct inode *inode, struct file *file,
1330                          unsigned int cmd, void *arg)
1331 {
1332         struct cx8802_fh  *fh  = file->private_data;
1333         struct cx8802_dev *dev = fh->dev;
1334         struct cx88_core  *core = dev->core;
1335
1336         if (debug > 1)
1337                 v4l_print_ioctl(core->name,cmd);
1338
1339         switch (cmd) {
1340
1341         /* --- capabilities ------------------------------------------ */
1342         case VIDIOC_QUERYCAP:
1343         {
1344                 struct v4l2_capability *cap = arg;
1345
1346                 memset(cap,0,sizeof(*cap));
1347                 strcpy(cap->driver, "cx88_blackbird");
1348                 strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
1349                 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
1350                 cap->version = CX88_VERSION_CODE;
1351                 cap->capabilities =
1352                         V4L2_CAP_VIDEO_CAPTURE |
1353                         V4L2_CAP_READWRITE     |
1354                         V4L2_CAP_STREAMING     |
1355                         0;
1356                 if (UNSET != core->tuner_type)
1357                         cap->capabilities |= V4L2_CAP_TUNER;
1358
1359                 return 0;
1360         }
1361
1362         /* --- capture ioctls ---------------------------------------- */
1363         case VIDIOC_ENUM_FMT:
1364         {
1365                 struct v4l2_fmtdesc *f = arg;
1366                 int index;
1367
1368                 index = f->index;
1369                 if (index != 0)
1370                         return -EINVAL;
1371
1372                 memset(f,0,sizeof(*f));
1373                 f->index = index;
1374                 strlcpy(f->description, "MPEG", sizeof(f->description));
1375                 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1376                 f->pixelformat = V4L2_PIX_FMT_MPEG;
1377                 return 0;
1378         }
1379         case VIDIOC_G_FMT:
1380         {
1381                 struct v4l2_format *f = arg;
1382
1383                 memset(f,0,sizeof(*f));
1384                 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1385                 f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
1386                 f->fmt.pix.bytesperline = 0;
1387                 f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
1388                 f->fmt.pix.colorspace   = 0;
1389                 f->fmt.pix.width        = dev->width;
1390                 f->fmt.pix.height       = dev->height;
1391                 f->fmt.pix.field        = fh->mpegq.field;
1392                 dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
1393                         dev->width, dev->height, fh->mpegq.field );
1394                 return 0;
1395         }
1396         case VIDIOC_TRY_FMT:
1397         {
1398                 struct v4l2_format *f = arg;
1399
1400                 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1401                 f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
1402                 f->fmt.pix.bytesperline = 0;
1403                 f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
1404                 f->fmt.pix.colorspace   = 0;
1405                 dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
1406                         dev->width, dev->height, fh->mpegq.field );
1407                 return 0;
1408         }
1409         case VIDIOC_S_FMT:
1410         {
1411                 struct v4l2_format *f = arg;
1412
1413                 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1414                 f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
1415                 f->fmt.pix.bytesperline = 0;
1416                 f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
1417                 f->fmt.pix.colorspace   = 0;
1418                 dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
1419                         f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
1420                 return 0;
1421         }
1422
1423         /* --- streaming capture ------------------------------------- */
1424         case VIDIOC_REQBUFS:
1425                 return videobuf_reqbufs(&fh->mpegq, arg);
1426
1427         case VIDIOC_QUERYBUF:
1428                 return videobuf_querybuf(&fh->mpegq, arg);
1429
1430         case VIDIOC_QBUF:
1431                 return videobuf_qbuf(&fh->mpegq, arg);
1432
1433         case VIDIOC_DQBUF:
1434                 return videobuf_dqbuf(&fh->mpegq, arg,
1435                                       file->f_flags & O_NONBLOCK);
1436
1437         case VIDIOC_STREAMON:
1438                 return videobuf_streamon(&fh->mpegq);
1439
1440         case VIDIOC_STREAMOFF:
1441                 return videobuf_streamoff(&fh->mpegq);
1442
1443         /* --- mpeg compression -------------------------------------- */
1444         case VIDIOC_G_MPEGCOMP:
1445         {
1446                 struct v4l2_mpeg_compression *f = arg;
1447
1448                 memcpy(f,&dev->params,sizeof(*f));
1449                 return 0;
1450         }
1451         case VIDIOC_S_MPEGCOMP:
1452         {
1453                 struct v4l2_mpeg_compression *f = arg;
1454
1455                 blackbird_set_params(dev, f);
1456                 return 0;
1457         }
1458         case VIDIOC_S_FREQUENCY:
1459         {
1460                 blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
1461                                   BLACKBIRD_END_NOW,
1462                                   BLACKBIRD_MPEG_CAPTURE,
1463                                   BLACKBIRD_RAW_BITS_NONE);
1464
1465                 cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook );
1466
1467                 blackbird_initialize_codec(dev);
1468                 cx88_set_scale(dev->core, dev->width, dev->height,
1469                                fh->mpegq.field);
1470                 return 0;
1471         }
1472
1473         default:
1474                 return cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook );
1475         }
1476         return 0;
1477 }
1478
1479 int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
1480                         unsigned int cmd, void *arg);
1481 unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
1482
1483 static unsigned int mpeg_translate_ioctl(unsigned int cmd)
1484 {
1485         return cmd;
1486 }
1487
1488 static int mpeg_ioctl(struct inode *inode, struct file *file,
1489                         unsigned int cmd, unsigned long arg)
1490 {
1491         cmd = cx88_ioctl_translator( cmd );
1492         return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
1493 }
1494
1495 static int mpeg_open(struct inode *inode, struct file *file)
1496 {
1497         int minor = iminor(inode);
1498         struct cx8802_dev *h,*dev = NULL;
1499         struct cx8802_fh *fh;
1500         struct list_head *list;
1501
1502         list_for_each(list,&cx8802_devlist) {
1503                 h = list_entry(list, struct cx8802_dev, devlist);
1504                 if (h->mpeg_dev->minor == minor)
1505                         dev = h;
1506         }
1507         if (NULL == dev)
1508                 return -ENODEV;
1509
1510         if (blackbird_initialize_codec(dev) < 0)
1511                 return -EINVAL;
1512         dprintk(1,"open minor=%d\n",minor);
1513
1514         /* allocate + initialize per filehandle data */
1515         fh = kzalloc(sizeof(*fh),GFP_KERNEL);
1516         if (NULL == fh)
1517                 return -ENOMEM;
1518         file->private_data = fh;
1519         fh->dev      = dev;
1520
1521         videobuf_queue_init(&fh->mpegq, &blackbird_qops,
1522                             dev->pci, &dev->slock,
1523                             V4L2_BUF_TYPE_VIDEO_CAPTURE,
1524                             V4L2_FIELD_INTERLACED,
1525                             sizeof(struct cx88_buffer),
1526                             fh);
1527
1528         /* FIXME: locking against other video device */
1529         cx88_set_scale(dev->core, dev->width, dev->height,
1530                         fh->mpegq.field);
1531
1532         return 0;
1533 }
1534
1535 static int mpeg_release(struct inode *inode, struct file *file)
1536 {
1537         struct cx8802_fh  *fh  = file->private_data;
1538
1539         /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
1540         blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
1541                         BLACKBIRD_END_NOW,
1542                         BLACKBIRD_MPEG_CAPTURE,
1543                         BLACKBIRD_RAW_BITS_NONE
1544                 );
1545
1546         cx8802_cancel_buffers(fh->dev);
1547         /* stop mpeg capture */
1548         if (fh->mpegq.streaming)
1549                 videobuf_streamoff(&fh->mpegq);
1550         if (fh->mpegq.reading)
1551                 videobuf_read_stop(&fh->mpegq);
1552
1553         videobuf_mmap_free(&fh->mpegq);
1554         file->private_data = NULL;
1555         kfree(fh);
1556         return 0;
1557 }
1558
1559 static ssize_t
1560 mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1561 {
1562         struct cx8802_fh *fh = file->private_data;
1563
1564         return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
1565                                     file->f_flags & O_NONBLOCK);
1566 }
1567
1568 static unsigned int
1569 mpeg_poll(struct file *file, struct poll_table_struct *wait)
1570 {
1571         struct cx8802_fh *fh = file->private_data;
1572
1573         return videobuf_poll_stream(file, &fh->mpegq, wait);
1574 }
1575
1576 static int
1577 mpeg_mmap(struct file *file, struct vm_area_struct * vma)
1578 {
1579         struct cx8802_fh *fh = file->private_data;
1580
1581         return videobuf_mmap_mapper(&fh->mpegq, vma);
1582 }
1583
1584 static struct file_operations mpeg_fops =
1585 {
1586         .owner         = THIS_MODULE,
1587         .open          = mpeg_open,
1588         .release       = mpeg_release,
1589         .read          = mpeg_read,
1590         .poll          = mpeg_poll,
1591         .mmap          = mpeg_mmap,
1592         .ioctl         = mpeg_ioctl,
1593         .llseek        = no_llseek,
1594 };
1595
1596 static struct video_device cx8802_mpeg_template =
1597 {
1598         .name          = "cx8802",
1599         .type          = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
1600         .hardware      = 0,
1601         .fops          = &mpeg_fops,
1602         .minor         = -1,
1603 };
1604
1605 /* ------------------------------------------------------------------ */
1606
1607 static void blackbird_unregister_video(struct cx8802_dev *dev)
1608 {
1609         if (dev->mpeg_dev) {
1610                 if (-1 != dev->mpeg_dev->minor)
1611                         video_unregister_device(dev->mpeg_dev);
1612                 else
1613                         video_device_release(dev->mpeg_dev);
1614                 dev->mpeg_dev = NULL;
1615         }
1616 }
1617
1618 static int blackbird_register_video(struct cx8802_dev *dev)
1619 {
1620         int err;
1621
1622         dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
1623                                        &cx8802_mpeg_template,"mpeg");
1624         err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
1625         if (err < 0) {
1626                 printk(KERN_INFO "%s/2: can't register mpeg device\n",
1627                        dev->core->name);
1628                 return err;
1629         }
1630         printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n",
1631                dev->core->name,dev->mpeg_dev->minor & 0x1f);
1632         return 0;
1633 }
1634
1635 /* ----------------------------------------------------------- */
1636
1637 static int __devinit blackbird_probe(struct pci_dev *pci_dev,
1638                                      const struct pci_device_id *pci_id)
1639 {
1640         struct cx8802_dev *dev;
1641         struct cx88_core  *core;
1642         int err;
1643
1644         /* general setup */
1645         core = cx88_core_get(pci_dev);
1646         if (NULL == core)
1647                 return -EINVAL;
1648
1649         err = -ENODEV;
1650         if (!cx88_boards[core->board].blackbird)
1651                 goto fail_core;
1652
1653         err = -ENOMEM;
1654         dev = kzalloc(sizeof(*dev),GFP_KERNEL);
1655         if (NULL == dev)
1656                 goto fail_core;
1657         dev->pci = pci_dev;
1658         dev->core = core;
1659         dev->width = 720;
1660         dev->height = 576;
1661         memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params));
1662         memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params));
1663
1664         switch (core->board) {
1665         case CX88_BOARD_HAUPPAUGE_ROSLYN:
1666                 if (core->tuner_formats & V4L2_STD_525_60) {
1667                         dev->height = 480;
1668                         dev->params.vi_frame_rate = 30;
1669                 } else {
1670                         dev->height = 576;
1671                         dev->params.vi_frame_rate = 25;
1672                 }
1673                 break;
1674         case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT:
1675                 if (core->tvnorm->id & V4L2_STD_525_60) {
1676                         dev->height = 480;
1677                         dev->params.vi_frame_rate = 30;
1678                 } else {
1679                         dev->height = 576;
1680                         dev->params.vi_frame_rate = 25;
1681                 }
1682                 break;
1683         }
1684
1685         err = cx8802_init_common(dev);
1686         if (0 != err)
1687                 goto fail_free;
1688
1689         /* blackbird stuff */
1690         printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
1691                core->name);
1692         host_setup(dev->core);
1693
1694         list_add_tail(&dev->devlist,&cx8802_devlist);
1695         blackbird_register_video(dev);
1696
1697         /* initial device configuration: needed ? */
1698
1699         return 0;
1700
1701  fail_free:
1702         kfree(dev);
1703  fail_core:
1704         cx88_core_put(core,pci_dev);
1705         return err;
1706 }
1707
1708 static void __devexit blackbird_remove(struct pci_dev *pci_dev)
1709 {
1710         struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
1711
1712         /* blackbird */
1713         blackbird_unregister_video(dev);
1714         list_del(&dev->devlist);
1715
1716         /* common */
1717         cx8802_fini_common(dev);
1718         cx88_core_put(dev->core,dev->pci);
1719         kfree(dev);
1720 }
1721
1722 static struct pci_device_id cx8802_pci_tbl[] = {
1723         {
1724                 .vendor       = 0x14f1,
1725                 .device       = 0x8802,
1726                 .subvendor    = PCI_ANY_ID,
1727                 .subdevice    = PCI_ANY_ID,
1728         },{
1729                 /* --- end of list --- */
1730         }
1731 };
1732 MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
1733
1734 static struct pci_driver blackbird_pci_driver = {
1735         .name     = "cx88-blackbird",
1736         .id_table = cx8802_pci_tbl,
1737         .probe    = blackbird_probe,
1738         .remove   = __devexit_p(blackbird_remove),
1739         .suspend  = cx8802_suspend_common,
1740         .resume   = cx8802_resume_common,
1741 };
1742
1743 static int blackbird_init(void)
1744 {
1745         printk(KERN_INFO "cx2388x blackbird driver version %d.%d.%d loaded\n",
1746                (CX88_VERSION_CODE >> 16) & 0xff,
1747                (CX88_VERSION_CODE >>  8) & 0xff,
1748                CX88_VERSION_CODE & 0xff);
1749 #ifdef SNAPSHOT
1750         printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
1751                SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
1752 #endif
1753         cx88_ioctl_hook = mpeg_do_ioctl;
1754         cx88_ioctl_translator = mpeg_translate_ioctl;
1755         return pci_register_driver(&blackbird_pci_driver);
1756 }
1757
1758 static void blackbird_fini(void)
1759 {
1760         pci_unregister_driver(&blackbird_pci_driver);
1761 }
1762
1763 module_init(blackbird_init);
1764 module_exit(blackbird_fini);
1765
1766 EXPORT_SYMBOL(cx88_ioctl_hook);
1767 EXPORT_SYMBOL(cx88_ioctl_translator);
1768 EXPORT_SYMBOL(blackbird_set_params);
1769 EXPORT_SYMBOL(blackbird_set_dnr_params);
1770
1771 /* ----------------------------------------------------------- */
1772 /*
1773  * Local variables:
1774  * c-basic-offset: 8
1775  * End:
1776  * 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
1777  */