Merge branch 'e1000'
[deliverable/linux.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 */
This page took 0.105241 seconds and 5 git commands to generate.