Linux-libre 5.4.48-gnu
[librecmc/linux-libre.git] / drivers / media / usb / pvrusb2 / pvrusb2-encoder.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *
4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
5  *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
6  */
7
8 #include <linux/device.h>   // for linux/firmware.h
9 #include <linux/firmware.h>
10 #include "pvrusb2-util.h"
11 #include "pvrusb2-encoder.h"
12 #include "pvrusb2-hdw-internal.h"
13 #include "pvrusb2-debug.h"
14 #include "pvrusb2-fx2-cmd.h"
15
16
17
18 /* Firmware mailbox flags - definitions found from ivtv */
19 #define IVTV_MBOX_FIRMWARE_DONE 0x00000004
20 #define IVTV_MBOX_DRIVER_DONE 0x00000002
21 #define IVTV_MBOX_DRIVER_BUSY 0x00000001
22
23 #define MBOX_BASE 0x44
24
25
26 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
27                                     unsigned int offs,
28                                     const u32 *data, unsigned int dlen)
29 {
30         unsigned int idx,addr;
31         unsigned int bAddr;
32         int ret;
33         unsigned int chunkCnt;
34
35         /*
36
37         Format: First byte must be 0x01.  Remaining 32 bit words are
38         spread out into chunks of 7 bytes each, with the first 4 bytes
39         being the data word (little endian), and the next 3 bytes
40         being the address where that data word is to be written (big
41         endian).  Repeat request for additional words, with offset
42         adjusted accordingly.
43
44         */
45         while (dlen) {
46                 chunkCnt = 8;
47                 if (chunkCnt > dlen) chunkCnt = dlen;
48                 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
49                 bAddr = 0;
50                 hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
51                 for (idx = 0; idx < chunkCnt; idx++) {
52                         addr = idx + offs;
53                         hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
54                         hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
55                         hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
56                         PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
57                         bAddr += 7;
58                 }
59                 ret = pvr2_send_request(hdw,
60                                         hdw->cmd_buffer,1+(chunkCnt*7),
61                                         NULL,0);
62                 if (ret) return ret;
63                 data += chunkCnt;
64                 dlen -= chunkCnt;
65                 offs += chunkCnt;
66         }
67
68         return 0;
69 }
70
71
72 static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
73                                    unsigned int offs,
74                                    u32 *data, unsigned int dlen)
75 {
76         unsigned int idx;
77         int ret;
78         unsigned int chunkCnt;
79
80         /*
81
82         Format: First byte must be 0x02 (status check) or 0x28 (read
83         back block of 32 bit words).  Next 6 bytes must be zero,
84         followed by a single byte of MBOX_BASE+offset for portion to
85         be read.  Returned data is packed set of 32 bits words that
86         were read.
87
88         */
89
90         while (dlen) {
91                 chunkCnt = 16;
92                 if (chunkCnt > dlen) chunkCnt = dlen;
93                 if (chunkCnt < 16) chunkCnt = 1;
94                 hdw->cmd_buffer[0] =
95                         ((chunkCnt == 1) ?
96                          FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
97                 hdw->cmd_buffer[1] = 0;
98                 hdw->cmd_buffer[2] = 0;
99                 hdw->cmd_buffer[3] = 0;
100                 hdw->cmd_buffer[4] = 0;
101                 hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
102                 hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
103                 hdw->cmd_buffer[7] = (offs & 0xffu);
104                 ret = pvr2_send_request(hdw,
105                                         hdw->cmd_buffer,8,
106                                         hdw->cmd_buffer,
107                                         (chunkCnt == 1 ? 4 : 16 * 4));
108                 if (ret) return ret;
109
110                 for (idx = 0; idx < chunkCnt; idx++) {
111                         data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
112                 }
113                 data += chunkCnt;
114                 dlen -= chunkCnt;
115                 offs += chunkCnt;
116         }
117
118         return 0;
119 }
120
121
122 /* This prototype is set up to be compatible with the
123    cx2341x_mbox_func prototype in cx2341x.h, which should be in
124    kernels 2.6.18 or later.  We do this so that we can enable
125    cx2341x.ko to write to our encoder (by handing it a pointer to this
126    function).  For earlier kernels this doesn't really matter. */
127 static int pvr2_encoder_cmd(void *ctxt,
128                             u32 cmd,
129                             int arg_cnt_send,
130                             int arg_cnt_recv,
131                             u32 *argp)
132 {
133         unsigned int poll_count;
134         unsigned int try_count = 0;
135         int retry_flag;
136         int ret = 0;
137         unsigned int idx;
138         /* These sizes look to be limited by the FX2 firmware implementation */
139         u32 wrData[16];
140         u32 rdData[16];
141         struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
142
143
144         /*
145
146         The encoder seems to speak entirely using blocks 32 bit words.
147         In ivtv driver terms, this is a mailbox at MBOX_BASE which we
148         populate with data and watch what the hardware does with it.
149         The first word is a set of flags used to control the
150         transaction, the second word is the command to execute, the
151         third byte is zero (ivtv driver suggests that this is some
152         kind of return value), and the fourth byte is a specified
153         timeout (windows driver always uses 0x00060000 except for one
154         case when it is zero).  All successive words are the argument
155         words for the command.
156
157         First, write out the entire set of words, with the first word
158         being zero.
159
160         Next, write out just the first word again, but set it to
161         IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
162         probably means "go").
163
164         Next, read back the return count words.  Check the first word,
165         which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
166         that bit is not set, then the command isn't done so repeat the
167         read until it is set.
168
169         Finally, write out just the first word again, but set it to
170         0x0 this time (which probably means "idle").
171
172         */
173
174         if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
175                 pvr2_trace(
176                         PVR2_TRACE_ERROR_LEGS,
177                         "Failed to write cx23416 command - too many input arguments (was given %u limit %lu)",
178                         arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
179                 return -EINVAL;
180         }
181
182         if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
183                 pvr2_trace(
184                         PVR2_TRACE_ERROR_LEGS,
185                         "Failed to write cx23416 command - too many return arguments (was given %u limit %lu)",
186                         arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
187                 return -EINVAL;
188         }
189
190
191         LOCK_TAKE(hdw->ctl_lock); while (1) {
192
193                 if (!hdw->state_encoder_ok) {
194                         ret = -EIO;
195                         break;
196                 }
197
198                 retry_flag = 0;
199                 try_count++;
200                 ret = 0;
201                 wrData[0] = 0;
202                 wrData[1] = cmd;
203                 wrData[2] = 0;
204                 wrData[3] = 0x00060000;
205                 for (idx = 0; idx < arg_cnt_send; idx++) {
206                         wrData[idx+4] = argp[idx];
207                 }
208                 for (; idx < ARRAY_SIZE(wrData) - 4; idx++) {
209                         wrData[idx+4] = 0;
210                 }
211
212                 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
213                 if (ret) break;
214                 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
215                 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
216                 if (ret) break;
217                 poll_count = 0;
218                 while (1) {
219                         poll_count++;
220                         ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
221                                                       arg_cnt_recv+4);
222                         if (ret) {
223                                 break;
224                         }
225                         if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
226                                 break;
227                         }
228                         if (rdData[0] && (poll_count < 1000)) continue;
229                         if (!rdData[0]) {
230                                 retry_flag = !0;
231                                 pvr2_trace(
232                                         PVR2_TRACE_ERROR_LEGS,
233                                         "Encoder timed out waiting for us; arranging to retry");
234                         } else {
235                                 pvr2_trace(
236                                         PVR2_TRACE_ERROR_LEGS,
237                                         "***WARNING*** device's encoder appears to be stuck (status=0x%08x)",
238 rdData[0]);
239                         }
240                         pvr2_trace(
241                                 PVR2_TRACE_ERROR_LEGS,
242                                 "Encoder command: 0x%02x",cmd);
243                         for (idx = 4; idx < arg_cnt_send; idx++) {
244                                 pvr2_trace(
245                                         PVR2_TRACE_ERROR_LEGS,
246                                         "Encoder arg%d: 0x%08x",
247                                         idx-3,wrData[idx]);
248                         }
249                         ret = -EBUSY;
250                         break;
251                 }
252                 if (retry_flag) {
253                         if (try_count < 20) continue;
254                         pvr2_trace(
255                                 PVR2_TRACE_ERROR_LEGS,
256                                 "Too many retries...");
257                         ret = -EBUSY;
258                 }
259                 if (ret) {
260                         del_timer_sync(&hdw->encoder_run_timer);
261                         hdw->state_encoder_ok = 0;
262                         pvr2_trace(PVR2_TRACE_STBITS,
263                                    "State bit %s <-- %s",
264                                    "state_encoder_ok",
265                                    (hdw->state_encoder_ok ? "true" : "false"));
266                         if (hdw->state_encoder_runok) {
267                                 hdw->state_encoder_runok = 0;
268                                 pvr2_trace(PVR2_TRACE_STBITS,
269                                    "State bit %s <-- %s",
270                                            "state_encoder_runok",
271                                            (hdw->state_encoder_runok ?
272                                             "true" : "false"));
273                         }
274                         pvr2_trace(
275                                 PVR2_TRACE_ERROR_LEGS,
276                                 "Giving up on command.  This is normally recovered via a firmware reload and re-initialization; concern is only warranted if this happens repeatedly and rapidly.");
277                         break;
278                 }
279                 wrData[0] = 0x7;
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,MBOX_BASE,wrData,1);
286                 break;
287
288         }; 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 > ARRAY_SIZE(data)) {
302                 pvr2_trace(
303                         PVR2_TRACE_ERROR_LEGS,
304                         "Failed to write cx23416 command - too many arguments (was given %u limit %lu)",
305                         args, (long unsigned) ARRAY_SIZE(data));
306                 return -EINVAL;
307         }
308
309         va_start(vl, args);
310         for (idx = 0; idx < args; idx++) {
311                 data[idx] = va_arg(vl, u32);
312         }
313         va_end(vl);
314
315         return pvr2_encoder_cmd(hdw,cmd,args,0,data);
316 }
317
318
319 /* This implements some extra setup for the encoder that seems to be
320    specific to the PVR USB2 hardware. */
321 static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
322 {
323         int ret = 0;
324         int encMisc3Arg = 0;
325
326 #if 0
327         /* This inexplicable bit happens in the Hauppauge windows
328            driver (for both 24xxx and 29xxx devices).  However I
329            currently see no difference in behavior with or without
330            this stuff.  Leave this here as a note of its existence,
331            but don't use it. */
332         LOCK_TAKE(hdw->ctl_lock); do {
333                 u32 dat[1];
334                 dat[0] = 0x80000640;
335                 pvr2_encoder_write_words(hdw,0x01fe,dat,1);
336                 pvr2_encoder_write_words(hdw,0x023e,dat,1);
337         } while(0); LOCK_GIVE(hdw->ctl_lock);
338 #endif
339
340         /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver
341            sends the following list of ENC_MISC commands (for both
342            24xxx and 29xxx devices).  Meanings are not entirely clear,
343            however without the ENC_MISC(3,1) command then we risk
344            random perpetual video corruption whenever the video input
345            breaks up for a moment (like when switching channels). */
346
347
348 #if 0
349         /* This ENC_MISC(5,0) command seems to hurt 29xxx sync
350            performance on channel changes, but is not a problem on
351            24xxx devices. */
352         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
353 #endif
354
355         /* This ENC_MISC(3,encMisc3Arg) command is critical - without
356            it there will eventually be video corruption.  Also, the
357            saa7115 case is strange - the Windows driver is passing 1
358            regardless of device type but if we have 1 for saa7115
359            devices the video turns sluggish.  */
360         if (hdw->hdw_desc->flag_has_cx25840) {
361                 encMisc3Arg = 1;
362         } else {
363                 encMisc3Arg = 0;
364         }
365         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
366                                  encMisc3Arg,0,0);
367
368         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
369
370 #if 0
371         /* This ENC_MISC(4,1) command is poisonous, so it is commented
372            out.  But I'm leaving it here anyway to document its
373            existence in the Windows driver.  The effect of this
374            command is that apps displaying the stream become sluggish
375            with stuttering video. */
376         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
377 #endif
378
379         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
380         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
381
382         /* prevent the PTSs from slowly drifting away in the generated
383            MPEG stream */
384         ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
385
386         return ret;
387 }
388
389 int pvr2_encoder_adjust(struct pvr2_hdw *hdw)
390 {
391         int ret;
392         ret = cx2341x_update(hdw,pvr2_encoder_cmd,
393                              (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
394                              &hdw->enc_ctl_state);
395         if (ret) {
396                 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
397                            "Error from cx2341x module code=%d",ret);
398         } else {
399                 hdw->enc_cur_state = hdw->enc_ctl_state;
400                 hdw->enc_cur_valid = !0;
401         }
402         return ret;
403 }
404
405
406 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
407 {
408         int ret;
409         int val;
410         pvr2_trace(PVR2_TRACE_ENCODER, "pvr2_encoder_configure (cx2341x module)");
411         hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
412         hdw->enc_ctl_state.width = hdw->res_hor_val;
413         hdw->enc_ctl_state.height = hdw->res_ver_val;
414         hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
415                                       0 : 1);
416
417         ret = 0;
418
419         ret |= pvr2_encoder_prep_config(hdw);
420
421         /* saa7115: 0xf0 */
422         val = 0xf0;
423         if (hdw->hdw_desc->flag_has_cx25840) {
424                 /* ivtv cx25840: 0x140 */
425                 val = 0x140;
426         }
427
428         if (!ret) ret = pvr2_encoder_vcmd(
429                 hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
430                 val, val);
431
432         /* setup firmware to notify us about some events (don't know why...) */
433         if (!ret) ret = pvr2_encoder_vcmd(
434                 hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
435                 0, 0, 0x10000000, 0xffffffff);
436
437         if (!ret) ret = pvr2_encoder_vcmd(
438                 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
439                 0xffffffff,0,0,0,0);
440
441         if (ret) {
442                 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
443                            "Failed to configure cx23416");
444                 return ret;
445         }
446
447         ret = pvr2_encoder_adjust(hdw);
448         if (ret) return ret;
449
450         ret = pvr2_encoder_vcmd(
451                 hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
452
453         if (ret) {
454                 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
455                            "Failed to initialize cx23416 video input");
456                 return ret;
457         }
458
459         return 0;
460 }
461
462
463 int pvr2_encoder_start(struct pvr2_hdw *hdw)
464 {
465         int status;
466
467         /* unmask some interrupts */
468         pvr2_write_register(hdw, 0x0048, 0xbfffffff);
469
470         pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
471                           hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
472
473         switch (hdw->active_stream_type) {
474         case pvr2_config_vbi:
475                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
476                                            0x01,0x14);
477                 break;
478         case pvr2_config_mpeg:
479                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
480                                            0,0x13);
481                 break;
482         default: /* Unhandled cases for now */
483                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
484                                            0,0x13);
485                 break;
486         }
487         return status;
488 }
489
490 int pvr2_encoder_stop(struct pvr2_hdw *hdw)
491 {
492         int status;
493
494         /* mask all interrupts */
495         pvr2_write_register(hdw, 0x0048, 0xffffffff);
496
497         switch (hdw->active_stream_type) {
498         case pvr2_config_vbi:
499                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
500                                            0x01,0x01,0x14);
501                 break;
502         case pvr2_config_mpeg:
503                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
504                                            0x01,0,0x13);
505                 break;
506         default: /* Unhandled cases for now */
507                 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
508                                            0x01,0,0x13);
509                 break;
510         }
511
512         return status;
513 }