cx18-mailbox.c revision 72c2d6d3ac91d1b9efb482ff4a8dd68e3d867965
11c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil/*
21c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  cx18 mailbox functions
31c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
41c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
51c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
61c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  This program is free software; you can redistribute it and/or modify
71c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  it under the terms of the GNU General Public License as published by
81c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  the Free Software Foundation; either version 2 of the License, or
91c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  (at your option) any later version.
101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  This program is distributed in the hope that it will be useful,
121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  but WITHOUT ANY WARRANTY; without even the implied warranty of
131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  GNU General Public License for more details.
151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  You should have received a copy of the GNU General Public License
171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  along with this program; if not, write to the Free Software
181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  02111-1307  USA
201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil */
211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include <stdarg.h>
231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-driver.h"
25b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls#include "cx18-io.h"
261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-scb.h"
271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-irq.h"
281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-mailbox.h"
291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#define API_FAST (1 << 2) /* Short timeout */
311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#define API_SLOW (1 << 3) /* Additional 300ms timeout */
321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstruct cx18_api_info {
341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u32 cmd;
351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u8 flags;		/* Flags, see above */
361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u8 rpu;			/* Processing unit */
371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	const char *name; 	/* The name of the command */
381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil};
391c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
401c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic const struct cx18_api_info api_info[] = {
431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* MPEG encoder API */
441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,		0),
451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_EPU_DEBUG, 				0),
461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CREATE_TASK, 			0),
471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_DESTROY_TASK, 			0),
481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_CAPTURE_START,                  API_SLOW),
491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_CAPTURE_STOP,                   API_SLOW),
501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_CAPTURE_PAUSE,                  0),
511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_CAPTURE_RESUME,                 0),
521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_STREAM_OUTPUT_TYPE,         0),
541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_IN,                   0),
551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RATE,                 0),
561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RESOLUTION,           0),
571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_FILTER_PARAM,               0),
581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_SPATIAL_FILTER_TYPE,        0),
591c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_MEDIAN_CORING,              0),
601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_INDEXTABLE,                 0),
611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PARAMETERS,           0),
621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_MUTE,                 0),
631c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_AUDIO_MUTE,                 0),
641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_MISC_PARAMETERS,            0),
651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_RAW_VBI_PARAM,              API_SLOW),
661c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_CAPTURE_LINE_NO,            0),
671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_COPYRIGHT,                  0),
681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PID,                  0),
691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_PID,                  0),
701c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_VER_CROP_LINE,              0),
711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_GOP_STRUCTURE,              0),
721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_SCENE_CHANGE_DETECTION,     0),
731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_ASPECT_RATIO,               0),
741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_SKIP_INPUT_FRAME,           0),
751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM,           0),
761c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER,      0),
771c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS,                    0),
781c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK,			0),
791c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(CPU, CX18_CPU_DE_SET_MDL,			API_FAST),
8081cb727d29eda7692a03be035b7228b4c3f6b610Hans Verkuil	API_ENTRY(CPU, CX18_APU_RESETAI,			API_FAST),
814e6b61047db2a77a250b6510bdb3c20c41aee591Andy Walls	API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL,			API_SLOW),
821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	API_ENTRY(0, 0,						0),
831c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil};
841c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
851c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic const struct cx18_api_info *find_api_info(u32 cmd)
861c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
871c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int i;
881c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
891c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	for (i = 0; api_info[i].cmd; i++)
901c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (api_info[i].cmd == cmd)
911c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return &api_info[i];
921c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return NULL;
931c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
941c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
95990c81c8afcd71eced2482ad59950ea755eddc7fAl Virostatic struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu,
961c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		u32 *state, u32 *irq, u32 *req)
971c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
98990c81c8afcd71eced2482ad59950ea755eddc7fAl Viro	struct cx18_mailbox __iomem *mb = NULL;
991c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int wait_count = 0;
1001c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u32 ack;
1011c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1021c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	switch (rpu) {
1031c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case APU:
1041c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		mb = &cx->scb->epu2apu_mb;
105b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		*state = cx18_readl(cx, &cx->scb->apu_state);
106b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		*irq = cx18_readl(cx, &cx->scb->epu2apu_irq);
1071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		break;
1081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1091c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CPU:
1101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		mb = &cx->scb->epu2cpu_mb;
111b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		*state = cx18_readl(cx, &cx->scb->cpu_state);
112b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		*irq = cx18_readl(cx, &cx->scb->epu2cpu_irq);
1131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		break;
1141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
11572c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	default:
1161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		break;
1171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
1181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (mb == NULL)
1201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return mb;
1211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	do {
123b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		*req = cx18_readl(cx, &mb->request);
124b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		ack = cx18_readl(cx, &mb->ack);
1251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		wait_count++;
1261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	} while (*req != ack && wait_count < 600);
1271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (*req == ack) {
1291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		(*req)++;
1301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (*req == 0 || *req == 0xffffffff)
1311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			*req = 1;
1321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return mb;
1331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
1341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return NULL;
1351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
1361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
13772c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Wallslong cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb, int rpu)
1381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
139990c81c8afcd71eced2482ad59950ea755eddc7fAl Viro	struct cx18_mailbox __iomem *ack_mb;
1401c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u32 ack_irq;
1411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	switch (rpu) {
1431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case APU:
1441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		ack_irq = IRQ_EPU_TO_APU_ACK;
1451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		ack_mb = &cx->scb->apu2epu_mb;
1461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		break;
1471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CPU:
1481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		ack_irq = IRQ_EPU_TO_CPU_ACK;
1491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		ack_mb = &cx->scb->cpu2epu_mb;
1501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		break;
1511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	default:
15272c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		CX18_WARN("Unhandled RPU (%d) for command %x ack\n",
15372c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls			  rpu, mb->cmd);
1541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EINVAL;
1551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
1561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
157b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls	cx18_setup_page(cx, SCB_OFFSET);
158b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls	cx18_write_sync(cx, mb->request, &ack_mb->ack);
159f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls	cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq);
1601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return 0;
1611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
1621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1631c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
1651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
1661c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	const struct cx18_api_info *info = find_api_info(cmd);
1671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u32 state = 0, irq = 0, req, oldreq, err;
168990c81c8afcd71eced2482ad59950ea755eddc7fAl Viro	struct cx18_mailbox __iomem *mb;
1691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	wait_queue_head_t *waitq;
17072c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	struct mutex *mb_lock;
1711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int timeout = 100;
1721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int sig = 0;
1731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int i;
1741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (info == NULL) {
1761c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_WARN("unknown cmd %x\n", cmd);
1771c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EINVAL;
1781c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
1791c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1801c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (cmd == CX18_CPU_DE_SET_MDL)
1811c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_HI_API("%s\n", info->name);
1821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	else
1831c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_API("%s\n", info->name);
18472c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls
18572c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	switch (info->rpu) {
18672c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	case APU:
18772c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		waitq = &cx->mb_apu_waitq;
18872c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		mb_lock = &cx->epu2apu_mb_lock;
18972c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		break;
19072c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	case CPU:
19172c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		waitq = &cx->mb_cpu_waitq;
19272c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		mb_lock = &cx->epu2cpu_mb_lock;
19372c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		break;
19472c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	default:
19572c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		CX18_WARN("Unknown RPU (%d) for API call\n", info->rpu);
19672c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		return -EINVAL;
19772c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	}
19872c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls
19972c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	mutex_lock(mb_lock);
200b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls	cx18_setup_page(cx, SCB_OFFSET);
2011c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
2021c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2031c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (mb == NULL) {
20472c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		mutex_unlock(mb_lock);
2051c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_ERR("mb %s busy\n", info->name);
2061c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EBUSY;
2071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
2081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2091c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	oldreq = req - 1;
210b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls	cx18_writel(cx, cmd, &mb->cmd);
2111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	for (i = 0; i < args; i++)
212b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		cx18_writel(cx, data[i], &mb->args[i]);
213b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls	cx18_writel(cx, 0, &mb->error);
214b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls	cx18_writel(cx, req, &mb->request);
2151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (info->flags & API_FAST)
2171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		timeout /= 2;
218f056d29eebd2c8800cf42528ba0470c77a928821Andy Walls	cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
2191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
22072c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	sig = wait_event_interruptible_timeout(
22172c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		       *waitq,
22272c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		       cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request),
22372c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		       msecs_to_jiffies(timeout));
22472c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	if (sig == 0) {
22572c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		/* Timed out */
226b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		cx18_writel(cx, oldreq, &mb->request);
22772c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		mutex_unlock(mb_lock);
22872c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		CX18_ERR("sending %s timed out waiting for RPU to respond\n",
22972c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls			 info->name);
2301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EINVAL;
23172c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	} else if (sig < 0) {
23272c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		/* Interrupted */
23372c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		cx18_writel(cx, oldreq, &mb->request);
23472c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		mutex_unlock(mb_lock);
23572c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		CX18_WARN("sending %s interrupted waiting for RPU to respond\n",
23672c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls			  info->name);
23772c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls		return -EINTR;
2381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
23972c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls
2401c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	for (i = 0; i < MAX_MB_ARGUMENTS; i++)
241b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls		data[i] = cx18_readl(cx, &mb->args[i]);
242b1526421eac9a912b2cda7e147f1da2aa31be278Andy Walls	err = cx18_readl(cx, &mb->error);
24372c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	mutex_unlock(mb_lock);
24472c2d6d3ac91d1b9efb482ff4a8dd68e3d867965Andy Walls	if (info->flags & API_SLOW)
2451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_msleep_timeout(300, 0);
2461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (err)
2471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
2481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				info->name);
2491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return err ? -EIO : 0;
2501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
2511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilint cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
2531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
2541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int res = cx18_api_call(cx, cmd, args, data);
2551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* Allow a single retry, probably already too late though.
2571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	   If there is no free mailbox then that is usually an indication
2581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	   of a more serious problem. */
2591c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return (res == -EBUSY) ? cx18_api_call(cx, cmd, args, data) : res;
2601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
2611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic int cx18_set_filter_param(struct cx18_stream *s)
2631c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
2641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = s->cx;
2651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u32 mode;
2661c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int ret;
2671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mode = (cx->filter_mode & 1) ? 2 : (cx->spatial_strength ? 1 : 0);
2691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	ret = cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
2701c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			s->handle, 1, mode, cx->spatial_strength);
2711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mode = (cx->filter_mode & 2) ? 2 : (cx->temporal_strength ? 1 : 0);
2721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
2731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			s->handle, 0, mode, cx->temporal_strength);
2741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
2751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			s->handle, 2, cx->filter_mode >> 2, 0);
2761c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return ret;
2771c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
2781c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2791c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilint cx18_api_func(void *priv, u32 cmd, int in, int out,
2801c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		u32 data[CX2341X_MBOX_MAX_DATA])
2811c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
2821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = priv;
2831c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
2841c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2851c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	switch (cmd) {
2861c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_OUTPUT_PORT:
2871c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return 0;
2881c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_FRAME_RATE:
2891c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_IN, 6,
2901c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, 0, 0, 0, 0, data[0]);
2911c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_FRAME_SIZE:
2921c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RESOLUTION, 3,
2931c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[1], data[0]);
2941c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_STREAM_TYPE:
2951c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 2,
2961c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0]);
2971c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_ASPECT_RATIO:
2981c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_ASPECT_RATIO, 2,
2991c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0]);
3001c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
3011c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_GOP_PROPERTIES:
3021c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_GOP_STRUCTURE, 3,
3031c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0], data[1]);
3041c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_GOP_CLOSURE:
3051c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return 0;
3061c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_AUDIO_PROPERTIES:
3071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
3081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0]);
3091c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_MUTE_AUDIO:
3101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
3111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0]);
3121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_BIT_RATE:
3131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RATE, 5,
3141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0], data[1], data[2], data[3]);
3151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_MUTE_VIDEO:
3161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
3171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0]);
3181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_FRAME_DROP_RATE:
3191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_SKIP_INPUT_FRAME, 2,
3201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0]);
3211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_MISC:
3221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 4,
3231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0], data[1], data[2]);
3241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_DNR_FILTER_MODE:
3251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx->filter_mode = (data[0] & 3) | (data[1] << 2);
3261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_set_filter_param(s);
3271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_DNR_FILTER_PROPS:
3281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx->spatial_strength = data[0];
3291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx->temporal_strength = data[1];
3301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_set_filter_param(s);
3311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
3321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 3,
3331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0], data[1]);
3341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	case CX2341X_ENC_SET_CORING_LEVELS:
3351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return cx18_vapi(cx, CX18_CPU_SET_MEDIAN_CORING, 5,
3361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->handle, data[0], data[1], data[2], data[3]);
3371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
3381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_WARN("Unknown cmd %x\n", cmd);
3391c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return 0;
3401c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
3411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
3421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilint cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS],
3431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		u32 cmd, int args, ...)
3441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
3451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	va_list ap;
3461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int i;
3471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
3481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	va_start(ap, args);
3491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	for (i = 0; i < args; i++)
3501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		data[i] = va_arg(ap, u32);
3511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	va_end(ap);
3521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return cx18_api(cx, cmd, args, data);
3531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
3541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
3551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilint cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...)
3561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
3571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	u32 data[MAX_MB_ARGUMENTS];
3581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	va_list ap;
3591c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int i;
3601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
3611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (cx == NULL) {
3621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_ERR("cx == NULL (cmd=%x)\n", cmd);
3631c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return 0;
3641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
3651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (args > MAX_MB_ARGUMENTS) {
3661c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_ERR("args too big (cmd=%x)\n", cmd);
3671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		args = MAX_MB_ARGUMENTS;
3681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
3691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	va_start(ap, args);
3701c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	for (i = 0; i < args; i++)
3711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		data[i] = va_arg(ap, u32);
3721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	va_end(ap);
3731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return cx18_api(cx, cmd, args, data);
3741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
375