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