[NETFILTER]: Move ip6_masked_addrcmp to include/net/ipv6.h
[linux-2.6/verdex.git] / drivers / media / dvb / ttpci / av7110_hw.c
blob0bb6e74ae7f0f83edaf538bd45f5cc682a843461
1 /*
2 * av7110_hw.c: av7110 low level hardware access and firmware interface
4 * Copyright (C) 1999-2002 Ralph Metzler
5 * & Marcus Metzler for convergence integrated media GmbH
7 * originally based on code by:
8 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
25 * the project's page is at http://www.linuxtv.org/dvb/
28 /* for debugging ARM communication: */
29 //#define COM_DEBUG
31 #include <stdarg.h>
32 #include <linux/types.h>
33 #include <linux/kernel.h>
34 #include <linux/string.h>
35 #include <linux/sched.h>
36 #include <linux/delay.h>
37 #include <linux/byteorder/swabb.h>
38 #include <linux/smp_lock.h>
39 #include <linux/fs.h>
41 #include "av7110.h"
42 #include "av7110_hw.h"
44 #define _NOHANDSHAKE
46 /****************************************************************************
47 * DEBI functions
48 ****************************************************************************/
50 /* This DEBI code is based on the Stradis driver
51 by Nathan Laredo <laredo@gnu.org> */
53 int av7110_debiwrite(struct av7110 *av7110, u32 config,
54 int addr, u32 val, int count)
56 struct saa7146_dev *dev = av7110->dev;
58 if (count <= 0 || count > 32764) {
59 printk("%s: invalid count %d\n", __FUNCTION__, count);
60 return -1;
62 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
63 printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
64 return -1;
66 saa7146_write(dev, DEBI_CONFIG, config);
67 if (count <= 4) /* immediate transfer */
68 saa7146_write(dev, DEBI_AD, val);
69 else /* block transfer */
70 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
71 saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
72 saa7146_write(dev, MC2, (2 << 16) | 2);
73 return 0;
76 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
78 struct saa7146_dev *dev = av7110->dev;
79 u32 result = 0;
81 if (count > 32764 || count <= 0) {
82 printk("%s: invalid count %d\n", __FUNCTION__, count);
83 return 0;
85 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
86 printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
87 return 0;
89 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
90 saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
92 saa7146_write(dev, DEBI_CONFIG, config);
93 saa7146_write(dev, MC2, (2 << 16) | 2);
94 if (count > 4)
95 return count;
96 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
97 printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
98 return 0;
101 result = saa7146_read(dev, DEBI_AD);
102 result &= (0xffffffffUL >> ((4 - count) * 8));
103 return result;
108 /* av7110 ARM core boot stuff */
109 #if 0
110 void av7110_reset_arm(struct av7110 *av7110)
112 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
114 /* Disable DEBI and GPIO irq */
115 SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
116 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
118 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
119 msleep(30); /* the firmware needs some time to initialize */
121 ARM_ResetMailBox(av7110);
123 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
124 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
126 av7110->arm_ready = 1;
127 dprintk(1, "reset ARM\n");
129 #endif /* 0 */
131 static int waitdebi(struct av7110 *av7110, int adr, int state)
133 int k;
135 dprintk(4, "%p\n", av7110);
137 for (k = 0; k < 100; k++) {
138 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
139 return 0;
140 udelay(5);
142 return -ETIMEDOUT;
145 static int load_dram(struct av7110 *av7110, u32 *data, int len)
147 int i;
148 int blocks, rest;
149 u32 base, bootblock = AV7110_BOOT_BLOCK;
151 dprintk(4, "%p\n", av7110);
153 blocks = len / AV7110_BOOT_MAX_SIZE;
154 rest = len % AV7110_BOOT_MAX_SIZE;
155 base = DRAM_START_CODE;
157 for (i = 0; i < blocks; i++) {
158 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
159 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
160 return -ETIMEDOUT;
162 dprintk(4, "writing DRAM block %d\n", i);
163 mwdebi(av7110, DEBISWAB, bootblock,
164 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
165 bootblock ^= 0x1400;
166 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
167 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
168 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
169 base += AV7110_BOOT_MAX_SIZE;
172 if (rest > 0) {
173 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
174 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
175 return -ETIMEDOUT;
177 if (rest > 4)
178 mwdebi(av7110, DEBISWAB, bootblock,
179 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
180 else
181 mwdebi(av7110, DEBISWAB, bootblock,
182 ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
184 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
185 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
186 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
188 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
189 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
190 return -ETIMEDOUT;
192 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
193 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
194 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
195 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
196 return -ETIMEDOUT;
198 return 0;
202 /* we cannot write av7110 DRAM directly, so load a bootloader into
203 * the DPRAM which implements a simple boot protocol */
204 static u8 bootcode[] = {
205 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
206 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
207 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
208 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
209 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
210 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
211 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
212 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
213 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
214 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
215 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
216 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
217 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
218 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
219 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
220 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
221 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
222 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
225 int av7110_bootarm(struct av7110 *av7110)
227 struct saa7146_dev *dev = av7110->dev;
228 u32 ret;
229 int i;
231 dprintk(4, "%p\n", av7110);
233 av7110->arm_ready = 0;
235 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
237 /* Disable DEBI and GPIO irq */
238 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
239 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
241 /* enable DEBI */
242 saa7146_write(av7110->dev, MC1, 0x08800880);
243 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
244 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
246 /* test DEBI */
247 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
248 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
249 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
251 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
252 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
253 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
254 ret, 0x10325476);
255 return -1;
257 for (i = 0; i < 8192; i += 4)
258 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
259 dprintk(2, "debi test OK\n");
261 /* boot */
262 dprintk(1, "load boot code\n");
263 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
264 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
265 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
267 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
268 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
270 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
271 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
272 "saa7146_wait_for_debi_done() timed out\n");
273 return -ETIMEDOUT;
275 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
276 mdelay(1);
278 dprintk(1, "load dram code\n");
279 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
280 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
281 "load_dram() failed\n");
282 return -1;
285 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
286 mdelay(1);
288 dprintk(1, "load dpram code\n");
289 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
291 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
292 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
293 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
294 return -ETIMEDOUT;
296 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
297 msleep(30); /* the firmware needs some time to initialize */
299 //ARM_ClearIrq(av7110);
300 ARM_ResetMailBox(av7110);
301 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
302 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
304 av7110->arm_errors = 0;
305 av7110->arm_ready = 1;
306 return 0;
310 /****************************************************************************
311 * DEBI command polling
312 ****************************************************************************/
314 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
316 unsigned long start;
317 u32 stat;
318 int err;
320 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
321 /* not supported by old firmware */
322 msleep(50);
323 return 0;
326 /* new firmware */
327 start = jiffies;
328 for (;;) {
329 err = time_after(jiffies, start + ARM_WAIT_FREE);
330 if (down_interruptible(&av7110->dcomlock))
331 return -ERESTARTSYS;
332 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
333 up(&av7110->dcomlock);
334 if ((stat & flags) == 0)
335 break;
336 if (err) {
337 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
338 __FUNCTION__, stat & flags);
339 return -ETIMEDOUT;
341 msleep(1);
343 return 0;
346 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
348 int i;
349 unsigned long start;
350 char *type = NULL;
351 u16 flags[2] = {0, 0};
352 u32 stat;
353 int err;
355 // dprintk(4, "%p\n", av7110);
357 if (!av7110->arm_ready) {
358 dprintk(1, "arm not ready.\n");
359 return -ENXIO;
362 start = jiffies;
363 while (1) {
364 err = time_after(jiffies, start + ARM_WAIT_FREE);
365 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
366 break;
367 if (err) {
368 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
369 av7110->arm_errors++;
370 return -ETIMEDOUT;
372 msleep(1);
375 if (FW_VERSION(av7110->arm_app) <= 0x261f)
376 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
378 #ifndef _NOHANDSHAKE
379 start = jiffies;
380 while (1) {
381 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
382 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
383 break;
384 if (err) {
385 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
386 return -ETIMEDOUT;
388 msleep(1);
390 #endif
392 switch ((buf[0] >> 8) & 0xff) {
393 case COMTYPE_PIDFILTER:
394 case COMTYPE_ENCODER:
395 case COMTYPE_REC_PLAY:
396 case COMTYPE_MPEGDECODER:
397 type = "MSG";
398 flags[0] = GPMQOver;
399 flags[1] = GPMQFull;
400 break;
401 case COMTYPE_OSD:
402 type = "OSD";
403 flags[0] = OSDQOver;
404 flags[1] = OSDQFull;
405 break;
406 case COMTYPE_MISC:
407 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
408 type = "MSG";
409 flags[0] = GPMQOver;
410 flags[1] = GPMQBusy;
412 break;
413 default:
414 break;
417 if (type != NULL) {
418 /* non-immediate COMMAND type */
419 start = jiffies;
420 for (;;) {
421 err = time_after(jiffies, start + ARM_WAIT_FREE);
422 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
423 if (stat & flags[0]) {
424 printk(KERN_ERR "%s: %s QUEUE overflow\n",
425 __FUNCTION__, type);
426 return -1;
428 if ((stat & flags[1]) == 0)
429 break;
430 if (err) {
431 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
432 __FUNCTION__, type);
433 return -ETIMEDOUT;
435 msleep(1);
439 for (i = 2; i < length; i++)
440 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
442 if (length)
443 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
444 else
445 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
447 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
449 if (FW_VERSION(av7110->arm_app) <= 0x261f)
450 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
452 #ifdef COM_DEBUG
453 start = jiffies;
454 while (1) {
455 err = time_after(jiffies, start + ARM_WAIT_FREE);
456 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
457 break;
458 if (err) {
459 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
460 __FUNCTION__, (buf[0] >> 8) & 0xff);
461 return -ETIMEDOUT;
463 msleep(1);
466 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
467 if (stat & GPMQOver) {
468 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
469 return -ENOSPC;
471 else if (stat & OSDQOver) {
472 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
473 return -ENOSPC;
475 #endif
477 return 0;
480 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
482 int ret;
484 // dprintk(4, "%p\n", av7110);
486 if (!av7110->arm_ready) {
487 dprintk(1, "arm not ready.\n");
488 return -1;
490 if (down_interruptible(&av7110->dcomlock))
491 return -ERESTARTSYS;
493 ret = __av7110_send_fw_cmd(av7110, buf, length);
494 up(&av7110->dcomlock);
495 if (ret && ret!=-ERESTARTSYS)
496 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
497 __FUNCTION__, ret);
498 return ret;
501 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
503 va_list args;
504 u16 buf[num + 2];
505 int i, ret;
507 // dprintk(4, "%p\n", av7110);
509 buf[0] = ((type << 8) | com);
510 buf[1] = num;
512 if (num) {
513 va_start(args, num);
514 for (i = 0; i < num; i++)
515 buf[i + 2] = va_arg(args, u32);
516 va_end(args);
519 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
520 if (ret && ret != -ERESTARTSYS)
521 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
522 return ret;
525 #if 0
526 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
528 int i, ret;
529 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
530 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
532 dprintk(4, "%p\n", av7110);
534 for(i = 0; i < len && i < 32; i++)
536 if(i % 2 == 0)
537 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
538 else
539 cmd[(i / 2) + 2] |= buf[i];
542 ret = av7110_send_fw_cmd(av7110, cmd, 18);
543 if (ret && ret != -ERESTARTSYS)
544 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
545 return ret;
547 #endif /* 0 */
549 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
550 int request_buf_len, u16 *reply_buf, int reply_buf_len)
552 int err;
553 s16 i;
554 unsigned long start;
555 #ifdef COM_DEBUG
556 u32 stat;
557 #endif
559 dprintk(4, "%p\n", av7110);
561 if (!av7110->arm_ready) {
562 dprintk(1, "arm not ready.\n");
563 return -1;
566 if (down_interruptible(&av7110->dcomlock))
567 return -ERESTARTSYS;
569 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
570 up(&av7110->dcomlock);
571 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
572 return err;
575 start = jiffies;
576 while (1) {
577 err = time_after(jiffies, start + ARM_WAIT_FREE);
578 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
579 break;
580 if (err) {
581 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
582 up(&av7110->dcomlock);
583 return -ETIMEDOUT;
585 #ifdef _NOHANDSHAKE
586 msleep(1);
587 #endif
590 #ifndef _NOHANDSHAKE
591 start = jiffies;
592 while (1) {
593 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
594 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
595 break;
596 if (err) {
597 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
598 up(&av7110->dcomlock);
599 return -ETIMEDOUT;
601 msleep(1);
603 #endif
605 #ifdef COM_DEBUG
606 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
607 if (stat & GPMQOver) {
608 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
609 up(&av7110->dcomlock);
610 return -1;
612 else if (stat & OSDQOver) {
613 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
614 up(&av7110->dcomlock);
615 return -1;
617 #endif
619 for (i = 0; i < reply_buf_len; i++)
620 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
622 up(&av7110->dcomlock);
623 return 0;
626 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
628 int ret;
629 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
630 if (ret)
631 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
632 return ret;
636 /****************************************************************************
637 * Firmware commands
638 ****************************************************************************/
640 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
641 int av7110_firmversion(struct av7110 *av7110)
643 u16 buf[20];
644 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
646 dprintk(4, "%p\n", av7110);
648 if (av7110_fw_query(av7110, tag, buf, 16)) {
649 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
650 av7110->dvb_adapter.num);
651 return -EIO;
654 av7110->arm_fw = (buf[0] << 16) + buf[1];
655 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
656 av7110->arm_vid = (buf[4] << 16) + buf[5];
657 av7110->arm_app = (buf[6] << 16) + buf[7];
658 av7110->avtype = (buf[8] << 16) + buf[9];
660 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
661 av7110->dvb_adapter.num, av7110->arm_fw,
662 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
664 /* print firmware capabilities */
665 if (FW_CI_LL_SUPPORT(av7110->arm_app))
666 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
667 av7110->dvb_adapter.num);
668 else
669 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
670 av7110->dvb_adapter.num);
672 return 0;
676 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
678 int i, ret;
679 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
680 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
682 dprintk(4, "%p\n", av7110);
684 if (len > 10)
685 len = 10;
687 buf[1] = len + 2;
688 buf[2] = len;
690 if (burst != -1)
691 buf[3] = burst ? 0x01 : 0x00;
692 else
693 buf[3] = 0xffff;
695 for (i = 0; i < len; i++)
696 buf[i + 4] = msg[i];
698 ret = av7110_send_fw_cmd(av7110, buf, 18);
699 if (ret && ret!=-ERESTARTSYS)
700 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
701 return ret;
705 #ifdef CONFIG_DVB_AV7110_OSD
707 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
709 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
712 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
713 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
715 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
716 windownr, colordepth, index, blending);
719 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
720 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
722 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
723 windownr, colordepth, index, colorhi, colorlo);
726 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
727 u16 colorfg, u16 colorbg)
729 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
730 windownr, fontsize, colorfg, colorbg);
733 static int FlushText(struct av7110 *av7110)
735 unsigned long start;
736 int err;
738 if (down_interruptible(&av7110->dcomlock))
739 return -ERESTARTSYS;
740 start = jiffies;
741 while (1) {
742 err = time_after(jiffies, start + ARM_WAIT_OSD);
743 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
744 break;
745 if (err) {
746 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
747 __FUNCTION__);
748 up(&av7110->dcomlock);
749 return -ETIMEDOUT;
751 msleep(1);
753 up(&av7110->dcomlock);
754 return 0;
757 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
759 int i, ret;
760 unsigned long start;
761 int length = strlen(buf) + 1;
762 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
764 if (down_interruptible(&av7110->dcomlock))
765 return -ERESTARTSYS;
767 start = jiffies;
768 while (1) {
769 ret = time_after(jiffies, start + ARM_WAIT_OSD);
770 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
771 break;
772 if (ret) {
773 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
774 __FUNCTION__);
775 up(&av7110->dcomlock);
776 return -ETIMEDOUT;
778 msleep(1);
780 #ifndef _NOHANDSHAKE
781 start = jiffies;
782 while (1) {
783 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
784 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
785 break;
786 if (ret) {
787 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
788 __FUNCTION__);
789 up(&av7110->dcomlock);
790 return -ETIMEDOUT;
792 msleep(1);
794 #endif
795 for (i = 0; i < length / 2; i++)
796 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
797 swab16(*(u16 *)(buf + 2 * i)), 2);
798 if (length & 1)
799 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
800 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
801 up(&av7110->dcomlock);
802 if (ret && ret!=-ERESTARTSYS)
803 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
804 return ret;
807 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
808 u16 x, u16 y, u16 dx, u16 dy, u16 color)
810 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
811 windownr, x, y, dx, dy, color);
814 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
815 u16 x, u16 y, u16 dx, u16 dy, u16 color)
817 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
818 windownr, x, y, dx, dy, color);
821 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
823 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
826 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
828 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
831 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
833 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
836 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
838 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
841 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
842 osd_raw_window_t disptype,
843 u16 width, u16 height)
845 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
846 windownr, disptype, width, height);
850 static enum av7110_osd_palette_type bpp2pal[8] = {
851 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
853 static osd_raw_window_t bpp2bit[8] = {
854 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
857 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
859 int ret = wait_event_interruptible_timeout(av7110->bmpq,
860 av7110->bmp_state != BMP_LOADING, 10*HZ);
861 if (ret == -ERESTARTSYS)
862 return ret;
863 if (ret == 0) {
864 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
865 ret, av7110->bmp_state);
866 av7110->bmp_state = BMP_NONE;
867 return -ETIMEDOUT;
869 return 0;
872 static inline int LoadBitmap(struct av7110 *av7110,
873 u16 dx, u16 dy, int inc, u8 __user * data)
875 u16 format;
876 int bpp;
877 int i;
878 int d, delta;
879 u8 c;
880 int ret;
882 dprintk(4, "%p\n", av7110);
884 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
886 av7110->bmp_state = BMP_LOADING;
887 if (format == OSD_BITMAP8) {
888 bpp=8; delta = 1;
889 } else if (format == OSD_BITMAP4) {
890 bpp=4; delta = 2;
891 } else if (format == OSD_BITMAP2) {
892 bpp=2; delta = 4;
893 } else if (format == OSD_BITMAP1) {
894 bpp=1; delta = 8;
895 } else {
896 av7110->bmp_state = BMP_NONE;
897 return -EINVAL;
899 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
900 av7110->bmpp = 0;
901 if (av7110->bmplen > 32768) {
902 av7110->bmp_state = BMP_NONE;
903 return -EINVAL;
905 for (i = 0; i < dy; i++) {
906 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
907 av7110->bmp_state = BMP_NONE;
908 return -EINVAL;
911 if (format != OSD_BITMAP8) {
912 for (i = 0; i < dx * dy / delta; i++) {
913 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
914 for (d = delta - 2; d >= 0; d--) {
915 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
916 << ((delta - d - 1) * bpp));
917 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
921 av7110->bmplen += 1024;
922 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
923 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
924 if (!ret)
925 ret = WaitUntilBmpLoaded(av7110);
926 return ret;
929 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
931 dprintk(4, "%p\n", av7110);
933 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
936 static inline int ReleaseBitmap(struct av7110 *av7110)
938 dprintk(4, "%p\n", av7110);
940 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
941 return -1;
942 if (av7110->bmp_state == BMP_LOADING)
943 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
944 av7110->bmp_state = BMP_NONE;
945 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
948 static u32 RGB2YUV(u16 R, u16 G, u16 B)
950 u16 y, u, v;
951 u16 Y, Cr, Cb;
953 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
954 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
955 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
957 Y = y / 256;
958 Cb = u / 16;
959 Cr = v / 16;
961 return Cr | (Cb << 16) | (Y << 8);
964 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
966 int ret;
968 u16 ch, cl;
969 u32 yuv;
971 yuv = blend ? RGB2YUV(r,g,b) : 0;
972 cl = (yuv & 0xffff);
973 ch = ((yuv >> 16) & 0xffff);
974 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
975 color, ch, cl);
976 if (!ret)
977 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
978 color, ((blend >> 4) & 0x0f));
979 return ret;
982 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
984 int i;
985 int length = last - first + 1;
987 if (length * 4 > DATA_BUFF3_SIZE)
988 return -EINVAL;
990 for (i = 0; i < length; i++) {
991 u32 color, blend, yuv;
993 if (get_user(color, colors + i))
994 return -EFAULT;
995 blend = (color & 0xF0000000) >> 4;
996 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
997 (color >> 16) & 0xFF) | blend : 0;
998 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
999 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
1001 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
1002 av7110->osdwin,
1003 bpp2pal[av7110->osdbpp[av7110->osdwin]],
1004 first, last);
1007 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
1008 int x1, int y1, int inc, u8 __user * data)
1010 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1011 int i;
1012 int rc,release_rc;
1014 w = x1 - x0 + 1;
1015 h = y1 - y0 + 1;
1016 if (inc <= 0)
1017 inc = w;
1018 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1019 return -EINVAL;
1020 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1021 bpl = ((w * bpp + 7) & ~7) / 8;
1022 size = h * bpl;
1023 lpb = (32 * 1024) / bpl;
1024 bnum = size / (lpb * bpl);
1025 brest = size - bnum * lpb * bpl;
1027 if (av7110->bmp_state == BMP_LOADING) {
1028 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1029 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1030 rc = WaitUntilBmpLoaded(av7110);
1031 if (rc)
1032 return rc;
1033 /* just continue. This should work for all fw versions
1034 * if bnum==1 && !brest && LoadBitmap was successful
1038 rc = 0;
1039 for (i = 0; i < bnum; i++) {
1040 rc = LoadBitmap(av7110, w, lpb, inc, data);
1041 if (rc)
1042 break;
1043 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1044 if (rc)
1045 break;
1046 data += lpb * inc;
1048 if (!rc && brest) {
1049 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1050 if (!rc)
1051 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1053 release_rc = ReleaseBitmap(av7110);
1054 if (!rc)
1055 rc = release_rc;
1056 if (rc)
1057 dprintk(1,"returns %d\n",rc);
1058 return rc;
1061 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1063 int ret;
1065 if (down_interruptible(&av7110->osd_sema))
1066 return -ERESTARTSYS;
1068 switch (dc->cmd) {
1069 case OSD_Close:
1070 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1071 break;
1072 case OSD_Open:
1073 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1074 ret = CreateOSDWindow(av7110, av7110->osdwin,
1075 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1076 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1077 if (ret)
1078 break;
1079 if (!dc->data) {
1080 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1081 if (ret)
1082 break;
1083 ret = SetColorBlend(av7110, av7110->osdwin);
1085 break;
1086 case OSD_Show:
1087 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1088 break;
1089 case OSD_Hide:
1090 ret = HideWindow(av7110, av7110->osdwin);
1091 break;
1092 case OSD_Clear:
1093 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1094 break;
1095 case OSD_Fill:
1096 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1097 break;
1098 case OSD_SetColor:
1099 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1100 break;
1101 case OSD_SetPalette:
1102 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1103 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1104 else {
1105 int i, len = dc->x0-dc->color+1;
1106 u8 __user *colors = (u8 __user *)dc->data;
1107 u8 r, g, b, blend;
1108 ret = 0;
1109 for (i = 0; i<len; i++) {
1110 if (get_user(r, colors + i * 4) ||
1111 get_user(g, colors + i * 4 + 1) ||
1112 get_user(b, colors + i * 4 + 2) ||
1113 get_user(blend, colors + i * 4 + 3)) {
1114 ret = -EFAULT;
1115 break;
1117 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1118 if (ret)
1119 break;
1122 break;
1123 case OSD_SetPixel:
1124 ret = DrawLine(av7110, av7110->osdwin,
1125 dc->x0, dc->y0, 0, 0, dc->color);
1126 break;
1127 case OSD_SetRow:
1128 dc->y1 = dc->y0;
1129 /* fall through */
1130 case OSD_SetBlock:
1131 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1132 break;
1133 case OSD_FillRow:
1134 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1135 dc->x1-dc->x0+1, dc->y1, dc->color);
1136 break;
1137 case OSD_FillBlock:
1138 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1139 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1140 break;
1141 case OSD_Line:
1142 ret = DrawLine(av7110, av7110->osdwin,
1143 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1144 break;
1145 case OSD_Text:
1147 char textbuf[240];
1149 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1150 ret = -EFAULT;
1151 break;
1153 textbuf[239] = 0;
1154 if (dc->x1 > 3)
1155 dc->x1 = 3;
1156 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1157 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1158 if (!ret)
1159 ret = FlushText(av7110);
1160 if (!ret)
1161 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1162 break;
1164 case OSD_SetWindow:
1165 if (dc->x0 < 1 || dc->x0 > 7)
1166 ret = -EINVAL;
1167 else {
1168 av7110->osdwin = dc->x0;
1169 ret = 0;
1171 break;
1172 case OSD_MoveWindow:
1173 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1174 if (!ret)
1175 ret = SetColorBlend(av7110, av7110->osdwin);
1176 break;
1177 case OSD_OpenRaw:
1178 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1179 ret = -EINVAL;
1180 break;
1182 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1183 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1184 else
1185 av7110->osdbpp[av7110->osdwin] = 0;
1186 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1187 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1188 if (ret)
1189 break;
1190 if (!dc->data) {
1191 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1192 if (!ret)
1193 ret = SetColorBlend(av7110, av7110->osdwin);
1195 break;
1196 default:
1197 ret = -EINVAL;
1198 break;
1201 up(&av7110->osd_sema);
1202 if (ret==-ERESTARTSYS)
1203 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1204 else if (ret)
1205 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1207 return ret;
1210 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1212 switch (cap->cmd) {
1213 case OSD_CAP_MEMSIZE:
1214 if (FW_4M_SDRAM(av7110->arm_app))
1215 cap->val = 1000000;
1216 else
1217 cap->val = 92000;
1218 return 0;
1219 default:
1220 return -EINVAL;
1223 #endif /* CONFIG_DVB_AV7110_OSD */