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