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