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 <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"
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,
38 static u32 pvr_tbl_srate[] = {
39 [PVR2_CVAL_SRATE_48] = 0x01,
40 [PVR2_CVAL_SRATE_44_1] = 0x00,
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,
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
68 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
69 const u32 *data, unsigned int dlen)
73 unsigned int offs = 0;
74 unsigned int chunkCnt;
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
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),
96 ret = pvr2_send_request(hdw,
97 hdw->cmd_buffer,1+(chunkCnt*7),
109 static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
110 u32 *data, unsigned int dlen)
114 unsigned int offs = 0;
115 unsigned int chunkCnt;
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
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,
135 hdw->cmd_buffer,chunkCnt * 4);
138 for (idx = 0; idx < chunkCnt; idx++) {
139 data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
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,
161 unsigned int poll_count;
164 /* These sizes look to be limited by the FX2 firmware implementation */
167 struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
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.
181 First, write out the entire set of words, with the first word
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").
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
193 Next, read back 32 words and compare with the original
194 arugments. Hopefully they will match.
196 Finally, write out just the first word again, but set it to
197 0x0 this time (which probably means "idle").
201 if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
203 PVR2_TRACE_ERROR_LEGS,
204 "Failed to write cx23416 command"
205 " - too many input arguments"
206 " (was given %u limit %u)",
208 (sizeof(wrData)/sizeof(wrData[0])) - 4);
212 if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
214 PVR2_TRACE_ERROR_LEGS,
215 "Failed to write cx23416 command"
216 " - too many return arguments"
217 " (was given %u limit %u)",
219 (sizeof(rdData)/sizeof(rdData[0])) - 4);
224 LOCK_TAKE(hdw->ctl_lock); do {
229 wrData[3] = 0x00060000;
230 for (idx = 0; idx < arg_cnt_send; idx++) {
231 wrData[idx+4] = argp[idx];
233 for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
237 ret = pvr2_encoder_write_words(hdw,wrData,idx);
239 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
240 ret = pvr2_encoder_write_words(hdw,wrData,1);
244 if (poll_count < 10000000) poll_count++;
245 ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
247 if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
250 if (poll_count == 100) {
252 PVR2_TRACE_ERROR_LEGS,
253 "***WARNING*** device's encoder"
254 " appears to be stuck"
255 " (status=0%08x)",rdData[0]);
257 PVR2_TRACE_ERROR_LEGS,
258 "Encoder command: 0x%02x",cmd);
259 for (idx = 4; idx < arg_cnt_send; idx++) {
261 PVR2_TRACE_ERROR_LEGS,
262 "Encoder arg%d: 0x%08x",
266 PVR2_TRACE_ERROR_LEGS,
269 " this is a bad idea...");
276 ret = pvr2_encoder_read_words(
278 sizeof(rdData)/sizeof(rdData[0]));
280 for (idx = 0; idx < arg_cnt_recv; idx++) {
281 argp[idx] = rdData[idx+4];
285 ret = pvr2_encoder_write_words(hdw,wrData,1);
288 } while(0); LOCK_GIVE(hdw->ctl_lock);
294 static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
301 if (args > sizeof(data)/sizeof(data[0])) {
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]));
312 for (idx = 0; idx < args; idx++) {
313 data[idx] = va_arg(vl, u32);
317 return pvr2_encoder_cmd(hdw,cmd,args,0,data);
321 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
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;
329 int is_30fps, is_ntsc;
331 if (vd_std & V4L2_STD_NTSC) {
334 } else if (vd_std & V4L2_STD_PAL_M) {
342 pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure");
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,
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,
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. */
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);
382 /* Strange compared to ivtv data. */
383 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
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);
390 /* set fps to 25 or 30 (1 or 0)*/
391 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_RATE, 1,
394 /* set encoding resolution */
395 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_SIZE, 2,
396 (height_full ? height : (height / 2)),
398 /* set encoding aspect ratio to 4:3 */
399 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_ASPECT_RATIO, 1,
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,
409 0x25256262, 0x387f7f7f,
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,
421 line_used(i), 0, 0, 0);
424 ret |= pvr2_encoder_vcmd(
425 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
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);
442 /* enable 3:2 pulldown */
443 ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_3_2_PULLDOWN,1,0);
445 /* set GOP open/close property (open) */
446 ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_GOP_CLOSURE,1,0);
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]);
455 ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_AUDIO_PROPERTIES,1,
458 /* set dynamic noise reduction filter to manual, Horiz/Vert */
459 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
462 /* dynamic noise reduction filter param */
463 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2
466 /* dynamic noise reduction median filter */
467 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_CORING_LEVELS, 4,
470 /* spacial prefiler parameter */
471 ret |= pvr2_encoder_vcmd(hdw,
472 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
475 /* initialize video input */
476 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
479 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
485 int pvr2_encoder_start(struct pvr2_hdw *hdw)
489 /* unmask some interrupts */
490 pvr2_write_register(hdw, 0x0048, 0xbfffffff);
492 /* change some GPIO data */
493 pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
494 pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
496 if (hdw->config == pvr2_config_vbi) {
497 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
499 } else if (hdw->config == pvr2_config_mpeg) {
500 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
503 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
507 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
512 int pvr2_encoder_stop(struct pvr2_hdw *hdw)
516 /* mask all interrupts */
517 pvr2_write_register(hdw, 0x0048, 0xffffffff);
519 if (hdw->config == pvr2_config_vbi) {
520 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
522 } else if (hdw->config == pvr2_config_mpeg) {
523 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
526 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
530 /* change some GPIO data */
531 /* Note: Bit d7 of dir appears to control the LED. So we shut it
533 pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
534 pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
537 hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
544 Stuff for Emacs to see, in order to encourage consistent editing style:
545 *** Local Variables: ***
547 *** fill-column: 70 ***
549 *** c-basic-offset: 8 ***