[PATCH] dvb: ttpci: fix timeout handling to be save with PREEMPT
[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         int err;
312
313         if (FW_VERSION(av7110->arm_app) <= 0x261c) {
314                 /* not supported by old firmware */
315                 msleep(50);
316                 return 0;
317         }
318
319         /* new firmware */
320         start = jiffies;
321         for (;;) {
322                 err = time_after(jiffies, start + ARM_WAIT_FREE);
323                 if (down_interruptible(&av7110->dcomlock))
324                         return -ERESTARTSYS;
325                 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
326                 up(&av7110->dcomlock);
327                 if ((stat & flags) == 0)
328                         break;
329                 if (err) {
330                         printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
331                                 __FUNCTION__, stat & flags);
332                         return -ETIMEDOUT;
333                 }
334                 msleep(1);
335         }
336         return 0;
337 }
338
339 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
340 {
341         int i;
342         unsigned long start;
343         char *type = NULL;
344         u16 flags[2] = {0, 0};
345         u32 stat;
346         int err;
347
348 //      dprintk(4, "%p\n", av7110);
349
350         if (!av7110->arm_ready) {
351                 dprintk(1, "arm not ready.\n");
352                 return -ENXIO;
353         }
354
355         start = jiffies;
356         while (1) {
357                 err = time_after(jiffies, start + ARM_WAIT_FREE);
358                 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
359                         break;
360                 if (err) {
361                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
362                         return -ETIMEDOUT;
363                 }
364                 msleep(1);
365         }
366
367         wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
368
369 #ifndef _NOHANDSHAKE
370         start = jiffies;
371         while (1) {
372                 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
373                 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
374                         break;
375                 if (err) {
376                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
377                         return -ETIMEDOUT;
378                 }
379                 msleep(1);
380         }
381 #endif
382
383         switch ((buf[0] >> 8) & 0xff) {
384         case COMTYPE_PIDFILTER:
385         case COMTYPE_ENCODER:
386         case COMTYPE_REC_PLAY:
387         case COMTYPE_MPEGDECODER:
388                 type = "MSG";
389                 flags[0] = GPMQOver;
390                 flags[1] = GPMQFull;
391                 break;
392         case COMTYPE_OSD:
393                 type = "OSD";
394                 flags[0] = OSDQOver;
395                 flags[1] = OSDQFull;
396                 break;
397         case COMTYPE_MISC:
398                 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
399                         type = "MSG";
400                         flags[0] = GPMQOver;
401                         flags[1] = GPMQBusy;
402                 }
403                 break;
404         default:
405                 break;
406         }
407
408         if (type != NULL) {
409                 /* non-immediate COMMAND type */
410                 start = jiffies;
411                 for (;;) {
412                         err = time_after(jiffies, start + ARM_WAIT_FREE);
413                         stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
414                         if (stat & flags[0]) {
415                                 printk(KERN_ERR "%s: %s QUEUE overflow\n",
416                                         __FUNCTION__, type);
417                                 return -1;
418                         }
419                         if ((stat & flags[1]) == 0)
420                                 break;
421                         if (err) {
422                                 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
423                                         __FUNCTION__, type);
424                                 return -ETIMEDOUT;
425                         }
426                         msleep(1);
427                 }
428         }
429
430         for (i = 2; i < length; i++)
431                 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
432
433         if (length)
434                 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
435         else
436                 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
437
438         wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
439
440         wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
441
442 #ifdef COM_DEBUG
443         start = jiffies;
444         while (1) {
445                 err = time_after(jiffies, start + ARM_WAIT_FREE);
446                 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
447                         break;
448                 if (err) {
449                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
450                                __FUNCTION__, (buf[0] >> 8) & 0xff);
451                         return -ETIMEDOUT;
452                 }
453                 msleep(1);
454         }
455
456         stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
457         if (stat & GPMQOver) {
458                 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
459                 return -ENOSPC;
460         }
461         else if (stat & OSDQOver) {
462                 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
463                 return -ENOSPC;
464         }
465 #endif
466
467         return 0;
468 }
469
470 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
471 {
472         int ret;
473
474 //      dprintk(4, "%p\n", av7110);
475
476         if (!av7110->arm_ready) {
477                 dprintk(1, "arm not ready.\n");
478                 return -1;
479         }
480         if (down_interruptible(&av7110->dcomlock))
481                 return -ERESTARTSYS;
482
483         ret = __av7110_send_fw_cmd(av7110, buf, length);
484         up(&av7110->dcomlock);
485         if (ret && ret!=-ERESTARTSYS)
486                 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
487                        __FUNCTION__, ret);
488         return ret;
489 }
490
491 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
492 {
493         va_list args;
494         u16 buf[num + 2];
495         int i, ret;
496
497 //      dprintk(4, "%p\n", av7110);
498
499         buf[0] = ((type << 8) | com);
500         buf[1] = num;
501
502         if (num) {
503                 va_start(args, num);
504                 for (i = 0; i < num; i++)
505                         buf[i + 2] = va_arg(args, u32);
506                 va_end(args);
507         }
508
509         ret = av7110_send_fw_cmd(av7110, buf, num + 2);
510         if (ret && ret != -ERESTARTSYS)
511                 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
512         return ret;
513 }
514
515 #if 0
516 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
517 {
518         int i, ret;
519         u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
520                 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
521
522         dprintk(4, "%p\n", av7110);
523
524         for(i = 0; i < len && i < 32; i++)
525         {
526                 if(i % 2 == 0)
527                         cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
528                 else
529                         cmd[(i / 2) + 2] |= buf[i];
530         }
531
532         ret = av7110_send_fw_cmd(av7110, cmd, 18);
533         if (ret && ret != -ERESTARTSYS)
534                 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
535         return ret;
536 }
537 #endif  /*  0  */
538
539 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
540                       int request_buf_len, u16 *reply_buf, int reply_buf_len)
541 {
542         int err;
543         s16 i;
544         unsigned long start;
545 #ifdef COM_DEBUG
546         u32 stat;
547 #endif
548
549         dprintk(4, "%p\n", av7110);
550
551         if (!av7110->arm_ready) {
552                 dprintk(1, "arm not ready.\n");
553                 return -1;
554         }
555
556         if (down_interruptible(&av7110->dcomlock))
557                 return -ERESTARTSYS;
558
559         if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
560                 up(&av7110->dcomlock);
561                 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
562                 return err;
563         }
564
565         start = jiffies;
566         while (1) {
567                 err = time_after(jiffies, start + ARM_WAIT_FREE);
568                 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
569                         break;
570                 if (err) {
571                         printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
572                         up(&av7110->dcomlock);
573                         return -ETIMEDOUT;
574                 }
575 #ifdef _NOHANDSHAKE
576                 msleep(1);
577 #endif
578         }
579
580 #ifndef _NOHANDSHAKE
581         start = jiffies;
582         while (1) {
583                 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
584                 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
585                         break;
586                 if (err) {
587                         printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
588                         up(&av7110->dcomlock);
589                         return -ETIMEDOUT;
590                 }
591                 msleep(1);
592         }
593 #endif
594
595 #ifdef COM_DEBUG
596         stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
597         if (stat & GPMQOver) {
598                 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
599                 up(&av7110->dcomlock);
600                 return -1;
601         }
602         else if (stat & OSDQOver) {
603                 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
604                 up(&av7110->dcomlock);
605                 return -1;
606         }
607 #endif
608
609         for (i = 0; i < reply_buf_len; i++)
610                 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
611
612         up(&av7110->dcomlock);
613         return 0;
614 }
615
616 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
617 {
618         int ret;
619         ret = av7110_fw_request(av7110, &tag, 0, buf, length);
620         if (ret)
621                 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
622         return ret;
623 }
624
625
626 /****************************************************************************
627  * Firmware commands
628  ****************************************************************************/
629
630 /* get version of the firmware ROM, RTSL, video ucode and ARM application  */
631 int av7110_firmversion(struct av7110 *av7110)
632 {
633         u16 buf[20];
634         u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
635
636         dprintk(4, "%p\n", av7110);
637
638         if (av7110_fw_query(av7110, tag, buf, 16)) {
639                 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
640                        av7110->dvb_adapter.num);
641                 return -EIO;
642         }
643
644         av7110->arm_fw = (buf[0] << 16) + buf[1];
645         av7110->arm_rtsl = (buf[2] << 16) + buf[3];
646         av7110->arm_vid = (buf[4] << 16) + buf[5];
647         av7110->arm_app = (buf[6] << 16) + buf[7];
648         av7110->avtype = (buf[8] << 16) + buf[9];
649
650         printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
651                av7110->dvb_adapter.num, av7110->arm_fw,
652                av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
653
654         /* print firmware capabilities */
655         if (FW_CI_LL_SUPPORT(av7110->arm_app))
656                 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
657                        av7110->dvb_adapter.num);
658         else
659                 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
660                        av7110->dvb_adapter.num);
661
662         return 0;
663 }
664
665
666 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
667 {
668         int i, ret;
669         u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
670                         16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
671
672         dprintk(4, "%p\n", av7110);
673
674         if (len > 10)
675                 len = 10;
676
677         buf[1] = len + 2;
678         buf[2] = len;
679
680         if (burst != -1)
681                 buf[3] = burst ? 0x01 : 0x00;
682         else
683                 buf[3] = 0xffff;
684
685         for (i = 0; i < len; i++)
686                 buf[i + 4] = msg[i];
687
688         ret = av7110_send_fw_cmd(av7110, buf, 18);
689         if (ret && ret!=-ERESTARTSYS)
690                 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
691         return ret;
692 }
693
694
695 #ifdef CONFIG_DVB_AV7110_OSD
696
697 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
698 {
699         return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
700 }
701
702 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
703                      enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
704 {
705         return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
706                              windownr, colordepth, index, blending);
707 }
708
709 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
710                      enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
711 {
712         return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
713                              windownr, colordepth, index, colorhi, colorlo);
714 }
715
716 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
717                           u16 colorfg, u16 colorbg)
718 {
719         return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
720                              windownr, fontsize, colorfg, colorbg);
721 }
722
723 static int FlushText(struct av7110 *av7110)
724 {
725         unsigned long start;
726         int err;
727
728         if (down_interruptible(&av7110->dcomlock))
729                 return -ERESTARTSYS;
730         start = jiffies;
731         while (1) {
732                 err = time_after(jiffies, start + ARM_WAIT_OSD);
733                 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
734                         break;
735                 if (err) {
736                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
737                                __FUNCTION__);
738                         up(&av7110->dcomlock);
739                         return -ETIMEDOUT;
740                 }
741                 msleep(1);
742         }
743         up(&av7110->dcomlock);
744         return 0;
745 }
746
747 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
748 {
749         int i, ret;
750         unsigned long start;
751         int length = strlen(buf) + 1;
752         u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
753
754         if (down_interruptible(&av7110->dcomlock))
755                 return -ERESTARTSYS;
756
757         start = jiffies;
758         while (1) {
759                 ret = time_after(jiffies, start + ARM_WAIT_OSD);
760                 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
761                         break;
762                 if (ret) {
763                         printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
764                                __FUNCTION__);
765                         up(&av7110->dcomlock);
766                         return -ETIMEDOUT;
767                 }
768                 msleep(1);
769         }
770 #ifndef _NOHANDSHAKE
771         start = jiffies;
772         while (1) {
773                 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
774                 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
775                         break;
776                 if (ret) {
777                         printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
778                                __FUNCTION__);
779                         up(&av7110->dcomlock);
780                         return -ETIMEDOUT;
781                 }
782                 msleep(1);
783         }
784 #endif
785         for (i = 0; i < length / 2; i++)
786                 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
787                       swab16(*(u16 *)(buf + 2 * i)), 2);
788         if (length & 1)
789                 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
790         ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
791         up(&av7110->dcomlock);
792         if (ret && ret!=-ERESTARTSYS)
793                 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
794         return ret;
795 }
796
797 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
798                            u16 x, u16 y, u16 dx, u16 dy, u16 color)
799 {
800         return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
801                              windownr, x, y, dx, dy, color);
802 }
803
804 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
805                             u16 x, u16 y, u16 dx, u16 dy, u16 color)
806 {
807         return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
808                              windownr, x, y, dx, dy, color);
809 }
810
811 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
812 {
813         return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
814 }
815
816 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
817 {
818         return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
819 }
820
821 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
822 {
823         return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
824 }
825
826 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
827 {
828         return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
829 }
830
831 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
832                                   osd_raw_window_t disptype,
833                                   u16 width, u16 height)
834 {
835         return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
836                              windownr, disptype, width, height);
837 }
838
839
840 static enum av7110_osd_palette_type bpp2pal[8] = {
841         Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
842 };
843 static osd_raw_window_t bpp2bit[8] = {
844         OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
845 };
846
847 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
848 {
849         int ret = wait_event_interruptible_timeout(av7110->bmpq,
850                                 av7110->bmp_state != BMP_LOADING, 10*HZ);
851         if (ret == -ERESTARTSYS)
852                 return ret;
853         if (ret == 0) {
854                 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
855                        ret, av7110->bmp_state);
856                 av7110->bmp_state = BMP_NONE;
857                 return -ETIMEDOUT;
858         }
859         return 0;
860 }
861
862 static inline int LoadBitmap(struct av7110 *av7110,
863                              u16 dx, u16 dy, int inc, u8 __user * data)
864 {
865         u16 format;
866         int bpp;
867         int i;
868         int d, delta;
869         u8 c;
870         int ret;
871
872         dprintk(4, "%p\n", av7110);
873
874         format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
875
876         av7110->bmp_state = BMP_LOADING;
877         if      (format == OSD_BITMAP8) {
878                 bpp=8; delta = 1;
879         } else if (format == OSD_BITMAP4) {
880                 bpp=4; delta = 2;
881         } else if (format == OSD_BITMAP2) {
882                 bpp=2; delta = 4;
883         } else if (format == OSD_BITMAP1) {
884                 bpp=1; delta = 8;
885         } else {
886                 av7110->bmp_state = BMP_NONE;
887                 return -EINVAL;
888         }
889         av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
890         av7110->bmpp = 0;
891         if (av7110->bmplen > 32768) {
892                 av7110->bmp_state = BMP_NONE;
893                 return -EINVAL;
894         }
895         for (i = 0; i < dy; i++) {
896                 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
897                         av7110->bmp_state = BMP_NONE;
898                         return -EINVAL;
899                 }
900         }
901         if (format != OSD_BITMAP8) {
902                 for (i = 0; i < dx * dy / delta; i++) {
903                         c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
904                         for (d = delta - 2; d >= 0; d--) {
905                                 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
906                                       << ((delta - d - 1) * bpp));
907                                 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
908                         }
909                 }
910         }
911         av7110->bmplen += 1024;
912         dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
913         ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
914         if (!ret)
915                 ret = WaitUntilBmpLoaded(av7110);
916         return ret;
917 }
918
919 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
920 {
921         dprintk(4, "%p\n", av7110);
922
923         return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
924 }
925
926 static inline int ReleaseBitmap(struct av7110 *av7110)
927 {
928         dprintk(4, "%p\n", av7110);
929
930         if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
931                 return -1;
932         if (av7110->bmp_state == BMP_LOADING)
933                 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
934         av7110->bmp_state = BMP_NONE;
935         return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
936 }
937
938 static u32 RGB2YUV(u16 R, u16 G, u16 B)
939 {
940         u16 y, u, v;
941         u16 Y, Cr, Cb;
942
943         y = R * 77 + G * 150 + B * 29;  /* Luma=0.299R+0.587G+0.114B 0..65535 */
944         u = 2048 + B * 8 -(y >> 5);     /* Cr 0..4095 */
945         v = 2048 + R * 8 -(y >> 5);     /* Cb 0..4095 */
946
947         Y = y / 256;
948         Cb = u / 16;
949         Cr = v / 16;
950
951         return Cr | (Cb << 16) | (Y << 8);
952 }
953
954 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
955 {
956         int ret;
957
958         u16 ch, cl;
959         u32 yuv;
960
961         yuv = blend ? RGB2YUV(r,g,b) : 0;
962         cl = (yuv & 0xffff);
963         ch = ((yuv >> 16) & 0xffff);
964         ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
965                         color, ch, cl);
966         if (!ret)
967                 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
968                                 color, ((blend >> 4) & 0x0f));
969         return ret;
970 }
971
972 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
973 {
974        int i;
975        int length = last - first + 1;
976
977        if (length * 4 > DATA_BUFF3_SIZE)
978                return -EINVAL;
979
980        for (i = 0; i < length; i++) {
981                u32 color, blend, yuv;
982
983                if (get_user(color, colors + i))
984                        return -EFAULT;
985                blend = (color & 0xF0000000) >> 4;
986                yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
987                                      (color >> 16) & 0xFF) | blend : 0;
988                yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
989                wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
990        }
991        return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
992                             av7110->osdwin,
993                             bpp2pal[av7110->osdbpp[av7110->osdwin]],
994                             first, last);
995 }
996
997 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
998                        int x1, int y1, int inc, u8 __user * data)
999 {
1000         uint w, h, bpp, bpl, size, lpb, bnum, brest;
1001         int i;
1002         int rc,release_rc;
1003
1004         w = x1 - x0 + 1;
1005         h = y1 - y0 + 1;
1006         if (inc <= 0)
1007                 inc = w;
1008         if (w <= 0 || w > 720 || h <= 0 || h > 576)
1009                 return -EINVAL;
1010         bpp = av7110->osdbpp[av7110->osdwin] + 1;
1011         bpl = ((w * bpp + 7) & ~7) / 8;
1012         size = h * bpl;
1013         lpb = (32 * 1024) / bpl;
1014         bnum = size / (lpb * bpl);
1015         brest = size - bnum * lpb * bpl;
1016
1017         if (av7110->bmp_state == BMP_LOADING) {
1018                 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1019                 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1020                 rc = WaitUntilBmpLoaded(av7110);
1021                 if (rc)
1022                         return rc;
1023                 /* just continue. This should work for all fw versions
1024                  * if bnum==1 && !brest && LoadBitmap was successful
1025                  */
1026         }
1027
1028         rc = 0;
1029         for (i = 0; i < bnum; i++) {
1030                 rc = LoadBitmap(av7110, w, lpb, inc, data);
1031                 if (rc)
1032                         break;
1033                 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1034                 if (rc)
1035                         break;
1036                 data += lpb * inc;
1037         }
1038         if (!rc && brest) {
1039                 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1040                 if (!rc)
1041                         rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1042         }
1043         release_rc = ReleaseBitmap(av7110);
1044         if (!rc)
1045                 rc = release_rc;
1046         if (rc)
1047                 dprintk(1,"returns %d\n",rc);
1048         return rc;
1049 }
1050
1051 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1052 {
1053         int ret;
1054
1055         if (down_interruptible(&av7110->osd_sema))
1056                 return -ERESTARTSYS;
1057
1058         switch (dc->cmd) {
1059         case OSD_Close:
1060                 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1061                 break;
1062         case OSD_Open:
1063                 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1064                 ret = CreateOSDWindow(av7110, av7110->osdwin,
1065                                 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1066                                 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1067                 if (ret)
1068                         break;
1069                 if (!dc->data) {
1070                         ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1071                         if (ret)
1072                                 break;
1073                         ret = SetColorBlend(av7110, av7110->osdwin);
1074                 }
1075                 break;
1076         case OSD_Show:
1077                 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1078                 break;
1079         case OSD_Hide:
1080                 ret = HideWindow(av7110, av7110->osdwin);
1081                 break;
1082         case OSD_Clear:
1083                 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1084                 break;
1085         case OSD_Fill:
1086                 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1087                 break;
1088         case OSD_SetColor:
1089                 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1090                 break;
1091         case OSD_SetPalette:
1092                 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1093                         ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1094                 else {
1095                         int i, len = dc->x0-dc->color+1;
1096                         u8 __user *colors = (u8 __user *)dc->data;
1097                         u8 r, g, b, blend;
1098                         ret = 0;
1099                         for (i = 0; i<len; i++) {
1100                                 if (get_user(r, colors + i * 4) ||
1101                                     get_user(g, colors + i * 4 + 1) ||
1102                                     get_user(b, colors + i * 4 + 2) ||
1103                                     get_user(blend, colors + i * 4 + 3)) {
1104                                         ret = -EFAULT;
1105                                         break;
1106                                     }
1107                                 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1108                                 if (ret)
1109                                         break;
1110                         }
1111                 }
1112                 break;
1113         case OSD_SetPixel:
1114                 ret = DrawLine(av7110, av7110->osdwin,
1115                          dc->x0, dc->y0, 0, 0, dc->color);
1116                 break;
1117         case OSD_SetRow:
1118                 dc->y1 = dc->y0;
1119                 /* fall through */
1120         case OSD_SetBlock:
1121                 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1122                 break;
1123         case OSD_FillRow:
1124                 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1125                           dc->x1-dc->x0+1, dc->y1, dc->color);
1126                 break;
1127         case OSD_FillBlock:
1128                 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1129                           dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1130                 break;
1131         case OSD_Line:
1132                 ret = DrawLine(av7110, av7110->osdwin,
1133                          dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1134                 break;
1135         case OSD_Text:
1136         {
1137                 char textbuf[240];
1138
1139                 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1140                         ret = -EFAULT;
1141                         break;
1142                 }
1143                 textbuf[239] = 0;
1144                 if (dc->x1 > 3)
1145                         dc->x1 = 3;
1146                 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1147                         (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1148                 if (!ret)
1149                         ret = FlushText(av7110);
1150                 if (!ret)
1151                         ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1152                 break;
1153         }
1154         case OSD_SetWindow:
1155                 if (dc->x0 < 1 || dc->x0 > 7)
1156                         ret = -EINVAL;
1157                 else {
1158                         av7110->osdwin = dc->x0;
1159                         ret = 0;
1160                 }
1161                 break;
1162         case OSD_MoveWindow:
1163                 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1164                 if (!ret)
1165                         ret = SetColorBlend(av7110, av7110->osdwin);
1166                 break;
1167         case OSD_OpenRaw:
1168                 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1169                         ret = -EINVAL;
1170                         break;
1171                 }
1172                 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1173                         av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1174                 else
1175                         av7110->osdbpp[av7110->osdwin] = 0;
1176                 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1177                                 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1178                 if (ret)
1179                         break;
1180                 if (!dc->data) {
1181                         ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1182                         if (!ret)
1183                                 ret = SetColorBlend(av7110, av7110->osdwin);
1184                 }
1185                 break;
1186         default:
1187                 ret = -EINVAL;
1188                 break;
1189         }
1190
1191         up(&av7110->osd_sema);
1192         if (ret==-ERESTARTSYS)
1193                 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1194         else if (ret)
1195                 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1196
1197         return ret;
1198 }
1199
1200 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1201 {
1202         switch (cap->cmd) {
1203         case OSD_CAP_MEMSIZE:
1204                 if (FW_4M_SDRAM(av7110->arm_app))
1205                         cap->val = 1000000;
1206                 else
1207                         cap->val = 92000;
1208                 return 0;
1209         default:
1210                 return -EINVAL;
1211         }
1212 }
1213 #endif /* CONFIG_DVB_AV7110_OSD */