• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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); 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 
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