V4L/DVB (5835): saa7146/dvb-ttpci: Fix signedness warnings (gcc 4.1.1, kernel 2.6.22)
[deliverable/linux.git] / drivers / media / dvb / ttpci / av7110_hw.c
CommitLineData
1da177e4
LT
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>
1da177e4 35#include <linux/delay.h>
1da177e4
LT
36#include <linux/fs.h>
37
38#include "av7110.h"
39#include "av7110_hw.h"
40
ce7d3c11
JS
41#define _NOHANDSHAKE
42
1da177e4
LT
43/****************************************************************************
44 * DEBI functions
45 ****************************************************************************/
46
47/* This DEBI code is based on the Stradis driver
48 by Nathan Laredo <laredo@gnu.org> */
49
50int 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
73u32 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 */
d91b730d 106#if 0
1da177e4
LT
107void 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}
d91b730d 126#endif /* 0 */
1da177e4
LT
127
128static 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 }
c9090ebb 139 return -ETIMEDOUT;
1da177e4
LT
140}
141
142static int load_dram(struct av7110 *av7110, u32 *data, int len)
143{
144 int i;
145 int blocks, rest;
fabd2386 146 u32 base, bootblock = AV7110_BOOT_BLOCK;
1da177e4
LT
147
148 dprintk(4, "%p\n", av7110);
149
fabd2386
MCC
150 blocks = len / AV7110_BOOT_MAX_SIZE;
151 rest = len % AV7110_BOOT_MAX_SIZE;
1da177e4
LT
152 base = DRAM_START_CODE;
153
154 for (i = 0; i < blocks; i++) {
fabd2386 155 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
1da177e4 156 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
c9090ebb 157 return -ETIMEDOUT;
1da177e4
LT
158 }
159 dprintk(4, "writing DRAM block %d\n", i);
160 mwdebi(av7110, DEBISWAB, bootblock,
804b4458 161 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
1da177e4 162 bootblock ^= 0x1400;
fabd2386
MCC
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;
1da177e4
LT
167 }
168
169 if (rest > 0) {
fabd2386 170 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
1da177e4 171 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
c9090ebb 172 return -ETIMEDOUT;
1da177e4
LT
173 }
174 if (rest > 4)
175 mwdebi(av7110, DEBISWAB, bootblock,
804b4458 176 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, rest);
1da177e4
LT
177 else
178 mwdebi(av7110, DEBISWAB, bootblock,
804b4458 179 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
1da177e4 180
fabd2386
MCC
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);
1da177e4 184 }
fabd2386 185 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
1da177e4 186 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
c9090ebb 187 return -ETIMEDOUT;
1da177e4 188 }
fabd2386
MCC
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) {
1da177e4 192 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
c9090ebb 193 return -ETIMEDOUT;
1da177e4
LT
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 */
201static 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
222int 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
66190a27
OE
230 av7110->arm_ready = 0;
231
1da177e4
LT
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);
9f3319b4
MS
245 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
246 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
247
1da177e4
LT
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));
fabd2386 265 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
1da177e4
LT
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");
c9090ebb 270 return -ETIMEDOUT;
1da177e4
LT
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");
c9090ebb 291 return -ETIMEDOUT;
1da177e4
LT
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
311int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
312{
313 unsigned long start;
314 u32 stat;
25de1926 315 int err;
1da177e4
LT
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 (;;) {
25de1926 326 err = time_after(jiffies, start + ARM_WAIT_FREE);
3593cab5 327 if (mutex_lock_interruptible(&av7110->dcomlock))
1da177e4
LT
328 return -ERESTARTSYS;
329 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
3593cab5 330 mutex_unlock(&av7110->dcomlock);
25de1926 331 if ((stat & flags) == 0)
1da177e4 332 break;
25de1926 333 if (err) {
1da177e4
LT
334 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
335 __FUNCTION__, stat & flags);
c9090ebb 336 return -ETIMEDOUT;
1da177e4
LT
337 }
338 msleep(1);
339 }
340 return 0;
341}
342
d91b730d 343static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
1da177e4
LT
344{
345 int i;
346 unsigned long start;
347 char *type = NULL;
348 u16 flags[2] = {0, 0};
349 u32 stat;
25de1926 350 int err;
1da177e4
LT
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;
25de1926
OE
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) {
1da177e4 365 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
66190a27 366 av7110->arm_errors++;
1da177e4
LT
367 return -ETIMEDOUT;
368 }
7d87bc39 369 msleep(1);
1da177e4
LT
370 }
371
9a7b102e
OE
372 if (FW_VERSION(av7110->arm_app) <= 0x261f)
373 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
1da177e4
LT
374
375#ifndef _NOHANDSHAKE
376 start = jiffies;
25de1926
OE
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) {
1da177e4
LT
382 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
383 return -ETIMEDOUT;
384 }
7d87bc39 385 msleep(1);
1da177e4
LT
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 (;;) {
25de1926 418 err = time_after(jiffies, start + ARM_WAIT_FREE);
1da177e4
LT
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;
25de1926 427 if (err) {
1da177e4
LT
428 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
429 __FUNCTION__, type);
c9090ebb 430 return -ETIMEDOUT;
1da177e4
LT
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
9a7b102e
OE
446 if (FW_VERSION(av7110->arm_app) <= 0x261f)
447 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
1da177e4
LT
448
449#ifdef COM_DEBUG
450 start = jiffies;
25de1926
OE
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) {
c9090ebb 456 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
25de1926 457 __FUNCTION__, (buf[0] >> 8) & 0xff);
1da177e4
LT
458 return -ETIMEDOUT;
459 }
7d87bc39 460 msleep(1);
1da177e4
LT
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
d91b730d 477static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
1da177e4
LT
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 }
3593cab5 487 if (mutex_lock_interruptible(&av7110->dcomlock))
1da177e4
LT
488 return -ERESTARTSYS;
489
490 ret = __av7110_send_fw_cmd(av7110, buf, length);
3593cab5 491 mutex_unlock(&av7110->dcomlock);
c9090ebb 492 if (ret && ret!=-ERESTARTSYS)
1da177e4
LT
493 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
494 __FUNCTION__, ret);
495 return ret;
496}
497
498int 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);
c9090ebb 517 if (ret && ret != -ERESTARTSYS)
1da177e4
LT
518 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
519 return ret;
520}
521
d91b730d 522#if 0
1da177e4
LT
523int 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);
c9090ebb 540 if (ret && ret != -ERESTARTSYS)
1da177e4
LT
541 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
542 return ret;
543}
d91b730d 544#endif /* 0 */
1da177e4
LT
545
546int 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
3593cab5 563 if (mutex_lock_interruptible(&av7110->dcomlock))
1da177e4
LT
564 return -ERESTARTSYS;
565
566 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
3593cab5 567 mutex_unlock(&av7110->dcomlock);
1da177e4
LT
568 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
569 return err;
570 }
571
572 start = jiffies;
25de1926
OE
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) {
1da177e4 578 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
3593cab5 579 mutex_unlock(&av7110->dcomlock);
c9090ebb 580 return -ETIMEDOUT;
1da177e4 581 }
7d87bc39
JS
582#ifdef _NOHANDSHAKE
583 msleep(1);
584#endif
1da177e4
LT
585 }
586
587#ifndef _NOHANDSHAKE
588 start = jiffies;
25de1926
OE
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) {
1da177e4 594 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
3593cab5 595 mutex_unlock(&av7110->dcomlock);
c9090ebb 596 return -ETIMEDOUT;
1da177e4 597 }
7d87bc39 598 msleep(1);
1da177e4
LT
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__);
3593cab5 606 mutex_unlock(&av7110->dcomlock);
1da177e4
LT
607 return -1;
608 }
609 else if (stat & OSDQOver) {
610 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
3593cab5 611 mutex_unlock(&av7110->dcomlock);
1da177e4
LT
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
3593cab5 619 mutex_unlock(&av7110->dcomlock);
1da177e4
LT
620 return 0;
621}
622
d91b730d 623static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
1da177e4
LT
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 */
638int 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",
fdc53a6d 647 av7110->dvb_adapter.num);
1da177e4
LT
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",
fdc53a6d 658 av7110->dvb_adapter.num, av7110->arm_fw,
1da177e4
LT
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",
fdc53a6d 664 av7110->dvb_adapter.num);
1da177e4
LT
665 else
666 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
fdc53a6d 667 av7110->dvb_adapter.num);
1da177e4
LT
668
669 return 0;
670}
671
672
673int 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
c9090ebb
WR
695 ret = av7110_send_fw_cmd(av7110, buf, 18);
696 if (ret && ret!=-ERESTARTSYS)
1da177e4 697 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
c9090ebb 698 return ret;
1da177e4
LT
699}
700
701
702#ifdef CONFIG_DVB_AV7110_OSD
703
704static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
705{
706 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
707}
708
709static 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
716static 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
723static 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
730static int FlushText(struct av7110 *av7110)
731{
732 unsigned long start;
25de1926 733 int err;
1da177e4 734
3593cab5 735 if (mutex_lock_interruptible(&av7110->dcomlock))
1da177e4
LT
736 return -ERESTARTSYS;
737 start = jiffies;
25de1926
OE
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) {
1da177e4
LT
743 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
744 __FUNCTION__);
3593cab5 745 mutex_unlock(&av7110->dcomlock);
c9090ebb 746 return -ETIMEDOUT;
1da177e4 747 }
7d87bc39 748 msleep(1);
1da177e4 749 }
3593cab5 750 mutex_unlock(&av7110->dcomlock);
1da177e4
LT
751 return 0;
752}
753
804b4458 754static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
1da177e4
LT
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
3593cab5 761 if (mutex_lock_interruptible(&av7110->dcomlock))
1da177e4
LT
762 return -ERESTARTSYS;
763
764 start = jiffies;
25de1926
OE
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) {
1da177e4
LT
770 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
771 __FUNCTION__);
3593cab5 772 mutex_unlock(&av7110->dcomlock);
c9090ebb 773 return -ETIMEDOUT;
1da177e4 774 }
7d87bc39 775 msleep(1);
1da177e4
LT
776 }
777#ifndef _NOHANDSHAKE
778 start = jiffies;
25de1926
OE
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) {
1da177e4
LT
784 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
785 __FUNCTION__);
3593cab5 786 mutex_unlock(&av7110->dcomlock);
c9090ebb 787 return -ETIMEDOUT;
1da177e4 788 }
7d87bc39 789 msleep(1);
1da177e4
LT
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);
3593cab5 798 mutex_unlock(&av7110->dcomlock);
c9090ebb 799 if (ret && ret!=-ERESTARTSYS)
1da177e4
LT
800 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
801 return ret;
802}
803
804static 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
811static 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
818static inline int HideWindow(struct av7110 *av7110, u8 windownr)
819{
820 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
821}
822
823static 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
828static 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
833static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
834{
835 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
836}
837
838static 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
847static enum av7110_osd_palette_type bpp2pal[8] = {
848 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
849};
850static osd_raw_window_t bpp2bit[8] = {
851 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
852};
853
c9090ebb
WR
854static 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
869static inline int LoadBitmap(struct av7110 *av7110,
1da177e4
LT
870 u16 dx, u16 dy, int inc, u8 __user * data)
871{
c9090ebb 872 u16 format;
1da177e4
LT
873 int bpp;
874 int i;
875 int d, delta;
876 u8 c;
877 int ret;
878
879 dprintk(4, "%p\n", av7110);
880
c9090ebb 881 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
1da177e4
LT
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;
c9090ebb 894 return -EINVAL;
1da177e4
LT
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;
c9090ebb 900 return -EINVAL;
1da177e4
LT
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;
c9090ebb 905 return -EINVAL;
1da177e4
LT
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);
c9090ebb
WR
920 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
921 if (!ret)
922 ret = WaitUntilBmpLoaded(av7110);
923 return ret;
1da177e4
LT
924}
925
c9090ebb 926static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
1da177e4 927{
1da177e4
LT
928 dprintk(4, "%p\n", av7110);
929
c9090ebb 930 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
1da177e4
LT
931}
932
933static inline int ReleaseBitmap(struct av7110 *av7110)
934{
935 dprintk(4, "%p\n", av7110);
936
c9090ebb 937 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
1da177e4 938 return -1;
c9090ebb
WR
939 if (av7110->bmp_state == BMP_LOADING)
940 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
1da177e4
LT
941 av7110->bmp_state = BMP_NONE;
942 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
943}
944
945static 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
c9090ebb 961static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
1da177e4 962{
c9090ebb
WR
963 int ret;
964
1da177e4
LT
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);
c9090ebb
WR
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;
1da177e4
LT
977}
978
979static 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
1004static 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;
c9090ebb 1009 int rc,release_rc;
1da177e4
LT
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)
c9090ebb 1016 return -EINVAL;
1da177e4
LT
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
c9090ebb
WR
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);
1da177e4
LT
1028 if (rc)
1029 return rc;
c9090ebb
WR
1030 /* just continue. This should work for all fw versions
1031 * if bnum==1 && !brest && LoadBitmap was successful
1032 */
1da177e4 1033 }
c9090ebb
WR
1034
1035 rc = 0;
1036 for (i = 0; i < bnum; i++) {
1037 rc = LoadBitmap(av7110, w, lpb, inc, data);
1da177e4 1038 if (rc)
c9090ebb
WR
1039 break;
1040 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1da177e4 1041 if (rc)
c9090ebb
WR
1042 break;
1043 data += lpb * inc;
1da177e4 1044 }
c9090ebb
WR
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;
1da177e4
LT
1056}
1057
1058int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1059{
1060 int ret;
1061
3593cab5 1062 if (mutex_lock_interruptible(&av7110->osd_mutex))
1da177e4
LT
1063 return -ERESTARTSYS;
1064
1da177e4
LT
1065 switch (dc->cmd) {
1066 case OSD_Close:
c9090ebb
WR
1067 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1068 break;
1da177e4
LT
1069 case OSD_Open:
1070 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
c9090ebb 1071 ret = CreateOSDWindow(av7110, av7110->osdwin,
1da177e4
LT
1072 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1073 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
c9090ebb
WR
1074 if (ret)
1075 break;
1da177e4 1076 if (!dc->data) {
c9090ebb
WR
1077 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1078 if (ret)
1079 break;
1080 ret = SetColorBlend(av7110, av7110->osdwin);
1da177e4 1081 }
c9090ebb 1082 break;
1da177e4 1083 case OSD_Show:
c9090ebb
WR
1084 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1085 break;
1da177e4 1086 case OSD_Hide:
c9090ebb
WR
1087 ret = HideWindow(av7110, av7110->osdwin);
1088 break;
1da177e4 1089 case OSD_Clear:
c9090ebb
WR
1090 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1091 break;
1da177e4 1092 case OSD_Fill:
c9090ebb
WR
1093 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1094 break;
1da177e4 1095 case OSD_SetColor:
c9090ebb
WR
1096 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1097 break;
1da177e4 1098 case OSD_SetPalette:
c9090ebb 1099 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1da177e4 1100 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
c9090ebb 1101 else {
1da177e4
LT
1102 int i, len = dc->x0-dc->color+1;
1103 u8 __user *colors = (u8 __user *)dc->data;
1104 u8 r, g, b, blend;
c9090ebb 1105 ret = 0;
1da177e4
LT
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;
c9090ebb 1112 break;
1da177e4 1113 }
c9090ebb
WR
1114 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1115 if (ret)
1116 break;
1da177e4
LT
1117 }
1118 }
c9090ebb 1119 break;
1da177e4 1120 case OSD_SetPixel:
c9090ebb 1121 ret = DrawLine(av7110, av7110->osdwin,
1da177e4 1122 dc->x0, dc->y0, 0, 0, dc->color);
c9090ebb 1123 break;
1da177e4
LT
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);
c9090ebb 1129 break;
1da177e4 1130 case OSD_FillRow:
c9090ebb 1131 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1da177e4 1132 dc->x1-dc->x0+1, dc->y1, dc->color);
c9090ebb 1133 break;
1da177e4 1134 case OSD_FillBlock:
c9090ebb 1135 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1da177e4 1136 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
c9090ebb 1137 break;
1da177e4 1138 case OSD_Line:
c9090ebb 1139 ret = DrawLine(av7110, av7110->osdwin,
1da177e4 1140 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
c9090ebb 1141 break;
1da177e4
LT
1142 case OSD_Text:
1143 {
1144 char textbuf[240];
1145
1146 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1147 ret = -EFAULT;
c9090ebb 1148 break;
1da177e4
LT
1149 }
1150 textbuf[239] = 0;
1151 if (dc->x1 > 3)
1152 dc->x1 = 3;
c9090ebb 1153 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1da177e4 1154 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
c9090ebb
WR
1155 if (!ret)
1156 ret = FlushText(av7110);
1157 if (!ret)
1158 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1159 break;
1da177e4
LT
1160 }
1161 case OSD_SetWindow:
c9090ebb 1162 if (dc->x0 < 1 || dc->x0 > 7)
1da177e4 1163 ret = -EINVAL;
c9090ebb
WR
1164 else {
1165 av7110->osdwin = dc->x0;
1166 ret = 0;
1da177e4 1167 }
c9090ebb 1168 break;
1da177e4 1169 case OSD_MoveWindow:
c9090ebb
WR
1170 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1171 if (!ret)
1172 ret = SetColorBlend(av7110, av7110->osdwin);
1173 break;
1da177e4
LT
1174 case OSD_OpenRaw:
1175 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1176 ret = -EINVAL;
c9090ebb 1177 break;
1da177e4 1178 }
c9090ebb 1179 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1da177e4 1180 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
c9090ebb 1181 else
1da177e4 1182 av7110->osdbpp[av7110->osdwin] = 0;
c9090ebb 1183 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1da177e4 1184 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
c9090ebb
WR
1185 if (ret)
1186 break;
1da177e4 1187 if (!dc->data) {
c9090ebb
WR
1188 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1189 if (!ret)
1190 ret = SetColorBlend(av7110, av7110->osdwin);
1da177e4 1191 }
c9090ebb 1192 break;
1da177e4
LT
1193 default:
1194 ret = -EINVAL;
c9090ebb 1195 break;
1da177e4
LT
1196 }
1197
3593cab5 1198 mutex_unlock(&av7110->osd_mutex);
c9090ebb
WR
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
1da177e4
LT
1204 return ret;
1205}
1206
1207int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1208{
9101e622
MCC
1209 switch (cap->cmd) {
1210 case OSD_CAP_MEMSIZE:
1211 if (FW_4M_SDRAM(av7110->arm_app))
50c25fff 1212 cap->val = 1000000;
9101e622 1213 else
50c25fff 1214 cap->val = 92000;
9101e622
MCC
1215 return 0;
1216 default:
1217 return -EINVAL;
1218 }
1da177e4
LT
1219}
1220#endif /* CONFIG_DVB_AV7110_OSD */
This page took 0.286027 seconds and 5 git commands to generate.