Merge branch 'for-linus' of git://linux-nfs.org/~bfields/linux
[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/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 */
This page took 0.063255 seconds and 5 git commands to generate.