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/sched.h>
36 #include <linux/delay.h>
37 #include <linux/smp_lock.h>
41 #include "av7110_hw.h"
45 /****************************************************************************
47 ****************************************************************************/
49 /* This DEBI code is based on the Stradis driver
50 by Nathan Laredo <laredo@gnu.org> */
52 int av7110_debiwrite(struct av7110 *av7110, u32 config,
53 int addr, u32 val, int count)
55 struct saa7146_dev *dev = av7110->dev;
57 if (count <= 0 || count > 32764) {
58 printk("%s: invalid count %d\n", __FUNCTION__, count);
61 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
62 printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
65 saa7146_write(dev, DEBI_CONFIG, config);
66 if (count <= 4) /* immediate transfer */
67 saa7146_write(dev, DEBI_AD, val);
68 else /* block transfer */
69 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
70 saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
71 saa7146_write(dev, MC2, (2 << 16) | 2);
75 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
77 struct saa7146_dev *dev = av7110->dev;
80 if (count > 32764 || count <= 0) {
81 printk("%s: invalid count %d\n", __FUNCTION__, count);
84 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
85 printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
88 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
89 saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
91 saa7146_write(dev, DEBI_CONFIG, config);
92 saa7146_write(dev, MC2, (2 << 16) | 2);
95 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
96 printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
100 result = saa7146_read(dev, DEBI_AD);
101 result &= (0xffffffffUL >> ((4 - count) * 8));
107 /* av7110 ARM core boot stuff */
109 void av7110_reset_arm(struct av7110 *av7110)
111 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
113 /* Disable DEBI and GPIO irq */
114 SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
115 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
117 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
118 msleep(30); /* the firmware needs some time to initialize */
120 ARM_ResetMailBox(av7110);
122 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
123 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
125 av7110->arm_ready = 1;
126 dprintk(1, "reset ARM\n");
130 static int waitdebi(struct av7110 *av7110, int adr, int state)
134 dprintk(4, "%p\n", av7110);
136 for (k = 0; k < 100; k++) {
137 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
144 static int load_dram(struct av7110 *av7110, u32 *data, int len)
148 u32 base, bootblock = AV7110_BOOT_BLOCK;
150 dprintk(4, "%p\n", av7110);
152 blocks = len / AV7110_BOOT_MAX_SIZE;
153 rest = len % AV7110_BOOT_MAX_SIZE;
154 base = DRAM_START_CODE;
156 for (i = 0; i < blocks; i++) {
157 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
158 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
161 dprintk(4, "writing DRAM block %d\n", i);
162 mwdebi(av7110, DEBISWAB, bootblock,
163 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
165 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
166 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
167 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
168 base += AV7110_BOOT_MAX_SIZE;
172 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
173 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
177 mwdebi(av7110, DEBISWAB, bootblock,
178 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
180 mwdebi(av7110, DEBISWAB, bootblock,
181 ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
183 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
184 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
185 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
187 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
188 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
191 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
192 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
193 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
194 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
201 /* we cannot write av7110 DRAM directly, so load a bootloader into
202 * the DPRAM which implements a simple boot protocol */
203 static u8 bootcode[] = {
204 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
205 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
206 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
207 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
208 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
209 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
210 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
211 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
212 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
213 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
214 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
215 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
216 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
217 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
218 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
219 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
220 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
221 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
224 int av7110_bootarm(struct av7110 *av7110)
226 struct saa7146_dev *dev = av7110->dev;
230 dprintk(4, "%p\n", av7110);
232 av7110->arm_ready = 0;
234 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
236 /* Disable DEBI and GPIO irq */
237 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
238 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
241 saa7146_write(av7110->dev, MC1, 0x08800880);
242 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
243 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
246 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
247 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
248 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
250 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
251 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
252 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
256 for (i = 0; i < 8192; i += 4)
257 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
258 dprintk(2, "debi test OK\n");
261 dprintk(1, "load boot code\n");
262 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
263 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
264 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
266 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
267 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
269 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
270 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
271 "saa7146_wait_for_debi_done() timed out\n");
274 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
277 dprintk(1, "load dram code\n");
278 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
279 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
280 "load_dram() failed\n");
284 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
287 dprintk(1, "load dpram code\n");
288 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
290 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
291 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
292 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
295 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
296 msleep(30); /* the firmware needs some time to initialize */
298 //ARM_ClearIrq(av7110);
299 ARM_ResetMailBox(av7110);
300 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
301 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
303 av7110->arm_errors = 0;
304 av7110->arm_ready = 1;
309 /****************************************************************************
310 * DEBI command polling
311 ****************************************************************************/
313 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
319 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
320 /* not supported by old firmware */
328 err = time_after(jiffies, start + ARM_WAIT_FREE);
329 if (mutex_lock_interruptible(&av7110->dcomlock))
331 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
332 mutex_unlock(&av7110->dcomlock);
333 if ((stat & flags) == 0)
336 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
337 __FUNCTION__, stat & flags);
345 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
350 u16 flags[2] = {0, 0};
354 // dprintk(4, "%p\n", av7110);
356 if (!av7110->arm_ready) {
357 dprintk(1, "arm not ready.\n");
363 err = time_after(jiffies, start + ARM_WAIT_FREE);
364 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
367 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
368 av7110->arm_errors++;
374 if (FW_VERSION(av7110->arm_app) <= 0x261f)
375 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
380 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
381 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
384 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
391 switch ((buf[0] >> 8) & 0xff) {
392 case COMTYPE_PIDFILTER:
393 case COMTYPE_ENCODER:
394 case COMTYPE_REC_PLAY:
395 case COMTYPE_MPEGDECODER:
406 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
417 /* non-immediate COMMAND type */
420 err = time_after(jiffies, start + ARM_WAIT_FREE);
421 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
422 if (stat & flags[0]) {
423 printk(KERN_ERR "%s: %s QUEUE overflow\n",
427 if ((stat & flags[1]) == 0)
430 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
438 for (i = 2; i < length; i++)
439 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
442 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
444 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
446 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
448 if (FW_VERSION(av7110->arm_app) <= 0x261f)
449 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
454 err = time_after(jiffies, start + ARM_WAIT_FREE);
455 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
458 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
459 __FUNCTION__, (buf[0] >> 8) & 0xff);
465 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
466 if (stat & GPMQOver) {
467 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
470 else if (stat & OSDQOver) {
471 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
479 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
483 // dprintk(4, "%p\n", av7110);
485 if (!av7110->arm_ready) {
486 dprintk(1, "arm not ready.\n");
489 if (mutex_lock_interruptible(&av7110->dcomlock))
492 ret = __av7110_send_fw_cmd(av7110, buf, length);
493 mutex_unlock(&av7110->dcomlock);
494 if (ret && ret!=-ERESTARTSYS)
495 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
500 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
506 // dprintk(4, "%p\n", av7110);
508 buf[0] = ((type << 8) | com);
513 for (i = 0; i < num; i++)
514 buf[i + 2] = va_arg(args, u32);
518 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
519 if (ret && ret != -ERESTARTSYS)
520 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
525 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
528 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
529 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
531 dprintk(4, "%p\n", av7110);
533 for(i = 0; i < len && i < 32; i++)
536 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
538 cmd[(i / 2) + 2] |= buf[i];
541 ret = av7110_send_fw_cmd(av7110, cmd, 18);
542 if (ret && ret != -ERESTARTSYS)
543 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
548 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
549 int request_buf_len, u16 *reply_buf, int reply_buf_len)
558 dprintk(4, "%p\n", av7110);
560 if (!av7110->arm_ready) {
561 dprintk(1, "arm not ready.\n");
565 if (mutex_lock_interruptible(&av7110->dcomlock))
568 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
569 mutex_unlock(&av7110->dcomlock);
570 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
576 err = time_after(jiffies, start + ARM_WAIT_FREE);
577 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
580 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
581 mutex_unlock(&av7110->dcomlock);
592 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
593 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
596 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
597 mutex_unlock(&av7110->dcomlock);
605 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
606 if (stat & GPMQOver) {
607 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
608 mutex_unlock(&av7110->dcomlock);
611 else if (stat & OSDQOver) {
612 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
613 mutex_unlock(&av7110->dcomlock);
618 for (i = 0; i < reply_buf_len; i++)
619 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
621 mutex_unlock(&av7110->dcomlock);
625 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
628 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
630 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
635 /****************************************************************************
637 ****************************************************************************/
639 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
640 int av7110_firmversion(struct av7110 *av7110)
643 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
645 dprintk(4, "%p\n", av7110);
647 if (av7110_fw_query(av7110, tag, buf, 16)) {
648 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
649 av7110->dvb_adapter.num);
653 av7110->arm_fw = (buf[0] << 16) + buf[1];
654 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
655 av7110->arm_vid = (buf[4] << 16) + buf[5];
656 av7110->arm_app = (buf[6] << 16) + buf[7];
657 av7110->avtype = (buf[8] << 16) + buf[9];
659 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
660 av7110->dvb_adapter.num, av7110->arm_fw,
661 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
663 /* print firmware capabilities */
664 if (FW_CI_LL_SUPPORT(av7110->arm_app))
665 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
666 av7110->dvb_adapter.num);
668 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
669 av7110->dvb_adapter.num);
675 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
678 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
679 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
681 dprintk(4, "%p\n", av7110);
690 buf[3] = burst ? 0x01 : 0x00;
694 for (i = 0; i < len; i++)
697 ret = av7110_send_fw_cmd(av7110, buf, 18);
698 if (ret && ret!=-ERESTARTSYS)
699 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
704 #ifdef CONFIG_DVB_AV7110_OSD
706 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
708 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
711 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
712 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
714 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
715 windownr, colordepth, index, blending);
718 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
719 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
721 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
722 windownr, colordepth, index, colorhi, colorlo);
725 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
726 u16 colorfg, u16 colorbg)
728 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
729 windownr, fontsize, colorfg, colorbg);
732 static int FlushText(struct av7110 *av7110)
737 if (mutex_lock_interruptible(&av7110->dcomlock))
741 err = time_after(jiffies, start + ARM_WAIT_OSD);
742 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
745 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
747 mutex_unlock(&av7110->dcomlock);
752 mutex_unlock(&av7110->dcomlock);
756 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
760 int length = strlen(buf) + 1;
761 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
763 if (mutex_lock_interruptible(&av7110->dcomlock))
768 ret = time_after(jiffies, start + ARM_WAIT_OSD);
769 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
772 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
774 mutex_unlock(&av7110->dcomlock);
782 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
783 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
786 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
788 mutex_unlock(&av7110->dcomlock);
794 for (i = 0; i < length / 2; i++)
795 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
796 swab16(*(u16 *)(buf + 2 * i)), 2);
798 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
799 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
800 mutex_unlock(&av7110->dcomlock);
801 if (ret && ret!=-ERESTARTSYS)
802 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
806 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
807 u16 x, u16 y, u16 dx, u16 dy, u16 color)
809 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
810 windownr, x, y, dx, dy, color);
813 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
814 u16 x, u16 y, u16 dx, u16 dy, u16 color)
816 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
817 windownr, x, y, dx, dy, color);
820 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
822 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
825 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
827 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
830 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
832 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
835 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
837 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
840 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
841 osd_raw_window_t disptype,
842 u16 width, u16 height)
844 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
845 windownr, disptype, width, height);
849 static enum av7110_osd_palette_type bpp2pal[8] = {
850 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
852 static osd_raw_window_t bpp2bit[8] = {
853 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
856 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
858 int ret = wait_event_interruptible_timeout(av7110->bmpq,
859 av7110->bmp_state != BMP_LOADING, 10*HZ);
860 if (ret == -ERESTARTSYS)
863 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
864 ret, av7110->bmp_state);
865 av7110->bmp_state = BMP_NONE;
871 static inline int LoadBitmap(struct av7110 *av7110,
872 u16 dx, u16 dy, int inc, u8 __user * data)
881 dprintk(4, "%p\n", av7110);
883 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
885 av7110->bmp_state = BMP_LOADING;
886 if (format == OSD_BITMAP8) {
888 } else if (format == OSD_BITMAP4) {
890 } else if (format == OSD_BITMAP2) {
892 } else if (format == OSD_BITMAP1) {
895 av7110->bmp_state = BMP_NONE;
898 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
900 if (av7110->bmplen > 32768) {
901 av7110->bmp_state = BMP_NONE;
904 for (i = 0; i < dy; i++) {
905 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
906 av7110->bmp_state = BMP_NONE;
910 if (format != OSD_BITMAP8) {
911 for (i = 0; i < dx * dy / delta; i++) {
912 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
913 for (d = delta - 2; d >= 0; d--) {
914 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
915 << ((delta - d - 1) * bpp));
916 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
920 av7110->bmplen += 1024;
921 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
922 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
924 ret = WaitUntilBmpLoaded(av7110);
928 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
930 dprintk(4, "%p\n", av7110);
932 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
935 static inline int ReleaseBitmap(struct av7110 *av7110)
937 dprintk(4, "%p\n", av7110);
939 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
941 if (av7110->bmp_state == BMP_LOADING)
942 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
943 av7110->bmp_state = BMP_NONE;
944 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
947 static u32 RGB2YUV(u16 R, u16 G, u16 B)
952 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
953 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
954 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
960 return Cr | (Cb << 16) | (Y << 8);
963 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
970 yuv = blend ? RGB2YUV(r,g,b) : 0;
972 ch = ((yuv >> 16) & 0xffff);
973 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
976 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
977 color, ((blend >> 4) & 0x0f));
981 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
984 int length = last - first + 1;
986 if (length * 4 > DATA_BUFF3_SIZE)
989 for (i = 0; i < length; i++) {
990 u32 color, blend, yuv;
992 if (get_user(color, colors + i))
994 blend = (color & 0xF0000000) >> 4;
995 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
996 (color >> 16) & 0xFF) | blend : 0;
997 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
998 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
1000 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
1002 bpp2pal[av7110->osdbpp[av7110->osdwin]],
1006 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
1007 int x1, int y1, int inc, u8 __user * data)
1009 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1017 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1019 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1020 bpl = ((w * bpp + 7) & ~7) / 8;
1022 lpb = (32 * 1024) / bpl;
1023 bnum = size / (lpb * bpl);
1024 brest = size - bnum * lpb * bpl;
1026 if (av7110->bmp_state == BMP_LOADING) {
1027 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1028 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1029 rc = WaitUntilBmpLoaded(av7110);
1032 /* just continue. This should work for all fw versions
1033 * if bnum==1 && !brest && LoadBitmap was successful
1038 for (i = 0; i < bnum; i++) {
1039 rc = LoadBitmap(av7110, w, lpb, inc, data);
1042 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1048 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1050 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1052 release_rc = ReleaseBitmap(av7110);
1056 dprintk(1,"returns %d\n",rc);
1060 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1064 if (mutex_lock_interruptible(&av7110->osd_mutex))
1065 return -ERESTARTSYS;
1069 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1072 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1073 ret = CreateOSDWindow(av7110, av7110->osdwin,
1074 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1075 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1079 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1082 ret = SetColorBlend(av7110, av7110->osdwin);
1086 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1089 ret = HideWindow(av7110, av7110->osdwin);
1092 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1095 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1098 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1100 case OSD_SetPalette:
1101 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1102 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1104 int i, len = dc->x0-dc->color+1;
1105 u8 __user *colors = (u8 __user *)dc->data;
1108 for (i = 0; i<len; i++) {
1109 if (get_user(r, colors + i * 4) ||
1110 get_user(g, colors + i * 4 + 1) ||
1111 get_user(b, colors + i * 4 + 2) ||
1112 get_user(blend, colors + i * 4 + 3)) {
1116 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1123 ret = DrawLine(av7110, av7110->osdwin,
1124 dc->x0, dc->y0, 0, 0, dc->color);
1130 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1133 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1134 dc->x1-dc->x0+1, dc->y1, dc->color);
1137 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1138 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1141 ret = DrawLine(av7110, av7110->osdwin,
1142 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1148 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1155 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1156 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1158 ret = FlushText(av7110);
1160 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1164 if (dc->x0 < 1 || dc->x0 > 7)
1167 av7110->osdwin = dc->x0;
1171 case OSD_MoveWindow:
1172 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1174 ret = SetColorBlend(av7110, av7110->osdwin);
1177 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1181 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1182 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1184 av7110->osdbpp[av7110->osdwin] = 0;
1185 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1186 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1190 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1192 ret = SetColorBlend(av7110, av7110->osdwin);
1200 mutex_unlock(&av7110->osd_mutex);
1201 if (ret==-ERESTARTSYS)
1202 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1204 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1209 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1212 case OSD_CAP_MEMSIZE:
1213 if (FW_4M_SDRAM(av7110->arm_app))
1222 #endif /* CONFIG_DVB_AV7110_OSD */