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