[PATCH] dvb: ttpci: fix bug in timeout handling
[linux-2.6.git] / drivers / media / dvb / ttpci / av7110_hw.c
1 /*
2  * av7110_hw.c: av7110 low level hardware access and firmware interface
3  *
4  * Copyright (C) 1999-2002 Ralph  Metzler
5  *                       & Marcus Metzler for convergence integrated media GmbH
6  *
7  * originally based on code by:
8  * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
9  *
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.
14  *
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.
19  *
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
24  *
25  * the project's page is at http://www.linuxtv.org/dvb/
26  */
27
28 /* for debugging ARM communication: */
29 //#define COM_DEBUG
30
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>
40
41 #include "av7110.h"
42 #include "av7110_hw.h"
43
44 /****************************************************************************
45  * DEBI functions
46  ****************************************************************************/
47
48 /* This DEBI code is based on the Stradis driver
49    by Nathan Laredo <laredo@gnu.org> */
50
51 int av7110_debiwrite(struct av7110 *av7110, u32 config,
52                      int addr, u32 val, int count)
53 {
54         struct saa7146_dev *dev = av7110->dev;
55
56         if (count <= 0 || count > 32764) {
57                 printk("%s: invalid count %d\n", __FUNCTION__, count);
58                 return -1;
59         }
60         if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
61                 printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
62                 return -1;
63         }
64         saa7146_write(dev, DEBI_CONFIG, config);
65         if (count <= 4)         /* immediate transfer */
66                 saa7146_write(dev, DEBI_AD, val);
67         else                    /* block transfer */
68                 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
69         saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
70         saa7146_write(dev, MC2, (2 << 16) | 2);
71         return 0;
72 }
73
74 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
75 {
76         struct saa7146_dev *dev = av7110->dev;
77         u32 result = 0;
78
79         if (count > 32764 || count <= 0) {
80                 printk("%s: invalid count %d\n", __FUNCTION__, count);
81                 return 0;
82         }
83         if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
84                 printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
85                 return 0;
86         }
87         saa7146_write(dev, DEBI_AD, av7110->debi_bus);
88         saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
89
90         saa7146_write(dev, DEBI_CONFIG, config);
91         saa7146_write(dev, MC2, (2 << 16) | 2);
92         if (count > 4)
93                 return count;
94         if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
95                 printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
96                 return 0;
97         }
98
99         result = saa7146_read(dev, DEBI_AD);
100         result &= (0xffffffffUL >> ((4 - count) * 8));
101         return result;
102 }
103
104
105
106 /* av7110 ARM core boot stuff */
107 #if 0
108 void av7110_reset_arm(struct av7110 *av7110)
109 {
110         saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
111
112         /* Disable DEBI and GPIO irq */
113         SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
114         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
115
116         saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
117         msleep(30);     /* the firmware needs some time to initialize */
118
119         ARM_ResetMailBox(av7110);
120
121         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
122         SAA7146_IER_ENABLE(av7110->dev, MASK_03);
123
124         av7110->arm_ready = 1;
125         dprintk(1, "reset ARM\n");
126 }
127 #endif  /*  0  */
128
129 static int waitdebi(struct av7110 *av7110, int adr, int state)
130 {
131         int k;
132
133         dprintk(4, "%p\n", av7110);
134
135         for (k = 0; k < 100; k++) {
136                 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
137                         return 0;
138                 udelay(5);
139         }
140         return -ETIMEDOUT;
141 }
142
143 static int load_dram(struct av7110 *av7110, u32 *data, int len)
144 {
145         int i;
146         int blocks, rest;
147         u32 base, bootblock = BOOT_BLOCK;
148
149         dprintk(4, "%p\n", av7110);
150
151         blocks = len / BOOT_MAX_SIZE;
152         rest = len % BOOT_MAX_SIZE;
153         base = DRAM_START_CODE;
154
155         for (i = 0; i < blocks; i++) {
156                 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
157                         printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
158                         return -ETIMEDOUT;
159                 }
160                 dprintk(4, "writing DRAM block %d\n", i);
161                 mwdebi(av7110, DEBISWAB, bootblock,
162                        ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
163                 bootblock ^= 0x1400;
164                 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
165                 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2);
166                 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
167                 base += BOOT_MAX_SIZE;
168         }
169
170         if (rest > 0) {
171                 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
172                         printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
173                         return -ETIMEDOUT;
174                 }
175                 if (rest > 4)
176                         mwdebi(av7110, DEBISWAB, bootblock,
177                                ((char*)data) + i * BOOT_MAX_SIZE, rest);
178                 else
179                         mwdebi(av7110, DEBISWAB, bootblock,
180                                ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4);
181
182                 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
183                 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
184                 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
185         }
186         if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
187                 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
188                 return -ETIMEDOUT;
189         }
190         iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
191         iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
192         if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) {
193                 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
194                 return -ETIMEDOUT;
195         }
196         return 0;
197 }
198
199
200 /* we cannot write av7110 DRAM directly, so load a bootloader into
201  * the DPRAM which implements a simple boot protocol */
202 static u8 bootcode[] = {
203   0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
204   0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
205   0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
206   0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
207   0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
208   0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
209   0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
210   0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
211   0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
212   0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
213   0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
214   0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
215   0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
216   0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
217   0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
218   0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
219   0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
220   0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
221 };
222
223 int av7110_bootarm(struct av7110 *av7110)
224 {
225         struct saa7146_dev *dev = av7110->dev;
226         u32 ret;
227         int i;
228
229         dprintk(4, "%p\n", av7110);
230
231         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
232
233         /* Disable DEBI and GPIO irq */
234         SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
235         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
236
237         /* enable DEBI */
238         saa7146_write(av7110->dev, MC1, 0x08800880);
239         saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
240         saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
241
242         /* test DEBI */
243         iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
244         if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
245                 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
246                        "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
247                        ret, 0x10325476);
248                 return -1;
249         }
250         for (i = 0; i < 8192; i += 4)
251                 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
252         dprintk(2, "debi test OK\n");
253
254         /* boot */
255         dprintk(1, "load boot code\n");
256         saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
257         //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
258         //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
259
260         mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
261         iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
262
263         if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
264                 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
265                        "saa7146_wait_for_debi_done() timed out\n");
266                 return -ETIMEDOUT;
267         }
268         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
269         mdelay(1);
270
271         dprintk(1, "load dram code\n");
272         if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
273                 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
274                        "load_dram() failed\n");
275                 return -1;
276         }
277
278         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
279         mdelay(1);
280
281         dprintk(1, "load dpram code\n");
282         mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
283
284         if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
285                 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
286                        "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
287                 return -ETIMEDOUT;
288         }
289         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
290         msleep(30);     /* the firmware needs some time to initialize */
291
292         //ARM_ClearIrq(av7110);
293         ARM_ResetMailBox(av7110);
294         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
295         SAA7146_IER_ENABLE(av7110->dev, MASK_03);
296
297         av7110->arm_errors = 0;
298         av7110->arm_ready = 1;
299         return 0;
300 }
301
302
303 /****************************************************************************
304  * DEBI command polling
305  ****************************************************************************/
306
307 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
308 {
309         unsigned long start;
310         u32 stat;
311
312         if (FW_VERSION(av7110->arm_app) <= 0x261c) {
313                 /* not supported by old firmware */
314                 msleep(50);
315                 return 0;
316         }
317
318         /* new firmware */
319         start = jiffies;
320         for (;;) {
321                 if (down_interruptible(&av7110->dcomlock))
322                         return -ERESTARTSYS;
323                 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
324                 up(&av7110->dcomlock);
325                 if ((stat & flags) == 0) {
326                         break;
327                 }
328                 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
329                         printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
330                                 __FUNCTION__, stat & flags);
331                         return -ETIMEDOUT;
332                 }
333                 msleep(1);
334         }
335         return 0;
336 }
337
338 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
339 {
340         int i;
341         unsigned long start;
342         char *type = NULL;
343         u16 flags[2] = {0, 0};
344         u32 stat;
345
346 //      dprintk(4, "%p\n", av7110);
347
348         if (!av7110->arm_ready) {
349                 dprintk(1, "arm not ready.\n");
350                 return -ENXIO;
351         }
352
353         start = jiffies;
354         while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
355                 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
356                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
357                         return -ETIMEDOUT;
358                 }
359                 msleep(1);
360         }
361
362         wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
363
364 #ifndef _NOHANDSHAKE
365         start = jiffies;
366         while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
367                 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
368                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
369                         return -ETIMEDOUT;
370                 }
371                 msleep(1);
372         }
373 #endif
374
375         switch ((buf[0] >> 8) & 0xff) {
376         case COMTYPE_PIDFILTER:
377         case COMTYPE_ENCODER:
378         case COMTYPE_REC_PLAY:
379         case COMTYPE_MPEGDECODER:
380                 type = "MSG";
381                 flags[0] = GPMQOver;
382                 flags[1] = GPMQFull;
383                 break;
384         case COMTYPE_OSD:
385                 type = "OSD";
386                 flags[0] = OSDQOver;
387                 flags[1] = OSDQFull;
388                 break;
389         case COMTYPE_MISC:
390                 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
391                         type = "MSG";
392                         flags[0] = GPMQOver;
393                         flags[1] = GPMQBusy;
394                 }
395                 break;
396         default:
397                 break;
398         }
399
400         if (type != NULL) {
401                 /* non-immediate COMMAND type */
402                 start = jiffies;
403                 for (;;) {
404                         stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
405                         if (stat & flags[0]) {
406                                 printk(KERN_ERR "%s: %s QUEUE overflow\n",
407                                         __FUNCTION__, type);
408                                 return -1;
409                         }
410                         if ((stat & flags[1]) == 0)
411                                 break;
412                         if (time_after(jiffies, start + ARM_WAIT_FREE)) {
413                                 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
414                                         __FUNCTION__, type);
415                                 return -ETIMEDOUT;
416                         }
417                         msleep(1);
418                 }
419         }
420
421         for (i = 2; i < length; i++)
422                 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
423
424         if (length)
425                 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
426         else
427                 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
428
429         wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
430
431         wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
432
433 #ifdef COM_DEBUG
434         start = jiffies;
435         while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
436                 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
437                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
438                                __FUNCTION__,
439                                 (buf[0] >> 8) & 0xff
440                                );
441                         return -ETIMEDOUT;
442                 }
443                 msleep(1);
444         }
445
446         stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
447         if (stat & GPMQOver) {
448                 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
449                 return -ENOSPC;
450         }
451         else if (stat & OSDQOver) {
452                 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
453                 return -ENOSPC;
454         }
455 #endif
456
457         return 0;
458 }
459
460 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
461 {
462         int ret;
463
464 //      dprintk(4, "%p\n", av7110);
465
466         if (!av7110->arm_ready) {
467                 dprintk(1, "arm not ready.\n");
468                 return -1;
469         }
470         if (down_interruptible(&av7110->dcomlock))
471                 return -ERESTARTSYS;
472
473         ret = __av7110_send_fw_cmd(av7110, buf, length);
474         up(&av7110->dcomlock);
475         if (ret && ret!=-ERESTARTSYS)
476                 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
477                        __FUNCTION__, ret);
478         return ret;
479 }
480
481 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
482 {
483         va_list args;
484         u16 buf[num + 2];
485         int i, ret;
486
487 //      dprintk(4, "%p\n", av7110);
488
489         buf[0] = ((type << 8) | com);
490         buf[1] = num;
491
492         if (num) {
493                 va_start(args, num);
494                 for (i = 0; i < num; i++)
495                         buf[i + 2] = va_arg(args, u32);
496                 va_end(args);
497         }
498
499         ret = av7110_send_fw_cmd(av7110, buf, num + 2);
500         if (ret && ret != -ERESTARTSYS)
501                 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
502         return ret;
503 }
504
505 #if 0
506 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
507 {
508         int i, ret;
509         u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
510                 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
511
512         dprintk(4, "%p\n", av7110);
513
514         for(i = 0; i < len && i < 32; i++)
515         {
516                 if(i % 2 == 0)
517                         cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
518                 else
519                         cmd[(i / 2) + 2] |= buf[i];
520         }
521
522         ret = av7110_send_fw_cmd(av7110, cmd, 18);
523         if (ret && ret != -ERESTARTSYS)
524                 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
525         return ret;
526 }
527 #endif  /*  0  */
528
529 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
530                       int request_buf_len, u16 *reply_buf, int reply_buf_len)
531 {
532         int err;
533         s16 i;
534         unsigned long start;
535 #ifdef COM_DEBUG
536         u32 stat;
537 #endif
538
539         dprintk(4, "%p\n", av7110);
540
541         if (!av7110->arm_ready) {
542                 dprintk(1, "arm not ready.\n");
543                 return -1;
544         }
545
546         if (down_interruptible(&av7110->dcomlock))
547                 return -ERESTARTSYS;
548
549         if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
550                 up(&av7110->dcomlock);
551                 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
552                 return err;
553         }
554
555         start = jiffies;
556         while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) {
557                 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
558                         printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
559                         up(&av7110->dcomlock);
560                         return -ETIMEDOUT;
561                 }
562 #ifdef _NOHANDSHAKE
563                 msleep(1);
564 #endif
565         }
566
567 #ifndef _NOHANDSHAKE
568         start = jiffies;
569         while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
570                 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
571                         printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
572                         up(&av7110->dcomlock);
573                         return -ETIMEDOUT;
574                 }
575                 msleep(1);
576         }
577 #endif
578
579 #ifdef COM_DEBUG
580         stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
581         if (stat & GPMQOver) {
582                 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
583                 up(&av7110->dcomlock);
584                 return -1;
585         }
586         else if (stat & OSDQOver) {
587                 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
588                 up(&av7110->dcomlock);
589                 return -1;
590         }
591 #endif
592
593         for (i = 0; i < reply_buf_len; i++)
594                 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
595
596         up(&av7110->dcomlock);
597         return 0;
598 }
599
600 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
601 {
602         int ret;
603         ret = av7110_fw_request(av7110, &tag, 0, buf, length);
604         if (ret)
605                 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
606         return ret;
607 }
608
609
610 /****************************************************************************
611  * Firmware commands
612  ****************************************************************************/
613
614 /* get version of the firmware ROM, RTSL, video ucode and ARM application  */
615 int av7110_firmversion(struct av7110 *av7110)
616 {
617         u16 buf[20];
618         u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
619
620         dprintk(4, "%p\n", av7110);
621
622         if (av7110_fw_query(av7110, tag, buf, 16)) {
623                 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
624                        av7110->dvb_adapter.num);
625                 return -EIO;
626         }
627
628         av7110->arm_fw = (buf[0] << 16) + buf[1];
629         av7110->arm_rtsl = (buf[2] << 16) + buf[3];
630         av7110->arm_vid = (buf[4] << 16) + buf[5];
631         av7110->arm_app = (buf[6] << 16) + buf[7];
632         av7110->avtype = (buf[8] << 16) + buf[9];
633
634         printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
635                av7110->dvb_adapter.num, av7110->arm_fw,
636                av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
637
638         /* print firmware capabilities */
639         if (FW_CI_LL_SUPPORT(av7110->arm_app))
640                 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
641                        av7110->dvb_adapter.num);
642         else
643                 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
644                        av7110->dvb_adapter.num);
645
646         return 0;
647 }
648
649
650 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
651 {
652         int i, ret;
653         u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
654                         16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
655
656         dprintk(4, "%p\n", av7110);
657
658         if (len > 10)
659                 len = 10;
660
661         buf[1] = len + 2;
662         buf[2] = len;
663
664         if (burst != -1)
665                 buf[3] = burst ? 0x01 : 0x00;
666         else
667                 buf[3] = 0xffff;
668
669         for (i = 0; i < len; i++)
670                 buf[i + 4] = msg[i];
671
672         ret = av7110_send_fw_cmd(av7110, buf, 18);
673         if (ret && ret!=-ERESTARTSYS)
674                 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
675         return ret;
676 }
677
678
679 #ifdef CONFIG_DVB_AV7110_OSD
680
681 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
682 {
683         return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
684 }
685
686 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
687                      enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
688 {
689         return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
690                              windownr, colordepth, index, blending);
691 }
692
693 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
694                      enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
695 {
696         return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
697                              windownr, colordepth, index, colorhi, colorlo);
698 }
699
700 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
701                           u16 colorfg, u16 colorbg)
702 {
703         return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
704                              windownr, fontsize, colorfg, colorbg);
705 }
706
707 static int FlushText(struct av7110 *av7110)
708 {
709         unsigned long start;
710
711         if (down_interruptible(&av7110->dcomlock))
712                 return -ERESTARTSYS;
713         start = jiffies;
714         while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
715                 if (time_after(jiffies, start + ARM_WAIT_OSD)) {
716                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
717                                __FUNCTION__);
718                         up(&av7110->dcomlock);
719                         return -ETIMEDOUT;
720                 }
721                 msleep(1);
722         }
723         up(&av7110->dcomlock);
724         return 0;
725 }
726
727 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
728 {
729         int i, ret;
730         unsigned long start;
731         int length = strlen(buf) + 1;
732         u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
733
734         if (down_interruptible(&av7110->dcomlock))
735                 return -ERESTARTSYS;
736
737         start = jiffies;
738         while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
739                 if (time_after(jiffies, start + ARM_WAIT_OSD)) {
740                         printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
741                                __FUNCTION__);
742                         up(&av7110->dcomlock);
743                         return -ETIMEDOUT;
744                 }
745                 msleep(1);
746         }
747 #ifndef _NOHANDSHAKE
748         start = jiffies;
749         while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) {
750                 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
751                         printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
752                                __FUNCTION__);
753                         up(&av7110->dcomlock);
754                         return -ETIMEDOUT;
755                 }
756                 msleep(1);
757         }
758 #endif
759         for (i = 0; i < length / 2; i++)
760                 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
761                       swab16(*(u16 *)(buf + 2 * i)), 2);
762         if (length & 1)
763                 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
764         ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
765         up(&av7110->dcomlock);
766         if (ret && ret!=-ERESTARTSYS)
767                 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
768         return ret;
769 }
770
771 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
772                            u16 x, u16 y, u16 dx, u16 dy, u16 color)
773 {
774         return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
775                              windownr, x, y, dx, dy, color);
776 }
777
778 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
779                             u16 x, u16 y, u16 dx, u16 dy, u16 color)
780 {
781         return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
782                              windownr, x, y, dx, dy, color);
783 }
784
785 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
786 {
787         return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
788 }
789
790 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
791 {
792         return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
793 }
794
795 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
796 {
797         return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
798 }
799
800 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
801 {
802         return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
803 }
804
805 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
806                                   osd_raw_window_t disptype,
807                                   u16 width, u16 height)
808 {
809         return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
810                              windownr, disptype, width, height);
811 }
812
813
814 static enum av7110_osd_palette_type bpp2pal[8] = {
815         Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
816 };
817 static osd_raw_window_t bpp2bit[8] = {
818         OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
819 };
820
821 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
822 {
823         int ret = wait_event_interruptible_timeout(av7110->bmpq,
824                                 av7110->bmp_state != BMP_LOADING, 10*HZ);
825         if (ret == -ERESTARTSYS)
826                 return ret;
827         if (ret == 0) {
828                 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
829                        ret, av7110->bmp_state);
830                 av7110->bmp_state = BMP_NONE;
831                 return -ETIMEDOUT;
832         }
833         return 0;
834 }
835
836 static inline int LoadBitmap(struct av7110 *av7110,
837                              u16 dx, u16 dy, int inc, u8 __user * data)
838 {
839         u16 format;
840         int bpp;
841         int i;
842         int d, delta;
843         u8 c;
844         int ret;
845
846         dprintk(4, "%p\n", av7110);
847
848         format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
849
850         av7110->bmp_state = BMP_LOADING;
851         if      (format == OSD_BITMAP8) {
852                 bpp=8; delta = 1;
853         } else if (format == OSD_BITMAP4) {
854                 bpp=4; delta = 2;
855         } else if (format == OSD_BITMAP2) {
856                 bpp=2; delta = 4;
857         } else if (format == OSD_BITMAP1) {
858                 bpp=1; delta = 8;
859         } else {
860                 av7110->bmp_state = BMP_NONE;
861                 return -EINVAL;
862         }
863         av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
864         av7110->bmpp = 0;
865         if (av7110->bmplen > 32768) {
866                 av7110->bmp_state = BMP_NONE;
867                 return -EINVAL;
868         }
869         for (i = 0; i < dy; i++) {
870                 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
871                         av7110->bmp_state = BMP_NONE;
872                         return -EINVAL;
873                 }
874         }
875         if (format != OSD_BITMAP8) {
876                 for (i = 0; i < dx * dy / delta; i++) {
877                         c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
878                         for (d = delta - 2; d >= 0; d--) {
879                                 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
880                                       << ((delta - d - 1) * bpp));
881                                 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
882                         }
883                 }
884         }
885         av7110->bmplen += 1024;
886         dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
887         ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
888         if (!ret)
889                 ret = WaitUntilBmpLoaded(av7110);
890         return ret;
891 }
892
893 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
894 {
895         dprintk(4, "%p\n", av7110);
896
897         return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
898 }
899
900 static inline int ReleaseBitmap(struct av7110 *av7110)
901 {
902         dprintk(4, "%p\n", av7110);
903
904         if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
905                 return -1;
906         if (av7110->bmp_state == BMP_LOADING)
907                 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
908         av7110->bmp_state = BMP_NONE;
909         return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
910 }
911
912 static u32 RGB2YUV(u16 R, u16 G, u16 B)
913 {
914         u16 y, u, v;
915         u16 Y, Cr, Cb;
916
917         y = R * 77 + G * 150 + B * 29;  /* Luma=0.299R+0.587G+0.114B 0..65535 */
918         u = 2048 + B * 8 -(y >> 5);     /* Cr 0..4095 */
919         v = 2048 + R * 8 -(y >> 5);     /* Cb 0..4095 */
920
921         Y = y / 256;
922         Cb = u / 16;
923         Cr = v / 16;
924
925         return Cr | (Cb << 16) | (Y << 8);
926 }
927
928 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
929 {
930         int ret;
931
932         u16 ch, cl;
933         u32 yuv;
934
935         yuv = blend ? RGB2YUV(r,g,b) : 0;
936         cl = (yuv & 0xffff);
937         ch = ((yuv >> 16) & 0xffff);
938         ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
939                         color, ch, cl);
940         if (!ret)
941                 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
942                                 color, ((blend >> 4) & 0x0f));
943         return ret;
944 }
945
946 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
947 {
948        int i;
949        int length = last - first + 1;
950
951        if (length * 4 > DATA_BUFF3_SIZE)
952                return -EINVAL;
953
954        for (i = 0; i < length; i++) {
955                u32 color, blend, yuv;
956
957                if (get_user(color, colors + i))
958                        return -EFAULT;
959                blend = (color & 0xF0000000) >> 4;
960                yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
961                                      (color >> 16) & 0xFF) | blend : 0;
962                yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
963                wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
964        }
965        return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
966                             av7110->osdwin,
967                             bpp2pal[av7110->osdbpp[av7110->osdwin]],
968                             first, last);
969 }
970
971 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
972                        int x1, int y1, int inc, u8 __user * data)
973 {
974         uint w, h, bpp, bpl, size, lpb, bnum, brest;
975         int i;
976         int rc,release_rc;
977
978         w = x1 - x0 + 1;
979         h = y1 - y0 + 1;
980         if (inc <= 0)
981                 inc = w;
982         if (w <= 0 || w > 720 || h <= 0 || h > 576)
983                 return -EINVAL;
984         bpp = av7110->osdbpp[av7110->osdwin] + 1;
985         bpl = ((w * bpp + 7) & ~7) / 8;
986         size = h * bpl;
987         lpb = (32 * 1024) / bpl;
988         bnum = size / (lpb * bpl);
989         brest = size - bnum * lpb * bpl;
990
991         if (av7110->bmp_state == BMP_LOADING) {
992                 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
993                 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
994                 rc = WaitUntilBmpLoaded(av7110);
995                 if (rc)
996                         return rc;
997                 /* just continue. This should work for all fw versions
998                  * if bnum==1 && !brest && LoadBitmap was successful
999                  */
1000         }
1001
1002         rc = 0;
1003         for (i = 0; i < bnum; i++) {
1004                 rc = LoadBitmap(av7110, w, lpb, inc, data);
1005                 if (rc)
1006                         break;
1007                 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1008                 if (rc)
1009                         break;
1010                 data += lpb * inc;
1011         }
1012         if (!rc && brest) {
1013                 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1014                 if (!rc)
1015                         rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1016         }
1017         release_rc = ReleaseBitmap(av7110);
1018         if (!rc)
1019                 rc = release_rc;
1020         if (rc)
1021                 dprintk(1,"returns %d\n",rc);
1022         return rc;
1023 }
1024
1025 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1026 {
1027         int ret;
1028
1029         if (down_interruptible(&av7110->osd_sema))
1030                 return -ERESTARTSYS;
1031
1032         switch (dc->cmd) {
1033         case OSD_Close:
1034                 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1035                 break;
1036         case OSD_Open:
1037                 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1038                 ret = CreateOSDWindow(av7110, av7110->osdwin,
1039                                 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1040                                 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1041                 if (ret)
1042                         break;
1043                 if (!dc->data) {
1044                         ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1045                         if (ret)
1046                                 break;
1047                         ret = SetColorBlend(av7110, av7110->osdwin);
1048                 }
1049                 break;
1050         case OSD_Show:
1051                 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1052                 break;
1053         case OSD_Hide:
1054                 ret = HideWindow(av7110, av7110->osdwin);
1055                 break;
1056         case OSD_Clear:
1057                 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1058                 break;
1059         case OSD_Fill:
1060                 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1061                 break;
1062         case OSD_SetColor:
1063                 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1064                 break;
1065         case OSD_SetPalette:
1066                 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1067                         ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1068                 else {
1069                         int i, len = dc->x0-dc->color+1;
1070                         u8 __user *colors = (u8 __user *)dc->data;
1071                         u8 r, g, b, blend;
1072                         ret = 0;
1073                         for (i = 0; i<len; i++) {
1074                                 if (get_user(r, colors + i * 4) ||
1075                                     get_user(g, colors + i * 4 + 1) ||
1076                                     get_user(b, colors + i * 4 + 2) ||
1077                                     get_user(blend, colors + i * 4 + 3)) {
1078                                         ret = -EFAULT;
1079                                         break;
1080                                     }
1081                                 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1082                                 if (ret)
1083                                         break;
1084                         }
1085                 }
1086                 break;
1087         case OSD_SetPixel:
1088                 ret = DrawLine(av7110, av7110->osdwin,
1089                          dc->x0, dc->y0, 0, 0, dc->color);
1090                 break;
1091         case OSD_SetRow:
1092                 dc->y1 = dc->y0;
1093                 /* fall through */
1094         case OSD_SetBlock:
1095                 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1096                 break;
1097         case OSD_FillRow:
1098                 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1099                           dc->x1-dc->x0+1, dc->y1, dc->color);
1100                 break;
1101         case OSD_FillBlock:
1102                 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1103                           dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1104                 break;
1105         case OSD_Line:
1106                 ret = DrawLine(av7110, av7110->osdwin,
1107                          dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1108                 break;
1109         case OSD_Text:
1110         {
1111                 char textbuf[240];
1112
1113                 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1114                         ret = -EFAULT;
1115                         break;
1116                 }
1117                 textbuf[239] = 0;
1118                 if (dc->x1 > 3)
1119                         dc->x1 = 3;
1120                 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1121                         (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1122                 if (!ret)
1123                         ret = FlushText(av7110);
1124                 if (!ret)
1125                         ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1126                 break;
1127         }
1128         case OSD_SetWindow:
1129                 if (dc->x0 < 1 || dc->x0 > 7)
1130                         ret = -EINVAL;
1131                 else {
1132                         av7110->osdwin = dc->x0;
1133                         ret = 0;
1134                 }
1135                 break;
1136         case OSD_MoveWindow:
1137                 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1138                 if (!ret)
1139                         ret = SetColorBlend(av7110, av7110->osdwin);
1140                 break;
1141         case OSD_OpenRaw:
1142                 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1143                         ret = -EINVAL;
1144                         break;
1145                 }
1146                 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1147                         av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1148                 else
1149                         av7110->osdbpp[av7110->osdwin] = 0;
1150                 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1151                                 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1152                 if (ret)
1153                         break;
1154                 if (!dc->data) {
1155                         ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1156                         if (!ret)
1157                                 ret = SetColorBlend(av7110, av7110->osdwin);
1158                 }
1159                 break;
1160         default:
1161                 ret = -EINVAL;
1162                 break;
1163         }
1164
1165         up(&av7110->osd_sema);
1166         if (ret==-ERESTARTSYS)
1167                 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1168         else if (ret)
1169                 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1170
1171         return ret;
1172 }
1173
1174 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1175 {
1176         switch (cap->cmd) {
1177         case OSD_CAP_MEMSIZE:
1178                 if (FW_4M_SDRAM(av7110->arm_app))
1179                         cap->val = 1000000;
1180                 else
1181                         cap->val = 92000;
1182                 return 0;
1183         default:
1184                 return -EINVAL;
1185         }
1186 }
1187 #endif /* CONFIG_DVB_AV7110_OSD */