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