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