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