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