fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.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 "pvrusb2-util.h"
26 #include "pvrusb2-encoder.h"
27 #include "pvrusb2-hdw-internal.h"
28 #include "pvrusb2-debug.h"
29
30
31
32 /* Firmware mailbox flags - definitions found from ivtv */
33 #define IVTV_MBOX_FIRMWARE_DONE 0x00000004
34 #define IVTV_MBOX_DRIVER_DONE 0x00000002
35 #define IVTV_MBOX_DRIVER_BUSY 0x00000001
36
37
38 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
39                                     const u32 *data, unsigned int dlen)
40 {
41         unsigned int idx;
42         int ret;
43         unsigned int offs = 0;
44         unsigned int chunkCnt;
45
46         /*
47
48         Format: First byte must be 0x01.  Remaining 32 bit words are
49         spread out into chunks of 7 bytes each, little-endian ordered,
50         offset at zero within each 2 blank bytes following and a
51         single byte that is 0x44 plus the offset of the word.  Repeat
52         request for additional words, with offset adjusted
53         accordingly.
54
55         */
56         while (dlen) {
57                 chunkCnt = 8;
58                 if (chunkCnt > dlen) chunkCnt = dlen;
59                 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
60                 hdw->cmd_buffer[0] = 0x01;
61                 for (idx = 0; idx < chunkCnt; idx++) {
62                         hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs;
63                         PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7),
64                                           data[idx]);
65                 }
66                 ret = pvr2_send_request(hdw,
67                                         hdw->cmd_buffer,1+(chunkCnt*7),
68                                         NULL,0);
69                 if (ret) return ret;
70                 data += chunkCnt;
71                 dlen -= chunkCnt;
72                 offs += chunkCnt;
73         }
74
75         return 0;
76 }
77
78
79 static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
80                                    u32 *data, unsigned int dlen)
81 {
82         unsigned int idx;
83         int ret;
84         unsigned int offs = 0;
85         unsigned int chunkCnt;
86
87         /*
88
89         Format: First byte must be 0x02 (status check) or 0x28 (read
90         back block of 32 bit words).  Next 6 bytes must be zero,
91         followed by a single byte of 0x44+offset for portion to be
92         read.  Returned data is packed set of 32 bits words that were
93         read.
94
95         */
96
97         while (dlen) {
98                 chunkCnt = 16;
99                 if (chunkCnt > dlen) chunkCnt = dlen;
100                 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
101                 hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28;
102                 hdw->cmd_buffer[7] = 0x44 + offs;
103                 ret = pvr2_send_request(hdw,
104                                         hdw->cmd_buffer,8,
105                                         hdw->cmd_buffer,chunkCnt * 4);
106                 if (ret) return ret;
107
108                 for (idx = 0; idx < chunkCnt; idx++) {
109                         data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
110                 }
111                 data += chunkCnt;
112                 dlen -= chunkCnt;
113                 offs += chunkCnt;
114         }
115
116         return 0;
117 }
118
119
120 /* This prototype is set up to be compatible with the
121    cx2341x_mbox_func prototype in cx2341x.h, which should be in
122    kernels 2.6.18 or later.  We do this so that we can enable
123    cx2341x.ko to write to our encoder (by handing it a pointer to this
124    function).  For earlier kernels this doesn't really matter. */
125 static int pvr2_encoder_cmd(void *ctxt,
126                             int cmd,
127                             int arg_cnt_send,
128                             int arg_cnt_recv,
129                             u32 *argp)
130 {
131         unsigned int poll_count;
132         int ret = 0;
133         unsigned int idx;
134         /* These sizes look to be limited by the FX2 firmware implementation */
135         u32 wrData[16];
136         u32 rdData[16];
137         struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
138
139
140         /*
141
142         The encoder seems to speak entirely using blocks 32 bit words.
143         In ivtv driver terms, this is a mailbox which we populate with
144         data and watch what the hardware does with it.  The first word
145         is a set of flags used to control the transaction, the second
146         word is the command to execute, the third byte is zero (ivtv
147         driver suggests that this is some kind of return value), and
148         the fourth byte is a specified timeout (windows driver always
149         uses 0x00060000 except for one case when it is zero).  All
150         successive words are the argument words for the command.
151
152         First, write out the entire set of words, with the first word
153         being zero.
154
155         Next, write out just the first word again, but set it to
156         IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
157         probably means "go").
158
159         Next, read back 16 words as status.  Check the first word,
160         which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
161         that bit is not set, then the command isn't done so repeat the
162         read.
163
164         Next, read back 32 words and compare with the original
165         arugments.  Hopefully they will match.
166
167         Finally, write out just the first word again, but set it to
168         0x0 this time (which probably means "idle").
169
170         */
171
172         if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
173                 pvr2_trace(
174                         PVR2_TRACE_ERROR_LEGS,
175                         "Failed to write cx23416 command"
176                         " - too many input arguments"
177                         " (was given %u limit %u)",
178                         arg_cnt_send,
179                         (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4);
180                 return -EINVAL;
181         }
182
183         if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
184                 pvr2_trace(
185                         PVR2_TRACE_ERROR_LEGS,
186                         "Failed to write cx23416 command"
187                         " - too many return arguments"
188                         " (was given %u limit %u)",
189                         arg_cnt_recv,
190                         (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4);
191                 return -EINVAL;
192         }
193
194
195         LOCK_TAKE(hdw->ctl_lock); do {
196
197                 wrData[0] = 0;
198                 wrData[1] = cmd;
199                 wrData[2] = 0;
200                 wrData[3] = 0x00060000;
201                 for (idx = 0; idx < arg_cnt_send; idx++) {
202                         wrData[idx+4] = argp[idx];
203                 }
204                 for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
205                         wrData[idx+4] = 0;
206                 }
207
208                 ret = pvr2_encoder_write_words(hdw,wrData,idx);
209                 if (ret) break;
210                 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
211                 ret = pvr2_encoder_write_words(hdw,wrData,1);
212                 if (ret) break;
213                 poll_count = 0;
214                 while (1) {
215                         if (poll_count < 10000000) poll_count++;
216                         ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
217                         if (ret) break;
218                         if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
219                                 break;
220                         }
221                         if (poll_count == 100) {
222                                 pvr2_trace(
223                                         PVR2_TRACE_ERROR_LEGS,
224                                         "***WARNING*** device's encoder"
225                                         " appears to be stuck"
226                                         " (status=0%08x)",rdData[0]);
227                                 pvr2_trace(
228                                         PVR2_TRACE_ERROR_LEGS,
229                                         "Encoder command: 0x%02x",cmd);
230                                 for (idx = 4; idx < arg_cnt_send; idx++) {
231                                         pvr2_trace(
232                                                 PVR2_TRACE_ERROR_LEGS,
233                                                 "Encoder arg%d: 0x%08x",
234                                                 idx-3,wrData[idx]);
235                                 }
236                                 pvr2_trace(
237                                         PVR2_TRACE_ERROR_LEGS,
238                                         "Giving up waiting."
239                                         "  It is likely that"
240                                         " this is a bad idea...");
241                                 ret = -EBUSY;
242                                 break;
243                         }
244                 }
245                 if (ret) break;
246                 wrData[0] = 0x7;
247                 ret = pvr2_encoder_read_words(
248                         hdw,0,rdData,
249                         sizeof(rdData)/sizeof(rdData[0]));
250                 if (ret) break;
251                 for (idx = 0; idx < arg_cnt_recv; idx++) {
252                         argp[idx] = rdData[idx+4];
253                 }
254
255                 wrData[0] = 0x0;
256                 ret = pvr2_encoder_write_words(hdw,wrData,1);
257                 if (ret) break;
258
259         } while(0); LOCK_GIVE(hdw->ctl_lock);
260
261         return ret;
262 }
263
264
265 static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
266                              int args, ...)
267 {
268         va_list vl;
269         unsigned int idx;
270         u32 data[12];
271
272         if (args > sizeof(data)/sizeof(data[0])) {
273                 pvr2_trace(
274                         PVR2_TRACE_ERROR_LEGS,
275                         "Failed to write cx23416 command"
276                         " - too many arguments"
277                         " (was given %u limit %u)",
278                         args,(unsigned int)(sizeof(data)/sizeof(data[0])));
279                 return -EINVAL;
280         }
281
282         va_start(vl, args);
283         for (idx = 0; idx < args; idx++) {
284                 data[idx] = va_arg(vl, u32);
285         }
286         va_end(vl);
287
288         return pvr2_encoder_cmd(hdw,cmd,args,0,data);
289 }
290
291
292 /* This implements some extra setup for the encoder that seems to be
293    specific to the PVR USB2 hardware. */
294 int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
295 {
296         int ret = 0;
297         int encMisc3Arg = 0;
298
299         /* Mike Isely <isely@pobox.com> 22-Feb-2007 The windows driver
300            sends the following list of ENC_MISC commands (for both
301            24xxx and 29xxx devices).  Meanings are not entirely clear,
302            however without the ENC_MISC(3,encMisc3Arg) command then we risk
303            random perpetual video corruption whenever the video input
304            breaks up for a moment (like when switching channels). */
305
306
307         /* This ENC_MISC(3,encMisc3Arg) command is critical - without
308            it there will eventually be video corruption.  Also, the
309            29xxx case is strange - the Windows driver is passing 1
310            regardless of device type but if we have 1 for 29xxx device
311            the video turns sluggish.  */
312         switch (hdw->hdw_type) {
313         case PVR2_HDW_TYPE_24XXX: encMisc3Arg = 1; break;
314         case PVR2_HDW_TYPE_29XXX: encMisc3Arg = 0; break;
315         default: break;
316         }
317         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
318                                  encMisc3Arg,0,0);
319
320         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
321
322         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
323         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
324
325         return ret;
326 }
327
328
329 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
330 {
331         int ret;
332         pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
333                    " (cx2341x module)");
334         hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
335         hdw->enc_ctl_state.width = hdw->res_hor_val;
336         hdw->enc_ctl_state.height = hdw->res_ver_val;
337         hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur &
338                                        (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ?
339                                       0 : 1);
340
341         ret = 0;
342
343         ret |= pvr2_encoder_prep_config(hdw);
344
345         if (!ret) ret = pvr2_encoder_vcmd(
346                 hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
347                 0xf0, 0xf0);
348
349         /* setup firmware to notify us about some events (don't know why...) */
350         if (!ret) ret = pvr2_encoder_vcmd(
351                 hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
352                 0, 0, 0x10000000, 0xffffffff);
353
354         if (!ret) ret = pvr2_encoder_vcmd(
355                 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
356                 0xffffffff,0,0,0,0);
357
358         if (ret) {
359                 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
360                            "Failed to configure cx23416");
361                 return ret;
362         }
363
364         ret = cx2341x_update(hdw,pvr2_encoder_cmd,
365                              (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
366                              &hdw->enc_ctl_state);
367         if (ret) {
368                 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
369                            "Error from cx2341x module code=%d",ret);
370                 return ret;
371         }
372
373         ret = 0;
374
375         if (!ret) ret = pvr2_encoder_vcmd(
376                 hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
377
378         if (ret) {
379                 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
380                            "Failed to initialize cx23416 video input");
381                 return ret;
382         }
383
384         hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
385         memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
386                sizeof(struct cx2341x_mpeg_params));
387         hdw->enc_cur_valid = !0;
388         return 0;
389 }
390
391
392 int pvr2_encoder_start(struct pvr2_hdw *hdw)
393 {
394         int status;
395
396         /* unmask some interrupts */
397         pvr2_write_register(hdw, 0x0048, 0xbfffffff);
398
399         /* change some GPIO data */
400         pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
401         pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
402
403         if (hdw->config == pvr2_config_vbi) {
404                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
405                                            0x01,0x14);
406         } else if (hdw->config == pvr2_config_mpeg) {
407                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
408                                            0,0x13);
409         } else {
410                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
411                                            0,0x13);
412         }
413         if (!status) {
414                 hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
415         }
416         return status;
417 }
418
419 int pvr2_encoder_stop(struct pvr2_hdw *hdw)
420 {
421         int status;
422
423         /* mask all interrupts */
424         pvr2_write_register(hdw, 0x0048, 0xffffffff);
425
426         if (hdw->config == pvr2_config_vbi) {
427                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
428                                            0x01,0x01,0x14);
429         } else if (hdw->config == pvr2_config_mpeg) {
430                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
431                                            0x01,0,0x13);
432         } else {
433                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
434                                            0x01,0,0x13);
435         }
436
437         /* change some GPIO data */
438         /* Note: Bit d7 of dir appears to control the LED.  So we shut it
439            off here. */
440         pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
441         pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
442
443         if (!status) {
444                 hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
445         }
446         return status;
447 }
448
449
450 /*
451   Stuff for Emacs to see, in order to encourage consistent editing style:
452   *** Local Variables: ***
453   *** mode: c ***
454   *** fill-column: 70 ***
455   *** tab-width: 8 ***
456   *** c-basic-offset: 8 ***
457   *** End: ***
458   */