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