11a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/*
21a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    mailbox functions
31a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
41a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
51a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
61a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
71a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    This program is free software; you can redistribute it and/or modify
81a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    it under the terms of the GNU General Public License as published by
91a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    the Free Software Foundation; either version 2 of the License, or
101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    (at your option) any later version.
111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    This program is distributed in the hope that it will be useful,
131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    but WITHOUT ANY WARRANTY; without even the implied warranty of
141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    GNU General Public License for more details.
161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    You should have received a copy of the GNU General Public License
181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    along with this program; if not, write to the Free Software
191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil */
211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#include <stdarg.h>
231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#include "ivtv-driver.h"
251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#include "ivtv-mailbox.h"
261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* Firmware mailbox flags*/
281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define IVTV_MBOX_DRIVER_DONE   0x00000002
301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define IVTV_MBOX_DRIVER_BUSY   0x00000001
311a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define IVTV_MBOX_FREE 		0x00000000
321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* Firmware mailbox standard timeout */
341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define IVTV_API_STD_TIMEOUT 	0x02000000
351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define API_CACHE 	 (1 << 0) 	/* Allow the command to be stored in the cache */
371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define API_RESULT	 (1 << 1) 	/* Allow 1 second for this cmd to end */
381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define API_FAST_RESULT	 (3 << 1)	/* Allow 0.1 second for this cmd to end */
391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define API_DMA 	 (1 << 3)	/* DMA mailbox, has special handling */
4067632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil#define API_HIGH_VOL 	 (1 << 5)	/* High volume command (i.e. called during encoding or decoding) */
411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define API_NO_WAIT_MB 	 (1 << 4)	/* Command may not wait for a free mailbox */
421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define API_NO_WAIT_RES	 (1 << 5)	/* Command may not wait for the result */
430b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil#define API_NO_POLL	 (1 << 6)	/* Avoid pointless polling */
441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstruct ivtv_api_info {
461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int flags;		/* Flags, see above */
471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	const char *name; 	/* The name of the command */
481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil};
491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#define API_ENTRY(x, f) [x] = { (f), #x }
511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic const struct ivtv_api_info api_info[256] = {
531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* MPEG encoder API */
541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_PING_FW, 			API_FAST_RESULT),
550b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil	API_ENTRY(CX2341X_ENC_START_CAPTURE, 		API_RESULT | API_NO_POLL),
561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_STOP_CAPTURE, 		API_RESULT),
571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_AUDIO_ID, 		API_CACHE),
581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_VIDEO_ID, 		API_CACHE),
591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_PCR_ID, 		API_CACHE),
601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_FRAME_RATE, 		API_CACHE),
611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_FRAME_SIZE, 		API_CACHE),
621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_BIT_RATE, 		API_CACHE),
631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_GOP_PROPERTIES, 	API_CACHE),
641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_ASPECT_RATIO, 	API_CACHE),
651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_MODE, 	API_CACHE),
661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_PROPS, 	API_CACHE),
671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_CORING_LEVELS, 	API_CACHE),
681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 	API_CACHE),
691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_VBI_LINE, 		API_RESULT),
701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_STREAM_TYPE, 		API_CACHE),
711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_OUTPUT_PORT, 		API_CACHE),
721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_AUDIO_PROPERTIES, 	API_CACHE),
731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_HALT_FW, 			API_FAST_RESULT),
741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_GET_VERSION, 		API_FAST_RESULT),
751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_GOP_CLOSURE, 		API_CACHE),
761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_GET_SEQ_END, 		API_RESULT),
771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_PGM_INDEX_INFO, 	API_FAST_RESULT),
781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_VBI_CONFIG, 		API_RESULT),
791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_DMA_BLOCK_SIZE, 	API_CACHE),
801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_10, 	API_FAST_RESULT),
811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_9, 	API_FAST_RESULT),
8267632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil	API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST, 	API_DMA | API_HIGH_VOL),
831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_INITIALIZE_INPUT, 	API_RESULT),
841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_FRAME_DROP_RATE, 	API_CACHE),
851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_PAUSE_ENCODER, 		API_RESULT),
8667632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil	API_ENTRY(CX2341X_ENC_REFRESH_INPUT, 		API_NO_WAIT_MB | API_HIGH_VOL),
871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_COPYRIGHT, 		API_CACHE),
881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_EVENT_NOTIFICATION, 	API_RESULT),
891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_NUM_VSYNC_LINES, 	API_CACHE),
901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_PLACEHOLDER, 		API_CACHE),
911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_MUTE_VIDEO, 		API_RESULT),
921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_MUTE_AUDIO, 		API_RESULT),
931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_SET_VERT_CROP_LINE,	API_FAST_RESULT),
941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_ENC_MISC, 			API_FAST_RESULT),
951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* Obsolete PULLDOWN API command */
961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(0xb1, 				API_CACHE),
971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* MPEG decoder API */
991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_PING_FW, 			API_FAST_RESULT),
1000b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil	API_ENTRY(CX2341X_DEC_START_PLAYBACK, 		API_RESULT | API_NO_POLL),
1011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_STOP_PLAYBACK, 		API_RESULT),
1021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED, 	API_RESULT),
1031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_STEP_VIDEO, 		API_RESULT),
1041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_DMA_BLOCK_SIZE, 	API_CACHE),
1051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_GET_XFER_INFO, 		API_FAST_RESULT),
1061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_GET_DMA_STATUS, 		API_FAST_RESULT),
10767632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil	API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST, 	API_DMA | API_HIGH_VOL),
1081a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_PAUSE_PLAYBACK, 		API_RESULT),
1091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_HALT_FW, 			API_FAST_RESULT),
1101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_STANDARD, 		API_CACHE),
1111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_GET_VERSION, 		API_FAST_RESULT),
1121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_STREAM_INPUT, 	API_CACHE),
1131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_GET_TIMING_INFO, 		API_RESULT /*| API_NO_WAIT_RES*/),
1141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_AUDIO_MODE, 		API_CACHE),
1151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_EVENT_NOTIFICATION, 	API_RESULT),
1161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_DISPLAY_BUFFERS, 	API_CACHE),
1171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_EXTRACT_VBI, 		API_RESULT),
1181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_DECODER_SOURCE, 	API_FAST_RESULT),
1191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_DEC_SET_PREBUFFERING, 	API_CACHE),
1201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* OSD API */
1221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_FRAMEBUFFER, 		API_FAST_RESULT),
1231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_PIXEL_FORMAT, 	API_FAST_RESULT),
1241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_PIXEL_FORMAT, 	API_CACHE),
1251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_STATE, 		API_FAST_RESULT),
1261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_STATE, 		API_CACHE),
1271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_OSD_COORDS, 		API_FAST_RESULT),
1281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_OSD_COORDS, 		API_CACHE),
1291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_SCREEN_COORDS, 	API_FAST_RESULT),
1301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_SCREEN_COORDS, 	API_CACHE),
1311a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_GLOBAL_ALPHA, 	API_FAST_RESULT),
1321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_GLOBAL_ALPHA, 	API_CACHE),
1331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_BLEND_COORDS, 	API_CACHE),
1341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_FLICKER_STATE, 	API_FAST_RESULT),
1351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_FLICKER_STATE, 	API_CACHE),
1361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_BLT_COPY, 		API_RESULT),
1371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_BLT_FILL, 		API_RESULT),
1381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_BLT_TEXT, 		API_RESULT),
1391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 	API_CACHE),
1401a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_CHROMA_KEY, 		API_CACHE),
1411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_GET_ALPHA_CONTENT_INDEX, 	API_FAST_RESULT),
1421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	API_ENTRY(CX2341X_OSD_SET_ALPHA_CONTENT_INDEX, 	API_CACHE)
1431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil};
1441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic int try_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int mb)
1461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
1471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	u32 flags = readl(&mbdata->mbox[mb].flags);
1481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int is_free = flags == IVTV_MBOX_FREE || (flags & IVTV_MBOX_FIRMWARE_DONE);
1491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* if the mailbox is free, then try to claim it */
1511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (is_free && !test_and_set_bit(mb, &mbdata->busy)) {
1521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		write_sync(IVTV_MBOX_DRIVER_BUSY, &mbdata->mbox[mb].flags);
1531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return 1;
1541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
1551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return 0;
1561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
1571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* Try to find a free mailbox. Note mailbox 0 is reserved for DMA and so is not
1591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil   attempted here. */
1601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int flags)
1611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
1621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	unsigned long then = jiffies;
1631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i, mb;
1641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int max_mbox = mbdata->max_mbox;
1651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int retries = 100;
1661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* All slow commands use the same mailbox, serializing them and also
1681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	   leaving the other mailbox free for simple fast commands. */
1691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if ((flags & API_FAST_RESULT) == API_RESULT)
1701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		max_mbox = 1;
1711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* find free non-DMA mailbox */
1731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i < retries; i++) {
1741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		for (mb = 1; mb <= max_mbox; mb++)
1751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			if (try_mailbox(itv, mbdata, mb))
1761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil				return mb;
1771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		/* Sleep before a retry, if not atomic */
1791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		if (!(flags & API_NO_WAIT_MB)) {
180168c626cb8f85df17585af99e14403904641c7acJulia Lawall			if (time_after(jiffies,
181168c626cb8f85df17585af99e14403904641c7acJulia Lawall				       then + msecs_to_jiffies(10*retries)))
1821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			       break;
183201700d3544c653d453716a60976efe1987110afMauro Carvalho Chehab			ivtv_msleep_timeout(10, 0);
1841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
1851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
1861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return -ENODEV;
1871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
1881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic void write_mailbox(volatile struct ivtv_mailbox __iomem *mbox, int cmd, int args, u32 data[])
1901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
1911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i;
1921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	write_sync(cmd, &mbox->cmd);
1941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	write_sync(IVTV_API_STD_TIMEOUT, &mbox->timeout);
1951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
1971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		write_sync(data[i], &mbox->data[i]);
1981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
1991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	write_sync(IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_DRIVER_BUSY, &mbox->flags);
2001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
2011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic void clear_all_mailboxes(struct ivtv *itv, struct ivtv_mailbox_data *mbdata)
2031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
2041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i;
2051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i <= mbdata->max_mbox; i++) {
2071a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		IVTV_DEBUG_WARN("Clearing mailbox %d: cmd 0x%08x flags 0x%08x\n",
2081a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			i, readl(&mbdata->mbox[i].cmd), readl(&mbdata->mbox[i].flags));
2091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		write_sync(0, &mbdata->mbox[i].flags);
2101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		clear_bit(i, &mbdata->busy);
2111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
2131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
2151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
2161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox;
2171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	volatile struct ivtv_mailbox __iomem *mbox;
218201700d3544c653d453716a60976efe1987110afMauro Carvalho Chehab	int api_timeout = msecs_to_jiffies(1000);
2191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int flags, mb, i;
2201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	unsigned long then;
2211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* sanity checks */
2231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (NULL == mbdata) {
2241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		IVTV_ERR("No mailbox allocated\n");
2251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return -ENODEV;
2261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (args < 0 || args > CX2341X_MBOX_MAX_DATA ||
2281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	    cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) {
2291aa32c2ffd146dddd76babf842e998502f1b993aHans Verkuil		IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args);
2301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return -EINVAL;
2311a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
23367632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil	if (api_info[cmd].flags & API_HIGH_VOL) {
2341aa32c2ffd146dddd76babf842e998502f1b993aHans Verkuil	    IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name);
23567632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil	}
23667632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil	else {
2371aa32c2ffd146dddd76babf842e998502f1b993aHans Verkuil	    IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name);
23867632e17da1e90a0c43283823f94080c0ee07088Hans Verkuil	}
2391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2401a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* clear possibly uninitialized part of data array */
2411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = args; i < CX2341X_MBOX_MAX_DATA; i++)
2421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		data[i] = 0;
2431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* If this command was issued within the last 30 minutes and with identical
2451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	   data, then just return 0 as there is no need to issue this command again.
2461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	   Just an optimization to prevent unnecessary use of mailboxes. */
2471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (itv->api_cache[cmd].last_jiffies &&
248168c626cb8f85df17585af99e14403904641c7acJulia Lawall	    time_before(jiffies,
249168c626cb8f85df17585af99e14403904641c7acJulia Lawall			itv->api_cache[cmd].last_jiffies +
250168c626cb8f85df17585af99e14403904641c7acJulia Lawall			msecs_to_jiffies(1800000)) &&
2511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	    !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
2521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		itv->api_cache[cmd].last_jiffies = jiffies;
2531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return 0;
2541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	flags = api_info[cmd].flags;
2571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (flags & API_DMA) {
2591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		for (i = 0; i < 100; i++) {
2601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			mb = i % (mbdata->max_mbox + 1);
2611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			if (try_mailbox(itv, mbdata, mb)) {
2621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil				write_mailbox(&mbdata->mbox[mb], cmd, args, data);
2631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil				clear_bit(mb, &mbdata->busy);
2641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil				return 0;
2651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			}
2661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n",
2671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil					api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags));
2681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
2691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name);
2701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		clear_all_mailboxes(itv, mbdata);
2711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return -EBUSY;
2721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if ((flags & API_FAST_RESULT) == API_FAST_RESULT)
275201700d3544c653d453716a60976efe1987110afMauro Carvalho Chehab		api_timeout = msecs_to_jiffies(100);
2761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	mb = get_mailbox(itv, mbdata, flags);
2781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (mb < 0) {
2791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name);
2801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		clear_all_mailboxes(itv, mbdata);
2811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return -EBUSY;
2821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	mbox = &mbdata->mbox[mb];
2841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	write_mailbox(mbox, cmd, args, data);
2851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if (flags & API_CACHE) {
2861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data));
2871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		itv->api_cache[cmd].last_jiffies = jiffies;
2881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	if ((flags & API_RESULT) == 0) {
2901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		clear_bit(mb, &mbdata->busy);
2911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		return 0;
2921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
2931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* Get results */
2951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	then = jiffies;
2961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
2970b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil	if (!(flags & API_NO_POLL)) {
2980b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil		/* First try to poll, then switch to delays */
2990b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil		for (i = 0; i < 100; i++) {
3000b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil			if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)
3010b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil				break;
3020b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil		}
3030b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil	}
3041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
305168c626cb8f85df17585af99e14403904641c7acJulia Lawall		if (time_after(jiffies, then + api_timeout)) {
3061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
3071a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			/* reset the mailbox, but it is likely too late already */
3081a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			write_sync(0, &mbox->flags);
3091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			clear_bit(mb, &mbdata->busy);
3101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			return -EIO;
3111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		}
3121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		if (flags & API_NO_WAIT_RES)
3131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil			mdelay(1);
3141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		else
3150b3e29e6d75cbfb8417f449555d40921fd656186Hans Verkuil			ivtv_msleep_timeout(1, 0);
3161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
317168c626cb8f85df17585af99e14403904641c7acJulia Lawall	if (time_after(jiffies, then + msecs_to_jiffies(100)))
318201700d3544c653d453716a60976efe1987110afMauro Carvalho Chehab		IVTV_DEBUG_WARN("%s took %u jiffies\n",
319201700d3544c653d453716a60976efe1987110afMauro Carvalho Chehab				api_info[cmd].name,
320201700d3544c653d453716a60976efe1987110afMauro Carvalho Chehab				jiffies_to_msecs(jiffies - then));
3211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
3231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		data[i] = readl(&mbox->data[i]);
3241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	write_sync(0, &mbox->flags);
3251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	clear_bit(mb, &mbdata->busy);
3261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return 0;
3271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
3281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilint ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[])
3301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
3311a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int res = ivtv_api_call(itv, cmd, args, data);
3321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	/* Allow a single retry, probably already too late though.
3341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	   If there is no free mailbox then that is usually an indication
3351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	   of a more serious problem. */
3361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return (res == -EBUSY) ? ivtv_api_call(itv, cmd, args, data) : res;
3371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
3381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
339ea48c13ad0e5626b827bd7076c22df1a352e3983Hans Verkuilint ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
3401a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
3411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return ivtv_api(priv, cmd, in, data);
3421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
3431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilint ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...)
3451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
3461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	va_list ap;
3471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i;
3481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	va_start(ap, args);
3501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i < args; i++) {
3511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		data[i] = va_arg(ap, u32);
3521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
3531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	va_end(ap);
3541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return ivtv_api(itv, cmd, args, data);
3551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
3561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilint ivtv_vapi(struct ivtv *itv, int cmd, int args, ...)
3581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
3591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	u32 data[CX2341X_MBOX_MAX_DATA];
3601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	va_list ap;
3611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i;
3621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	va_start(ap, args);
3641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	for (i = 0; i < args; i++) {
3651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil		data[i] = va_arg(ap, u32);
3661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	}
3671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	va_end(ap);
3681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	return ivtv_api(itv, cmd, args, data);
3691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
3701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil
3711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* This one is for stuff that can't sleep.. irq handlers, etc.. */
372587808d5f59e842f9258a15e88ad530fcf6e6763Andy Wallsvoid ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
373587808d5f59e842f9258a15e88ad530fcf6e6763Andy Walls		       int argc, u32 data[])
3741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{
375587808d5f59e842f9258a15e88ad530fcf6e6763Andy Walls	volatile u32 __iomem *p = mbdata->mbox[mb].data;
3761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil	int i;
377587808d5f59e842f9258a15e88ad530fcf6e6763Andy Walls	for (i = 0; i < argc; i++, p++)
378587808d5f59e842f9258a15e88ad530fcf6e6763Andy Walls		data[i] = readl(p);
3791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil}
380215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrong
381215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrong/* Wipe api cache */
382215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrongvoid ivtv_mailbox_cache_invalidate(struct ivtv *itv)
383215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrong{
384215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrong	int i;
385215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrong	for (i = 0; i < 256; i++)
386215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrong		itv->api_cache[i].last_jiffies = 0;
387215659d14f9dbc849ccda1655c94d710f8cc6384Ian Armstrong}
388