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