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  
pvr2_encoder_write_words(struct pvr2_hdw * hdw,unsigned int offs,const u32 * data,unsigned int dlen)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  
pvr2_encoder_read_words(struct pvr2_hdw * hdw,unsigned int offs,u32 * data,unsigned int dlen)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. */
pvr2_encoder_cmd(void * ctxt,u32 cmd,int arg_cnt_send,int arg_cnt_recv,u32 * argp)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);
192  	while (1) {
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  
pvr2_encoder_vcmd(struct pvr2_hdw * hdw,int cmd,int args,...)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. */
pvr2_encoder_prep_config(struct pvr2_hdw * hdw)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  
pvr2_encoder_adjust(struct pvr2_hdw * hdw)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  
pvr2_encoder_configure(struct pvr2_hdw * hdw)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  
pvr2_encoder_start(struct pvr2_hdw * hdw)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  
pvr2_encoder_stop(struct pvr2_hdw * hdw)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  }
514