2 * av7110_hw.c: av7110 low level hardware access and firmware interface
4 * Copyright (C) 1999-2002 Ralph Metzler
5 * & Marcus Metzler for convergence integrated media GmbH
7 * originally based on code by:
8 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
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.
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.
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
25 * the project's page is at http://www.linuxtv.org/dvb/
28 /* for debugging ARM communication: */
32 #include <linux/types.h>
33 #include <linux/kernel.h>
34 #include <linux/string.h>
35 #include <linux/delay.h>
36 #include <linux/smp_lock.h>
40 #include "av7110_hw.h"
44 /****************************************************************************
46 ****************************************************************************/
48 /* This DEBI code is based on the Stradis driver
49 by Nathan Laredo <laredo@gnu.org> */
51 int av7110_debiwrite(struct av7110 *av7110, u32 config,
52 int addr, u32 val, int count)
54 struct saa7146_dev *dev = av7110->dev;
56 if (count <= 0 || count > 32764) {
57 printk("%s: invalid count %d\n", __FUNCTION__, count);
60 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
61 printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
64 saa7146_write(dev, DEBI_CONFIG, config);
65 if (count <= 4) /* immediate transfer */
66 saa7146_write(dev, DEBI_AD, val);
67 else /* block transfer */
68 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
69 saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
70 saa7146_write(dev, MC2, (2 << 16) | 2);
74 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
76 struct saa7146_dev *dev = av7110->dev;
79 if (count > 32764 || count <= 0) {
80 printk("%s: invalid count %d\n", __FUNCTION__, count);
83 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
84 printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
87 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
88 saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
90 saa7146_write(dev, DEBI_CONFIG, config);
91 saa7146_write(dev, MC2, (2 << 16) | 2);
94 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
95 printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
99 result = saa7146_read(dev, DEBI_AD);
100 result &= (0xffffffffUL >> ((4 - count) * 8));
106 /* av7110 ARM core boot stuff */
108 void av7110_reset_arm(struct av7110 *av7110)
110 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
112 /* Disable DEBI and GPIO irq */
113 SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
114 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
116 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
117 msleep(30); /* the firmware needs some time to initialize */
119 ARM_ResetMailBox(av7110);
121 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
122 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
124 av7110->arm_ready = 1;
125 dprintk(1, "reset ARM\n");
129 static int waitdebi(struct av7110 *av7110, int adr, int state)
133 dprintk(4, "%p\n", av7110);
135 for (k = 0; k < 100; k++) {
136 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
143 static int load_dram(struct av7110 *av7110, u32 *data, int len)
147 u32 base, bootblock = AV7110_BOOT_BLOCK;
149 dprintk(4, "%p\n", av7110);
151 blocks = len / AV7110_BOOT_MAX_SIZE;
152 rest = len % AV7110_BOOT_MAX_SIZE;
153 base = DRAM_START_CODE;
155 for (i = 0; i < blocks; i++) {
156 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
157 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
160 dprintk(4, "writing DRAM block %d\n", i);
161 mwdebi(av7110, DEBISWAB, bootblock,
162 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
164 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
165 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
166 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
167 base += AV7110_BOOT_MAX_SIZE;
171 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
172 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
176 mwdebi(av7110, DEBISWAB, bootblock,
177 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
179 mwdebi(av7110, DEBISWAB, bootblock,
180 ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
182 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
183 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
184 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
186 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
187 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
190 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
191 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
192 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
193 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
200 /* we cannot write av7110 DRAM directly, so load a bootloader into
201 * the DPRAM which implements a simple boot protocol */
202 static u8 bootcode[] = {
203 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
204 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
205 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
206 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
207 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
208 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
209 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
210 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
211 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
212 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
213 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
214 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
215 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
216 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
217 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
218 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
219 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
220 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
223 int av7110_bootarm(struct av7110 *av7110)
225 struct saa7146_dev *dev = av7110->dev;
229 dprintk(4, "%p\n", av7110);
231 av7110->arm_ready = 0;
233 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
235 /* Disable DEBI and GPIO irq */
236 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
237 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
240 saa7146_write(av7110->dev, MC1, 0x08800880);
241 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
242 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
245 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
246 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
247 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
249 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
250 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
251 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
255 for (i = 0; i < 8192; i += 4)
256 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
257 dprintk(2, "debi test OK\n");
260 dprintk(1, "load boot code\n");
261 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
262 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
263 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
265 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
266 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
268 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
269 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
270 "saa7146_wait_for_debi_done() timed out\n");
273 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
276 dprintk(1, "load dram code\n");
277 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
278 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
279 "load_dram() failed\n");
283 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
286 dprintk(1, "load dpram code\n");
287 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
289 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
290 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
291 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
294 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
295 msleep(30); /* the firmware needs some time to initialize */
297 //ARM_ClearIrq(av7110);
298 ARM_ResetMailBox(av7110);
299 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
300 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
302 av7110->arm_errors = 0;
303 av7110->arm_ready = 1;
308 /****************************************************************************
309 * DEBI command polling
310 ****************************************************************************/
312 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
318 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
319 /* not supported by old firmware */
327 err = time_after(jiffies, start + ARM_WAIT_FREE);
328 if (mutex_lock_interruptible(&av7110->dcomlock))
330 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
331 mutex_unlock(&av7110->dcomlock);
332 if ((stat & flags) == 0)
335 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
336 __FUNCTION__, stat & flags);
344 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
349 u16 flags[2] = {0, 0};
353 // dprintk(4, "%p\n", av7110);
355 if (!av7110->arm_ready) {
356 dprintk(1, "arm not ready.\n");
362 err = time_after(jiffies, start + ARM_WAIT_FREE);
363 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
366 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
367 av7110->arm_errors++;
373 if (FW_VERSION(av7110->arm_app) <= 0x261f)
374 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
379 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
380 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
383 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
390 switch ((buf[0] >> 8) & 0xff) {
391 case COMTYPE_PIDFILTER:
392 case COMTYPE_ENCODER:
393 case COMTYPE_REC_PLAY:
394 case COMTYPE_MPEGDECODER:
405 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
416 /* non-immediate COMMAND type */
419 err = time_after(jiffies, start + ARM_WAIT_FREE);
420 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
421 if (stat & flags[0]) {
422 printk(KERN_ERR "%s: %s QUEUE overflow\n",
426 if ((stat & flags[1]) == 0)
429 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
437 for (i = 2; i < length; i++)
438 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
441 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
443 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
445 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
447 if (FW_VERSION(av7110->arm_app) <= 0x261f)
448 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
453 err = time_after(jiffies, start + ARM_WAIT_FREE);
454 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
457 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
458 __FUNCTION__, (buf[0] >> 8) & 0xff);
464 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
465 if (stat & GPMQOver) {
466 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
469 else if (stat & OSDQOver) {
470 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
478 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
482 // dprintk(4, "%p\n", av7110);
484 if (!av7110->arm_ready) {
485 dprintk(1, "arm not ready.\n");
488 if (mutex_lock_interruptible(&av7110->dcomlock))
491 ret = __av7110_send_fw_cmd(av7110, buf, length);
492 mutex_unlock(&av7110->dcomlock);
493 if (ret && ret!=-ERESTARTSYS)
494 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
499 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
505 // dprintk(4, "%p\n", av7110);
507 buf[0] = ((type << 8) | com);
512 for (i = 0; i < num; i++)
513 buf[i + 2] = va_arg(args, u32);
517 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
518 if (ret && ret != -ERESTARTSYS)
519 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
524 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
527 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
528 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
530 dprintk(4, "%p\n", av7110);
532 for(i = 0; i < len && i < 32; i++)
535 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
537 cmd[(i / 2) + 2] |= buf[i];
540 ret = av7110_send_fw_cmd(av7110, cmd, 18);
541 if (ret && ret != -ERESTARTSYS)
542 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
547 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
548 int request_buf_len, u16 *reply_buf, int reply_buf_len)
557 dprintk(4, "%p\n", av7110);
559 if (!av7110->arm_ready) {
560 dprintk(1, "arm not ready.\n");
564 if (mutex_lock_interruptible(&av7110->dcomlock))
567 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
568 mutex_unlock(&av7110->dcomlock);
569 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
575 err = time_after(jiffies, start + ARM_WAIT_FREE);
576 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
579 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
580 mutex_unlock(&av7110->dcomlock);
591 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
592 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
595 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
596 mutex_unlock(&av7110->dcomlock);
604 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
605 if (stat & GPMQOver) {
606 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
607 mutex_unlock(&av7110->dcomlock);
610 else if (stat & OSDQOver) {
611 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
612 mutex_unlock(&av7110->dcomlock);
617 for (i = 0; i < reply_buf_len; i++)
618 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
620 mutex_unlock(&av7110->dcomlock);
624 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
627 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
629 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
634 /****************************************************************************
636 ****************************************************************************/
638 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
639 int av7110_firmversion(struct av7110 *av7110)
642 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
644 dprintk(4, "%p\n", av7110);
646 if (av7110_fw_query(av7110, tag, buf, 16)) {
647 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
648 av7110->dvb_adapter.num);
652 av7110->arm_fw = (buf[0] << 16) + buf[1];
653 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
654 av7110->arm_vid = (buf[4] << 16) + buf[5];
655 av7110->arm_app = (buf[6] << 16) + buf[7];
656 av7110->avtype = (buf[8] << 16) + buf[9];
658 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
659 av7110->dvb_adapter.num, av7110->arm_fw,
660 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
662 /* print firmware capabilities */
663 if (FW_CI_LL_SUPPORT(av7110->arm_app))
664 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
665 av7110->dvb_adapter.num);
667 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
668 av7110->dvb_adapter.num);
674 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
677 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
678 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
680 dprintk(4, "%p\n", av7110);
689 buf[3] = burst ? 0x01 : 0x00;
693 for (i = 0; i < len; i++)
696 ret = av7110_send_fw_cmd(av7110, buf, 18);
697 if (ret && ret!=-ERESTARTSYS)
698 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
703 #ifdef CONFIG_DVB_AV7110_OSD
705 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
707 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
710 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
711 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
713 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
714 windownr, colordepth, index, blending);
717 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
718 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
720 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
721 windownr, colordepth, index, colorhi, colorlo);
724 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
725 u16 colorfg, u16 colorbg)
727 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
728 windownr, fontsize, colorfg, colorbg);
731 static int FlushText(struct av7110 *av7110)
736 if (mutex_lock_interruptible(&av7110->dcomlock))
740 err = time_after(jiffies, start + ARM_WAIT_OSD);
741 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
744 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
746 mutex_unlock(&av7110->dcomlock);
751 mutex_unlock(&av7110->dcomlock);
755 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
759 int length = strlen(buf) + 1;
760 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
762 if (mutex_lock_interruptible(&av7110->dcomlock))
767 ret = time_after(jiffies, start + ARM_WAIT_OSD);
768 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
771 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
773 mutex_unlock(&av7110->dcomlock);
781 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
782 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
785 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
787 mutex_unlock(&av7110->dcomlock);
793 for (i = 0; i < length / 2; i++)
794 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
795 swab16(*(u16 *)(buf + 2 * i)), 2);
797 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
798 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
799 mutex_unlock(&av7110->dcomlock);
800 if (ret && ret!=-ERESTARTSYS)
801 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
805 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
806 u16 x, u16 y, u16 dx, u16 dy, u16 color)
808 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
809 windownr, x, y, dx, dy, color);
812 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
813 u16 x, u16 y, u16 dx, u16 dy, u16 color)
815 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
816 windownr, x, y, dx, dy, color);
819 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
821 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
824 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
826 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
829 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
831 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
834 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
836 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
839 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
840 osd_raw_window_t disptype,
841 u16 width, u16 height)
843 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
844 windownr, disptype, width, height);
848 static enum av7110_osd_palette_type bpp2pal[8] = {
849 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
851 static osd_raw_window_t bpp2bit[8] = {
852 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
855 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
857 int ret = wait_event_interruptible_timeout(av7110->bmpq,
858 av7110->bmp_state != BMP_LOADING, 10*HZ);
859 if (ret == -ERESTARTSYS)
862 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
863 ret, av7110->bmp_state);
864 av7110->bmp_state = BMP_NONE;
870 static inline int LoadBitmap(struct av7110 *av7110,
871 u16 dx, u16 dy, int inc, u8 __user * data)
880 dprintk(4, "%p\n", av7110);
882 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
884 av7110->bmp_state = BMP_LOADING;
885 if (format == OSD_BITMAP8) {
887 } else if (format == OSD_BITMAP4) {
889 } else if (format == OSD_BITMAP2) {
891 } else if (format == OSD_BITMAP1) {
894 av7110->bmp_state = BMP_NONE;
897 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
899 if (av7110->bmplen > 32768) {
900 av7110->bmp_state = BMP_NONE;
903 for (i = 0; i < dy; i++) {
904 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
905 av7110->bmp_state = BMP_NONE;
909 if (format != OSD_BITMAP8) {
910 for (i = 0; i < dx * dy / delta; i++) {
911 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
912 for (d = delta - 2; d >= 0; d--) {
913 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
914 << ((delta - d - 1) * bpp));
915 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
919 av7110->bmplen += 1024;
920 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
921 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
923 ret = WaitUntilBmpLoaded(av7110);
927 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
929 dprintk(4, "%p\n", av7110);
931 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
934 static inline int ReleaseBitmap(struct av7110 *av7110)
936 dprintk(4, "%p\n", av7110);
938 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
940 if (av7110->bmp_state == BMP_LOADING)
941 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
942 av7110->bmp_state = BMP_NONE;
943 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
946 static u32 RGB2YUV(u16 R, u16 G, u16 B)
951 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
952 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
953 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
959 return Cr | (Cb << 16) | (Y << 8);
962 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
969 yuv = blend ? RGB2YUV(r,g,b) : 0;
971 ch = ((yuv >> 16) & 0xffff);
972 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
975 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
976 color, ((blend >> 4) & 0x0f));
980 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
983 int length = last - first + 1;
985 if (length * 4 > DATA_BUFF3_SIZE)
988 for (i = 0; i < length; i++) {
989 u32 color, blend, yuv;
991 if (get_user(color, colors + i))
993 blend = (color & 0xF0000000) >> 4;
994 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
995 (color >> 16) & 0xFF) | blend : 0;
996 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
997 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
999 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
1001 bpp2pal[av7110->osdbpp[av7110->osdwin]],
1005 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
1006 int x1, int y1, int inc, u8 __user * data)
1008 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1016 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1018 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1019 bpl = ((w * bpp + 7) & ~7) / 8;
1021 lpb = (32 * 1024) / bpl;
1022 bnum = size / (lpb * bpl);
1023 brest = size - bnum * lpb * bpl;
1025 if (av7110->bmp_state == BMP_LOADING) {
1026 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1027 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1028 rc = WaitUntilBmpLoaded(av7110);
1031 /* just continue. This should work for all fw versions
1032 * if bnum==1 && !brest && LoadBitmap was successful
1037 for (i = 0; i < bnum; i++) {
1038 rc = LoadBitmap(av7110, w, lpb, inc, data);
1041 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1047 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1049 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1051 release_rc = ReleaseBitmap(av7110);
1055 dprintk(1,"returns %d\n",rc);
1059 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1063 if (mutex_lock_interruptible(&av7110->osd_mutex))
1064 return -ERESTARTSYS;
1068 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1071 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1072 ret = CreateOSDWindow(av7110, av7110->osdwin,
1073 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1074 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1078 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1081 ret = SetColorBlend(av7110, av7110->osdwin);
1085 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1088 ret = HideWindow(av7110, av7110->osdwin);
1091 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1094 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1097 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1099 case OSD_SetPalette:
1100 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1101 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1103 int i, len = dc->x0-dc->color+1;
1104 u8 __user *colors = (u8 __user *)dc->data;
1107 for (i = 0; i<len; i++) {
1108 if (get_user(r, colors + i * 4) ||
1109 get_user(g, colors + i * 4 + 1) ||
1110 get_user(b, colors + i * 4 + 2) ||
1111 get_user(blend, colors + i * 4 + 3)) {
1115 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1122 ret = DrawLine(av7110, av7110->osdwin,
1123 dc->x0, dc->y0, 0, 0, dc->color);
1129 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1132 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1133 dc->x1-dc->x0+1, dc->y1, dc->color);
1136 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1137 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1140 ret = DrawLine(av7110, av7110->osdwin,
1141 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1147 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1154 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1155 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1157 ret = FlushText(av7110);
1159 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1163 if (dc->x0 < 1 || dc->x0 > 7)
1166 av7110->osdwin = dc->x0;
1170 case OSD_MoveWindow:
1171 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1173 ret = SetColorBlend(av7110, av7110->osdwin);
1176 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1180 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1181 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1183 av7110->osdbpp[av7110->osdwin] = 0;
1184 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1185 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1189 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1191 ret = SetColorBlend(av7110, av7110->osdwin);
1199 mutex_unlock(&av7110->osd_mutex);
1200 if (ret==-ERESTARTSYS)
1201 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1203 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1208 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1211 case OSD_CAP_MEMSIZE:
1212 if (FW_4M_SDRAM(av7110->arm_app))
1221 #endif /* CONFIG_DVB_AV7110_OSD */