]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/dvb/ttpci/av7110_hw.c
4d7150e15d1e1378c244df17f95569bd15f44843
[linux-2.6-omap-h63xx.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/delay.h>
36 #include <linux/smp_lock.h>
37 #include <linux/fs.h>
38
39 #include "av7110.h"
40 #include "av7110_hw.h"
41
42 #define _NOHANDSHAKE
43
44 /****************************************************************************
45  * DEBI functions
46  ****************************************************************************/
47
48 /* This DEBI code is based on the Stradis driver
49    by Nathan Laredo <laredo@gnu.org> */
50
51 int av7110_debiwrite(struct av7110 *av7110, u32 config,
52                      int addr, u32 val, int count)
53 {
54         struct saa7146_dev *dev = av7110->dev;
55
56         if (count <= 0 || count > 32764) {
57                 printk("%s: invalid count %d\n", __FUNCTION__, count);
58                 return -1;
59         }
60         if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
61                 printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
62                 return -1;
63         }
64         saa7146_write(dev, DEBI_CONFIG, config);
65         if (count <= 4)         /* immediate transfer */
66                 saa7146_write(dev, DEBI_AD, val);
67         else                    /* block transfer */
68                 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
69         saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
70         saa7146_write(dev, MC2, (2 << 16) | 2);
71         return 0;
72 }
73
74 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
75 {
76         struct saa7146_dev *dev = av7110->dev;
77         u32 result = 0;
78
79         if (count > 32764 || count <= 0) {
80                 printk("%s: invalid count %d\n", __FUNCTION__, count);
81                 return 0;
82         }
83         if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
84                 printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
85                 return 0;
86         }
87         saa7146_write(dev, DEBI_AD, av7110->debi_bus);
88         saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
89
90         saa7146_write(dev, DEBI_CONFIG, config);
91         saa7146_write(dev, MC2, (2 << 16) | 2);
92         if (count > 4)
93                 return count;
94         if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
95                 printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
96                 return 0;
97         }
98
99         result = saa7146_read(dev, DEBI_AD);
100         result &= (0xffffffffUL >> ((4 - count) * 8));
101         return result;
102 }
103
104
105
106 /* av7110 ARM core boot stuff */
107 #if 0
108 void av7110_reset_arm(struct av7110 *av7110)
109 {
110         saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
111
112         /* Disable DEBI and GPIO irq */
113         SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
114         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
115
116         saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
117         msleep(30);     /* the firmware needs some time to initialize */
118
119         ARM_ResetMailBox(av7110);
120
121         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
122         SAA7146_IER_ENABLE(av7110->dev, MASK_03);
123
124         av7110->arm_ready = 1;
125         dprintk(1, "reset ARM\n");
126 }
127 #endif  /*  0  */
128
129 static int waitdebi(struct av7110 *av7110, int adr, int state)
130 {
131         int k;
132
133         dprintk(4, "%p\n", av7110);
134
135         for (k = 0; k < 100; k++) {
136                 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
137                         return 0;
138                 udelay(5);
139         }
140         return -ETIMEDOUT;
141 }
142
143 static int load_dram(struct av7110 *av7110, u32 *data, int len)
144 {
145         int i;
146         int blocks, rest;
147         u32 base, bootblock = AV7110_BOOT_BLOCK;
148
149         dprintk(4, "%p\n", av7110);
150
151         blocks = len / AV7110_BOOT_MAX_SIZE;
152         rest = len % AV7110_BOOT_MAX_SIZE;
153         base = DRAM_START_CODE;
154
155         for (i = 0; i < blocks; i++) {
156                 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
157                         printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
158                         return -ETIMEDOUT;
159                 }
160                 dprintk(4, "writing DRAM block %d\n", i);
161                 mwdebi(av7110, DEBISWAB, bootblock,
162                        ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
163                 bootblock ^= 0x1400;
164                 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
165                 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
166                 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
167                 base += AV7110_BOOT_MAX_SIZE;
168         }
169
170         if (rest > 0) {
171                 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
172                         printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
173                         return -ETIMEDOUT;
174                 }
175                 if (rest > 4)
176                         mwdebi(av7110, DEBISWAB, bootblock,
177                                ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
178                 else
179                         mwdebi(av7110, DEBISWAB, bootblock,
180                                ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
181
182                 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
183                 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
184                 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
185         }
186         if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
187                 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
188                 return -ETIMEDOUT;
189         }
190         iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
191         iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
192         if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
193                 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
194                 return -ETIMEDOUT;
195         }
196         return 0;
197 }
198
199
200 /* we cannot write av7110 DRAM directly, so load a bootloader into
201  * the DPRAM which implements a simple boot protocol */
202 static u8 bootcode[] = {
203   0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
204   0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
205   0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
206   0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
207   0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
208   0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
209   0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
210   0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
211   0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
212   0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
213   0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
214   0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
215   0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
216   0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
217   0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
218   0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
219   0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
220   0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
221 };
222
223 int av7110_bootarm(struct av7110 *av7110)
224 {
225         struct saa7146_dev *dev = av7110->dev;
226         u32 ret;
227         int i;
228
229         dprintk(4, "%p\n", av7110);
230
231         av7110->arm_ready = 0;
232
233         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
234
235         /* Disable DEBI and GPIO irq */
236         SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
237         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
238
239         /* enable DEBI */
240         saa7146_write(av7110->dev, MC1, 0x08800880);
241         saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
242         saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
243
244         /* test DEBI */
245         iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
246         /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
247         iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
248
249         if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
250                 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
251                        "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
252                        ret, 0x10325476);
253                 return -1;
254         }
255         for (i = 0; i < 8192; i += 4)
256                 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
257         dprintk(2, "debi test OK\n");
258
259         /* boot */
260         dprintk(1, "load boot code\n");
261         saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
262         //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
263         //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
264
265         mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
266         iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
267
268         if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
269                 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
270                        "saa7146_wait_for_debi_done() timed out\n");
271                 return -ETIMEDOUT;
272         }
273         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
274         mdelay(1);
275
276         dprintk(1, "load dram code\n");
277         if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
278                 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
279                        "load_dram() failed\n");
280                 return -1;
281         }
282
283         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
284         mdelay(1);
285
286         dprintk(1, "load dpram code\n");
287         mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
288
289         if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
290                 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
291                        "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
292                 return -ETIMEDOUT;
293         }
294         saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
295         msleep(30);     /* the firmware needs some time to initialize */
296
297         //ARM_ClearIrq(av7110);
298         ARM_ResetMailBox(av7110);
299         SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
300         SAA7146_IER_ENABLE(av7110->dev, MASK_03);
301
302         av7110->arm_errors = 0;
303         av7110->arm_ready = 1;
304         return 0;
305 }
306
307
308 /****************************************************************************
309  * DEBI command polling
310  ****************************************************************************/
311
312 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
313 {
314         unsigned long start;
315         u32 stat;
316         int err;
317
318         if (FW_VERSION(av7110->arm_app) <= 0x261c) {
319                 /* not supported by old firmware */
320                 msleep(50);
321                 return 0;
322         }
323
324         /* new firmware */
325         start = jiffies;
326         for (;;) {
327                 err = time_after(jiffies, start + ARM_WAIT_FREE);
328                 if (mutex_lock_interruptible(&av7110->dcomlock))
329                         return -ERESTARTSYS;
330                 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
331                 mutex_unlock(&av7110->dcomlock);
332                 if ((stat & flags) == 0)
333                         break;
334                 if (err) {
335                         printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
336                                 __FUNCTION__, stat & flags);
337                         return -ETIMEDOUT;
338                 }
339                 msleep(1);
340         }
341         return 0;
342 }
343
344 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
345 {
346         int i;
347         unsigned long start;
348         char *type = NULL;
349         u16 flags[2] = {0, 0};
350         u32 stat;
351         int err;
352
353 //      dprintk(4, "%p\n", av7110);
354
355         if (!av7110->arm_ready) {
356                 dprintk(1, "arm not ready.\n");
357                 return -ENXIO;
358         }
359
360         start = jiffies;
361         while (1) {
362                 err = time_after(jiffies, start + ARM_WAIT_FREE);
363                 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
364                         break;
365                 if (err) {
366                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
367                         av7110->arm_errors++;
368                         return -ETIMEDOUT;
369                 }
370                 msleep(1);
371         }
372
373         if (FW_VERSION(av7110->arm_app) <= 0x261f)
374                 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
375
376 #ifndef _NOHANDSHAKE
377         start = jiffies;
378         while (1) {
379                 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
380                 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
381                         break;
382                 if (err) {
383                         printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
384                         return -ETIMEDOUT;
385                 }
386                 msleep(1);
387         }
388 #endif
389
390         switch ((buf[0] >> 8) & 0xff) {
391         case COMTYPE_PIDFILTER:
392         case COMTYPE_ENCODER:
393         case COMTYPE_REC_PLAY:
394         case COMTYPE_MPEGDECODER:
395                 type = "MSG";
396                 flags[0] = GPMQOver;
397                 flags[1] = GPMQFull;
398                 break;
399         case COMTYPE_OSD:
400                 type = "OSD";
401                 flags[0] = OSDQOver;
402                 flags[1] = OSDQFull;
403                 break;
404         case COMTYPE_MISC:
405                 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
406                         type = "MSG";
407                         flags[0] = GPMQOver;
408                         flags[1] = GPMQBusy;
409                 }
410                 break;
411         default:
412                 break;
413         }
414
415         if (type != NULL) {
416                 /* non-immediate COMMAND type */
417                 start = jiffies;
418                 for (;;) {
419                         err = time_after(jiffies, start + ARM_WAIT_FREE);
420                         stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
421                         if (stat & flags[0]) {
422                                 printk(KERN_ERR "%s: %s QUEUE overflow\n",
423                                         __FUNCTION__, type);
424                                 return -1;
425                         }
426                         if ((stat & flags[1]) == 0)
427                                 break;
428                         if (err) {
429                                 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
430                                         __FUNCTION__, type);
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                                __FUNCTION__, (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", __FUNCTION__);
467                 return -ENOSPC;
468         }
469         else if (stat & OSDQOver) {
470                 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
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                        __FUNCTION__, 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", __FUNCTION__);
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", __FUNCTION__);
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", __FUNCTION__);
607                 mutex_unlock(&av7110->dcomlock);
608                 return -1;
609         }
610         else if (stat & OSDQOver) {
611                 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
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                                __FUNCTION__);
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, u8* 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                                __FUNCTION__);
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                                __FUNCTION__);
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 */