Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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