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_write_encoder_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_read_encoder_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 static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
153 unsigned int poll_count;
162 The encoder seems to speak entirely using blocks 32 bit words.
163 In ivtv driver terms, this is a mailbox which we populate with
164 data and watch what the hardware does with it. The first word
165 is a set of flags used to control the transaction, the second
166 word is the command to execute, the third byte is zero (ivtv
167 driver suggests that this is some kind of return value), and
168 the fourth byte is a specified timeout (windows driver always
169 uses 0x00060000 except for one case when it is zero). All
170 successive words are the argument words for the command.
172 First, write out the entire set of words, with the first word
175 Next, write out just the first word again, but set it to
176 IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
177 probably means "go").
179 Next, read back 16 words as status. Check the first word,
180 which should have IVTV_MBOX_FIRMWARE_DONE set. If however
181 that bit is not set, then the command isn't done so repeat the
184 Next, read back 32 words and compare with the original
185 arugments. Hopefully they will match.
187 Finally, write out just the first word again, but set it to
188 0x0 this time (which probably means "idle").
193 LOCK_TAKE(hdw->ctl_lock); do {
198 wrData[3] = 0x00060000;
200 for (idx = 0; idx < args; idx++) {
201 wrData[idx+4] = va_arg(vl, u32);
205 while (args < sizeof(wrData)/sizeof(wrData[0])) {
209 ret = pvr2_write_encoder_words(hdw,wrData,args);
211 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
212 ret = pvr2_write_encoder_words(hdw,wrData,1);
216 if (poll_count < 10000000) poll_count++;
217 ret = pvr2_read_encoder_words(hdw,!0,rdData,1);
219 if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
222 if (poll_count == 100) {
224 PVR2_TRACE_ERROR_LEGS,
225 "***WARNING*** device's encoder"
226 " appears to be stuck"
227 " (status=0%08x)",rdData[0]);
229 PVR2_TRACE_ERROR_LEGS,
230 "Encoder command: 0x%02x",cmd);
231 for (idx = 4; idx < args; idx++) {
233 PVR2_TRACE_ERROR_LEGS,
234 "Encoder arg%d: 0x%08x",
238 PVR2_TRACE_ERROR_LEGS,
241 " this is a bad idea...");
248 ret = pvr2_read_encoder_words(hdw,0,rdData,16);
250 for (idx = 0; idx < args; idx++) {
251 if (rdData[idx] != wrData[idx]) {
254 "pvr2_encoder idx %02x mismatch exp:"
256 idx,wrData[idx],rdData[idx]);
261 ret = pvr2_write_encoder_words(hdw,wrData,1);
264 } while(0); LOCK_GIVE(hdw->ctl_lock);
269 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
271 int ret = 0, audio, i;
272 v4l2_std_id vd_std = hdw->std_mask_cur;
273 int height = hdw->res_ver_val;
274 int width = hdw->res_hor_val;
275 int height_full = !hdw->interlace_val;
277 int is_30fps, is_ntsc;
279 if (vd_std & V4L2_STD_NTSC) {
282 } else if (vd_std & V4L2_STD_PAL_M) {
290 pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure");
292 /* set stream output port. Some notes here: The ivtv-derived
293 encoder documentation says that this command only gets a
294 single argument. However the Windows driver for the model
295 29xxx series hardware has been sending 0x01 as a second
296 argument, while the Windows driver for the model 24xxx
297 series hardware has been sending 0x02 as a second argument.
298 Confusing matters further are the observations that 0x01
299 for that second argument simply won't work on the 24xxx
300 hardware, while 0x02 will work on the 29xxx - except that
301 when we use 0x02 then xawtv breaks due to a loss of
302 synchronization with the mpeg packet headers. While xawtv
303 should be fixed to let it resync better (I did try to
304 contact Gerd about this but he has not answered), it has
305 also been determined that sending 0x00 as this mystery
306 second argument seems to work on both hardware models AND
307 xawtv works again. So we're going to send 0x00. */
308 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_OUTPUT_PORT, 2,
311 /* set the Program Index Information. We want I,P,B frames (max 400) */
312 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_PGM_INDEX_INFO, 2,
315 /* NOTE : windows driver sends these */
316 /* Mike Isely <isely@pobox.com> 7-Mar-2006 The windows driver
317 sends the following commands but if we do the same then
318 many apps are no longer able to read the video stream.
319 Leaving these out seems to do no harm at all, so they're
320 commented out for that reason. */
322 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
323 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,1,0,0);
324 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
325 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
326 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
327 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
330 /* Strange compared to ivtv data. */
331 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
334 /* setup firmware to notify us about some events (don't know why...) */
335 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
336 0, 0, 0x10000000, 0xffffffff);
338 /* set fps to 25 or 30 (1 or 0)*/
339 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_RATE, 1,
342 /* set encoding resolution */
343 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_SIZE, 2,
344 (height_full ? height : (height / 2)),
346 /* set encoding aspect ratio to 4:3 */
347 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_ASPECT_RATIO, 1,
352 if (hdw->config == pvr2_config_vbi) {
353 int lines = 2 * (is_30fps ? 12 : 18);
354 int size = (4*((lines*1443+3)/4)) / lines;
355 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_VBI_CONFIG, 7,
357 0x25256262, 0x387f7f7f,
359 // 0x25256262, 0x13135454, lines , size);
360 /* select vbi lines */
361 #define line_used(l) (is_30fps ? (l >= 10 && l <= 21) : (l >= 6 && l <= 23))
362 for (i = 2 ; i <= 24 ; i++){
363 ret |= pvr2_write_encoder_vcmd(
364 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
365 i-1,line_used(i), 0, 0, 0);
366 ret |= pvr2_write_encoder_vcmd(
367 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
369 line_used(i), 0, 0, 0);
372 ret |= pvr2_write_encoder_vcmd(
373 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
377 /* set stream type, depending on resolution. */
378 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_STREAM_TYPE, 1,
379 height_full ? 0x0a : 0x0b);
380 /* set video bitrate */
381 ret |= pvr2_write_encoder_vcmd(
382 hdw, CX2341X_ENC_SET_BIT_RATE, 3,
383 (hdw->vbr_val ? 1 : 0),
384 hdw->videobitrate_val,
385 hdw->videopeak_val / 400);
386 /* setup GOP structure (GOP size = 0f or 0c, 3-1 = 2 B-frames) */
387 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
388 is_30fps ? 0x0f : 0x0c, 0x03);
390 /* enable 3:2 pulldown */
391 ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_3_2_PULLDOWN,1,0);
393 /* set GOP open/close property (open) */
394 ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_GOP_CLOSURE,1,0);
396 /* set audio stream properties 0x40b9? 0100 0000 1011 1001 */
397 audio = (pvr_tbl_audiobitrate[hdw->audiobitrate_val] |
398 pvr_tbl_srate[hdw->srate_val] |
399 hdw->audiolayer_val << 2 |
400 (hdw->audiocrc_val ? 1 << 14 : 0) |
401 pvr_tbl_emphasis[hdw->audioemphasis_val]);
403 ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_AUDIO_PROPERTIES,1,
406 /* set dynamic noise reduction filter to manual, Horiz/Vert */
407 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
410 /* dynamic noise reduction filter param */
411 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2
414 /* dynamic noise reduction median filter */
415 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_CORING_LEVELS, 4,
418 /* spacial prefiler parameter */
419 ret |= pvr2_write_encoder_vcmd(hdw,
420 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
423 /* initialize video input */
424 ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
427 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
433 int pvr2_encoder_start(struct pvr2_hdw *hdw)
437 /* unmask some interrupts */
438 pvr2_write_register(hdw, 0x0048, 0xbfffffff);
440 /* change some GPIO data */
441 pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
442 pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
444 if (hdw->config == pvr2_config_vbi) {
445 status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
447 } else if (hdw->config == pvr2_config_mpeg) {
448 status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
451 status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
455 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
460 int pvr2_encoder_stop(struct pvr2_hdw *hdw)
464 /* mask all interrupts */
465 pvr2_write_register(hdw, 0x0048, 0xffffffff);
467 if (hdw->config == pvr2_config_vbi) {
468 status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
470 } else if (hdw->config == pvr2_config_mpeg) {
471 status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
474 status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
478 /* change some GPIO data */
479 /* Note: Bit d7 of dir appears to control the LED. So we shut it
481 pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
482 pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
485 hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
492 Stuff for Emacs to see, in order to encourage consistent editing style:
493 *** Local Variables: ***
495 *** fill-column: 70 ***
497 *** c-basic-offset: 8 ***