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