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
26static 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
72static 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. */
127static 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)",
238rdData[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
294static 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. */
321static 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
389int 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
406int 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
463int 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
490int 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