]> err.no Git - linux-2.6/blob - drivers/media/video/pvrusb2/pvrusb2-encoder.c
V4L/DVB (4240): Various V4L control enhancements in pvrusb2
[linux-2.6] / drivers / media / video / pvrusb2 / pvrusb2-encoder.c
1 /*
2  *
3  *  $Id$
4  *
5  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
6  *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License
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
23 #include <linux/device.h>   // for linux/firmware.h
24 #include <linux/firmware.h>
25 #include "pvrusb2-util.h"
26 #include "pvrusb2-encoder.h"
27 #include "pvrusb2-hdw-internal.h"
28 #include "pvrusb2-debug.h"
29
30 static u32 pvr_tbl_emphasis [] = {
31         [PVR2_CVAL_AUDIOEMPHASIS_NONE] = 0x0 << 12,
32         [PVR2_CVAL_AUDIOEMPHASIS_50_15] = 0x1 << 12,
33         [PVR2_CVAL_AUDIOEMPHASIS_CCITT] = 0x3 << 12,
34 };
35
36 static u32 pvr_tbl_srate[] = {
37         [PVR2_CVAL_SRATE_48] =  0x01,
38         [PVR2_CVAL_SRATE_44_1] = 0x00,
39 };
40
41 static u32 pvr_tbl_audiobitrate[] = {
42         [PVR2_CVAL_AUDIOBITRATE_384] = 0xe << 4,
43         [PVR2_CVAL_AUDIOBITRATE_320] = 0xd << 4,
44         [PVR2_CVAL_AUDIOBITRATE_256] = 0xc << 4,
45         [PVR2_CVAL_AUDIOBITRATE_224] = 0xb << 4,
46         [PVR2_CVAL_AUDIOBITRATE_192] = 0xa << 4,
47         [PVR2_CVAL_AUDIOBITRATE_160] = 0x9 << 4,
48         [PVR2_CVAL_AUDIOBITRATE_128] = 0x8 << 4,
49         [PVR2_CVAL_AUDIOBITRATE_112] = 0x7 << 4,
50         [PVR2_CVAL_AUDIOBITRATE_96]  = 0x6 << 4,
51         [PVR2_CVAL_AUDIOBITRATE_80]  = 0x5 << 4,
52         [PVR2_CVAL_AUDIOBITRATE_64]  = 0x4 << 4,
53         [PVR2_CVAL_AUDIOBITRATE_56]  = 0x3 << 4,
54         [PVR2_CVAL_AUDIOBITRATE_48]  = 0x2 << 4,
55         [PVR2_CVAL_AUDIOBITRATE_32]  = 0x1 << 4,
56         [PVR2_CVAL_AUDIOBITRATE_VBR] = 0x0 << 4,
57 };
58
59
60 /* Firmware mailbox flags - definitions found from ivtv */
61 #define IVTV_MBOX_FIRMWARE_DONE 0x00000004
62 #define IVTV_MBOX_DRIVER_DONE 0x00000002
63 #define IVTV_MBOX_DRIVER_BUSY 0x00000001
64
65
66 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
67                                     const u32 *data, unsigned int dlen)
68 {
69         unsigned int idx;
70         int ret;
71         unsigned int offs = 0;
72         unsigned int chunkCnt;
73
74         /*
75
76         Format: First byte must be 0x01.  Remaining 32 bit words are
77         spread out into chunks of 7 bytes each, little-endian ordered,
78         offset at zero within each 2 blank bytes following and a
79         single byte that is 0x44 plus the offset of the word.  Repeat
80         request for additional words, with offset adjusted
81         accordingly.
82
83         */
84         while (dlen) {
85                 chunkCnt = 8;
86                 if (chunkCnt > dlen) chunkCnt = dlen;
87                 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
88                 hdw->cmd_buffer[0] = 0x01;
89                 for (idx = 0; idx < chunkCnt; idx++) {
90                         hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs;
91                         PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7),
92                                           data[idx]);
93                 }
94                 ret = pvr2_send_request(hdw,
95                                         hdw->cmd_buffer,1+(chunkCnt*7),
96                                         0,0);
97                 if (ret) return ret;
98                 data += chunkCnt;
99                 dlen -= chunkCnt;
100                 offs += chunkCnt;
101         }
102
103         return 0;
104 }
105
106
107 static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
108                                    u32 *data, unsigned int dlen)
109 {
110         unsigned int idx;
111         int ret;
112         unsigned int offs = 0;
113         unsigned int chunkCnt;
114
115         /*
116
117         Format: First byte must be 0x02 (status check) or 0x28 (read
118         back block of 32 bit words).  Next 6 bytes must be zero,
119         followed by a single byte of 0x44+offset for portion to be
120         read.  Returned data is packed set of 32 bits words that were
121         read.
122
123         */
124
125         while (dlen) {
126                 chunkCnt = 16;
127                 if (chunkCnt > dlen) chunkCnt = dlen;
128                 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
129                 hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28;
130                 hdw->cmd_buffer[7] = 0x44 + offs;
131                 ret = pvr2_send_request(hdw,
132                                         hdw->cmd_buffer,8,
133                                         hdw->cmd_buffer,chunkCnt * 4);
134                 if (ret) return ret;
135
136                 for (idx = 0; idx < chunkCnt; idx++) {
137                         data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
138                 }
139                 data += chunkCnt;
140                 dlen -= chunkCnt;
141                 offs += chunkCnt;
142         }
143
144         return 0;
145 }
146
147
148 /* This prototype is set up to be compatible with the
149    cx2341x_mbox_func prototype in cx2341x.h, which should be in
150    kernels 2.6.18 or later.  We do this so that we can enable
151    cx2341x.ko to write to our encoder (by handing it a pointer to this
152    function).  For earlier kernels this doesn't really matter. */
153 static int pvr2_encoder_cmd(void *ctxt,
154                             int cmd,
155                             int arg_cnt_send,
156                             int arg_cnt_recv,
157                             u32 *argp)
158 {
159         unsigned int poll_count;
160         int ret = 0;
161         unsigned int idx;
162         /* These sizes look to be limited by the FX2 firmware implementation */
163         u32 wrData[16];
164         u32 rdData[16];
165         struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
166
167
168         /*
169
170         The encoder seems to speak entirely using blocks 32 bit words.
171         In ivtv driver terms, this is a mailbox which we populate with
172         data and watch what the hardware does with it.  The first word
173         is a set of flags used to control the transaction, the second
174         word is the command to execute, the third byte is zero (ivtv
175         driver suggests that this is some kind of return value), and
176         the fourth byte is a specified timeout (windows driver always
177         uses 0x00060000 except for one case when it is zero).  All
178         successive words are the argument words for the command.
179
180         First, write out the entire set of words, with the first word
181         being zero.
182
183         Next, write out just the first word again, but set it to
184         IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
185         probably means "go").
186
187         Next, read back 16 words as status.  Check the first word,
188         which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
189         that bit is not set, then the command isn't done so repeat the
190         read.
191
192         Next, read back 32 words and compare with the original
193         arugments.  Hopefully they will match.
194
195         Finally, write out just the first word again, but set it to
196         0x0 this time (which probably means "idle").
197
198         */
199
200         if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
201                 pvr2_trace(
202                         PVR2_TRACE_ERROR_LEGS,
203                         "Failed to write cx23416 command"
204                         " - too many input arguments"
205                         " (was given %u limit %u)",
206                         arg_cnt_send,
207                         (sizeof(wrData)/sizeof(wrData[0])) - 4);
208                 return -EINVAL;
209         }
210
211         if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
212                 pvr2_trace(
213                         PVR2_TRACE_ERROR_LEGS,
214                         "Failed to write cx23416 command"
215                         " - too many return arguments"
216                         " (was given %u limit %u)",
217                         arg_cnt_recv,
218                         (sizeof(rdData)/sizeof(rdData[0])) - 4);
219                 return -EINVAL;
220         }
221
222
223         LOCK_TAKE(hdw->ctl_lock); do {
224
225                 wrData[0] = 0;
226                 wrData[1] = cmd;
227                 wrData[2] = 0;
228                 wrData[3] = 0x00060000;
229                 for (idx = 0; idx < arg_cnt_send; idx++) {
230                         wrData[idx+4] = argp[idx];
231                 }
232                 for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
233                         wrData[idx+4] = 0;
234                 }
235
236                 ret = pvr2_encoder_write_words(hdw,wrData,idx);
237                 if (ret) break;
238                 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
239                 ret = pvr2_encoder_write_words(hdw,wrData,1);
240                 if (ret) break;
241                 poll_count = 0;
242                 while (1) {
243                         if (poll_count < 10000000) poll_count++;
244                         ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
245                         if (ret) break;
246                         if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
247                                 break;
248                         }
249                         if (poll_count == 100) {
250                                 pvr2_trace(
251                                         PVR2_TRACE_ERROR_LEGS,
252                                         "***WARNING*** device's encoder"
253                                         " appears to be stuck"
254                                         " (status=0%08x)",rdData[0]);
255                                 pvr2_trace(
256                                         PVR2_TRACE_ERROR_LEGS,
257                                         "Encoder command: 0x%02x",cmd);
258                                 for (idx = 4; idx < arg_cnt_send; idx++) {
259                                         pvr2_trace(
260                                                 PVR2_TRACE_ERROR_LEGS,
261                                                 "Encoder arg%d: 0x%08x",
262                                                 idx-3,wrData[idx]);
263                                 }
264                                 pvr2_trace(
265                                         PVR2_TRACE_ERROR_LEGS,
266                                         "Giving up waiting."
267                                         "  It is likely that"
268                                         " this is a bad idea...");
269                                 ret = -EBUSY;
270                                 break;
271                         }
272                 }
273                 if (ret) break;
274                 wrData[0] = 0x7;
275                 ret = pvr2_encoder_read_words(
276                         hdw,0,rdData,
277                         sizeof(rdData)/sizeof(rdData[0]));
278                 if (ret) break;
279                 for (idx = 0; idx < arg_cnt_recv; idx++) {
280                         argp[idx] = rdData[idx+4];
281                 }
282
283                 wrData[0] = 0x0;
284                 ret = pvr2_encoder_write_words(hdw,wrData,1);
285                 if (ret) break;
286
287         } while(0); LOCK_GIVE(hdw->ctl_lock);
288
289         return ret;
290 }
291
292
293 static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
294                              int args, ...)
295 {
296         va_list vl;
297         unsigned int idx;
298         u32 data[12];
299
300         if (args > sizeof(data)/sizeof(data[0])) {
301                 pvr2_trace(
302                         PVR2_TRACE_ERROR_LEGS,
303                         "Failed to write cx23416 command"
304                         " - too many arguments"
305                         " (was given %u limit %u)",
306                         args,sizeof(data)/sizeof(data[0]));
307                 return -EINVAL;
308         }
309
310         va_start(vl, args);
311         for (idx = 0; idx < args; idx++) {
312                 data[idx] = va_arg(vl, u32);
313         }
314         va_end(vl);
315
316         return pvr2_encoder_cmd(hdw,cmd,args,0,data);
317 }
318
319
320 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
321 {
322         int ret = 0, audio, i;
323         v4l2_std_id vd_std = hdw->std_mask_cur;
324         int height = hdw->res_ver_val;
325         int width = hdw->res_hor_val;
326         int height_full = !hdw->interlace_val;
327
328         int is_30fps, is_ntsc;
329
330         if (vd_std & V4L2_STD_NTSC) {
331                 is_ntsc=1;
332                 is_30fps=1;
333         } else if (vd_std & V4L2_STD_PAL_M) {
334                 is_ntsc=0;
335                 is_30fps=1;
336         } else {
337                 is_ntsc=0;
338                 is_30fps=0;
339         }
340
341         pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure (native)");
342
343         /* set stream output port.  Some notes here: The ivtv-derived
344            encoder documentation says that this command only gets a
345            single argument.  However the Windows driver for the model
346            29xxx series hardware has been sending 0x01 as a second
347            argument, while the Windows driver for the model 24xxx
348            series hardware has been sending 0x02 as a second argument.
349            Confusing matters further are the observations that 0x01
350            for that second argument simply won't work on the 24xxx
351            hardware, while 0x02 will work on the 29xxx - except that
352            when we use 0x02 then xawtv breaks due to a loss of
353            synchronization with the mpeg packet headers.  While xawtv
354            should be fixed to let it resync better (I did try to
355            contact Gerd about this but he has not answered), it has
356            also been determined that sending 0x00 as this mystery
357            second argument seems to work on both hardware models AND
358            xawtv works again.  So we're going to send 0x00. */
359         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_OUTPUT_PORT, 2,
360                                  0x01, 0x00);
361
362         /* set the Program Index Information. We want I,P,B frames (max 400) */
363         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_PGM_INDEX_INFO, 2,
364                                  0x07, 0x0190);
365
366         /* NOTE : windows driver sends these */
367         /* Mike Isely <isely@pobox.com> 7-Mar-2006 The windows driver
368            sends the following commands but if we do the same then
369            many apps are no longer able to read the video stream.
370            Leaving these out seems to do no harm at all, so they're
371            commented out for that reason. */
372 #ifdef notdef
373         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
374         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,1,0,0);
375         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
376         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
377         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
378         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
379 #endif
380
381         /* Strange compared to ivtv data. */
382         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
383                                  0xf0, 0xf0);
384
385         /* setup firmware to notify us about some events (don't know why...) */
386         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
387                                  0, 0, 0x10000000, 0xffffffff);
388
389         /* set fps to 25 or 30 (1 or 0)*/
390         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_RATE, 1,
391                                  is_30fps ? 0 : 1);
392
393         /* set encoding resolution */
394         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_SIZE, 2,
395                                  (height_full ? height : (height / 2)),
396                                  width);
397         /* set encoding aspect ratio to 4:3 */
398         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_ASPECT_RATIO, 1,
399                                  0x02);
400
401         /* VBI */
402
403         if (hdw->config == pvr2_config_vbi) {
404                 int lines = 2 * (is_30fps ? 12 : 18);
405                 int size = (4*((lines*1443+3)/4)) / lines;
406                 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_VBI_CONFIG, 7,
407                                          0xbd05, 1, 4,
408                                          0x25256262, 0x387f7f7f,
409                                          lines , size);
410 //                                     0x25256262, 0x13135454, lines , size);
411                 /* select vbi lines */
412 #define line_used(l)  (is_30fps ? (l >= 10 && l <= 21) : (l >= 6 && l <= 23))
413                 for (i = 2 ; i <= 24 ; i++){
414                         ret |= pvr2_encoder_vcmd(
415                                 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
416                                 i-1,line_used(i), 0, 0, 0);
417                         ret |= pvr2_encoder_vcmd(
418                                 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
419                                 (i-1) | (1 << 31),
420                                 line_used(i), 0, 0, 0);
421                 }
422         } else {
423                 ret |= pvr2_encoder_vcmd(
424                         hdw,CX2341X_ENC_SET_VBI_LINE, 5,
425                         0xffffffff,0,0,0,0);
426         }
427
428         /* set stream type, depending on resolution. */
429         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_STREAM_TYPE, 1,
430                                  height_full ? 0x0a : 0x0b);
431         /* set video bitrate */
432         ret |= pvr2_encoder_vcmd(
433                 hdw, CX2341X_ENC_SET_BIT_RATE, 3,
434                 (hdw->vbr_val ? 1 : 0),
435                 hdw->videobitrate_val,
436                 hdw->videopeak_val / 400);
437         /* setup GOP structure (GOP size = 0f or 0c, 3-1 = 2 B-frames) */
438         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
439                                  is_30fps ?  0x0f : 0x0c, 0x03);
440
441         /* enable 3:2 pulldown */
442         ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_3_2_PULLDOWN,1,0);
443
444         /* set GOP open/close property (open) */
445         ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_GOP_CLOSURE,1,0);
446
447         /* set audio stream properties 0x40b9? 0100 0000 1011 1001 */
448         audio = (pvr_tbl_audiobitrate[hdw->audiobitrate_val] |
449                  pvr_tbl_srate[hdw->srate_val] |
450                  hdw->audiolayer_val << 2 |
451                  (hdw->audiocrc_val ? 1 << 14 : 0) |
452                  pvr_tbl_emphasis[hdw->audioemphasis_val]);
453
454         ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_AUDIO_PROPERTIES,1,
455                                  audio);
456
457         /* set dynamic noise reduction filter to manual, Horiz/Vert */
458         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
459                                  0, 0x03);
460
461         /* dynamic noise reduction filter param */
462         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2
463                                  , 0, 0);
464
465         /* dynamic noise reduction median filter */
466         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_CORING_LEVELS, 4,
467                                  0, 0xff, 0, 0xff);
468
469         /* spacial prefiler parameter */
470         ret |= pvr2_encoder_vcmd(hdw,
471                                  CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
472                                  0x01, 0x01);
473
474         /* initialize video input */
475         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
476
477         if (!ret) {
478                 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
479         }
480
481         return ret;
482 }
483
484 int pvr2_encoder_start(struct pvr2_hdw *hdw)
485 {
486         int status;
487
488         /* unmask some interrupts */
489         pvr2_write_register(hdw, 0x0048, 0xbfffffff);
490
491         /* change some GPIO data */
492         pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
493         pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
494
495         if (hdw->config == pvr2_config_vbi) {
496                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
497                                            0x01,0x14);
498         } else if (hdw->config == pvr2_config_mpeg) {
499                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
500                                            0,0x13);
501         } else {
502                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
503                                            0,0x13);
504         }
505         if (!status) {
506                 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
507         }
508         return status;
509 }
510
511 int pvr2_encoder_stop(struct pvr2_hdw *hdw)
512 {
513         int status;
514
515         /* mask all interrupts */
516         pvr2_write_register(hdw, 0x0048, 0xffffffff);
517
518         if (hdw->config == pvr2_config_vbi) {
519                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
520                                            0x01,0x01,0x14);
521         } else if (hdw->config == pvr2_config_mpeg) {
522                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
523                                            0x01,0,0x13);
524         } else {
525                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
526                                            0x01,0,0x13);
527         }
528
529         /* change some GPIO data */
530         /* Note: Bit d7 of dir appears to control the LED.  So we shut it
531            off here. */
532         pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
533         pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
534
535         if (!status) {
536                 hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
537         }
538         return status;
539 }
540
541
542 /*
543   Stuff for Emacs to see, in order to encourage consistent editing style:
544   *** Local Variables: ***
545   *** mode: c ***
546   *** fill-column: 70 ***
547   *** tab-width: 8 ***
548   *** c-basic-offset: 8 ***
549   *** End: ***
550   */