5 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
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
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.
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
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"
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,
36 static u32 pvr_tbl_srate[] = {
37 [PVR2_CVAL_SRATE_48] = 0x01,
38 [PVR2_CVAL_SRATE_44_1] = 0x00,
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,
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
66 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
67 const u32 *data, unsigned int dlen)
71 unsigned int offs = 0;
72 unsigned int chunkCnt;
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
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),
94 ret = pvr2_send_request(hdw,
95 hdw->cmd_buffer,1+(chunkCnt*7),
107 static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
108 u32 *data, unsigned int dlen)
112 unsigned int offs = 0;
113 unsigned int chunkCnt;
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
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,
133 hdw->cmd_buffer,chunkCnt * 4);
136 for (idx = 0; idx < chunkCnt; idx++) {
137 data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
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,
159 unsigned int poll_count;
162 /* These sizes look to be limited by the FX2 firmware implementation */
165 struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
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.
180 First, write out the entire set of words, with the first word
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").
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
192 Next, read back 32 words and compare with the original
193 arugments. Hopefully they will match.
195 Finally, write out just the first word again, but set it to
196 0x0 this time (which probably means "idle").
200 if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
202 PVR2_TRACE_ERROR_LEGS,
203 "Failed to write cx23416 command"
204 " - too many input arguments"
205 " (was given %u limit %u)",
207 (sizeof(wrData)/sizeof(wrData[0])) - 4);
211 if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
213 PVR2_TRACE_ERROR_LEGS,
214 "Failed to write cx23416 command"
215 " - too many return arguments"
216 " (was given %u limit %u)",
218 (sizeof(rdData)/sizeof(rdData[0])) - 4);
223 LOCK_TAKE(hdw->ctl_lock); do {
228 wrData[3] = 0x00060000;
229 for (idx = 0; idx < arg_cnt_send; idx++) {
230 wrData[idx+4] = argp[idx];
232 for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
236 ret = pvr2_encoder_write_words(hdw,wrData,idx);
238 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
239 ret = pvr2_encoder_write_words(hdw,wrData,1);
243 if (poll_count < 10000000) poll_count++;
244 ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
246 if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
249 if (poll_count == 100) {
251 PVR2_TRACE_ERROR_LEGS,
252 "***WARNING*** device's encoder"
253 " appears to be stuck"
254 " (status=0%08x)",rdData[0]);
256 PVR2_TRACE_ERROR_LEGS,
257 "Encoder command: 0x%02x",cmd);
258 for (idx = 4; idx < arg_cnt_send; idx++) {
260 PVR2_TRACE_ERROR_LEGS,
261 "Encoder arg%d: 0x%08x",
265 PVR2_TRACE_ERROR_LEGS,
268 " this is a bad idea...");
275 ret = pvr2_encoder_read_words(
277 sizeof(rdData)/sizeof(rdData[0]));
279 for (idx = 0; idx < arg_cnt_recv; idx++) {
280 argp[idx] = rdData[idx+4];
284 ret = pvr2_encoder_write_words(hdw,wrData,1);
287 } while(0); LOCK_GIVE(hdw->ctl_lock);
293 static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
300 if (args > sizeof(data)/sizeof(data[0])) {
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]));
311 for (idx = 0; idx < args; idx++) {
312 data[idx] = va_arg(vl, u32);
316 return pvr2_encoder_cmd(hdw,cmd,args,0,data);
320 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
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;
328 int is_30fps, is_ntsc;
330 if (vd_std & V4L2_STD_NTSC) {
333 } else if (vd_std & V4L2_STD_PAL_M) {
341 pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure (native)");
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,
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,
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. */
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);
381 /* Strange compared to ivtv data. */
382 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
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);
389 /* set fps to 25 or 30 (1 or 0)*/
390 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_RATE, 1,
393 /* set encoding resolution */
394 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_SIZE, 2,
395 (height_full ? height : (height / 2)),
397 /* set encoding aspect ratio to 4:3 */
398 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_ASPECT_RATIO, 1,
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,
408 0x25256262, 0x387f7f7f,
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,
420 line_used(i), 0, 0, 0);
423 ret |= pvr2_encoder_vcmd(
424 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
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);
441 /* enable 3:2 pulldown */
442 ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_3_2_PULLDOWN,1,0);
444 /* set GOP open/close property (open) */
445 ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_GOP_CLOSURE,1,0);
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]);
454 ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_AUDIO_PROPERTIES,1,
457 /* set dynamic noise reduction filter to manual, Horiz/Vert */
458 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
461 /* dynamic noise reduction filter param */
462 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2
465 /* dynamic noise reduction median filter */
466 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_CORING_LEVELS, 4,
469 /* spacial prefiler parameter */
470 ret |= pvr2_encoder_vcmd(hdw,
471 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
474 /* initialize video input */
475 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
478 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
484 int pvr2_encoder_start(struct pvr2_hdw *hdw)
488 /* unmask some interrupts */
489 pvr2_write_register(hdw, 0x0048, 0xbfffffff);
491 /* change some GPIO data */
492 pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
493 pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
495 if (hdw->config == pvr2_config_vbi) {
496 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
498 } else if (hdw->config == pvr2_config_mpeg) {
499 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
502 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
506 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
511 int pvr2_encoder_stop(struct pvr2_hdw *hdw)
515 /* mask all interrupts */
516 pvr2_write_register(hdw, 0x0048, 0xffffffff);
518 if (hdw->config == pvr2_config_vbi) {
519 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
521 } else if (hdw->config == pvr2_config_mpeg) {
522 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
525 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
529 /* change some GPIO data */
530 /* Note: Bit d7 of dir appears to control the LED. So we shut it
532 pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
533 pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
536 hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
543 Stuff for Emacs to see, in order to encourage consistent editing style:
544 *** Local Variables: ***
546 *** fill-column: 70 ***
548 *** c-basic-offset: 8 ***