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>
39 #include "av7110_hw.h"
43 /****************************************************************************
45 ****************************************************************************/
47 /* This DEBI code is based on the Stradis driver
48 by Nathan Laredo <laredo@gnu.org> */
50 int av7110_debiwrite(struct av7110 *av7110, u32 config,
51 int addr, u32 val, int count)
53 struct saa7146_dev *dev = av7110->dev;
55 if (count <= 0 || count > 32764) {
56 printk("%s: invalid count %d\n", __func__, count);
59 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
60 printk("%s: wait_for_debi_done failed\n", __func__);
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);
73 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
75 struct saa7146_dev *dev = av7110->dev;
78 if (count > 32764 || count <= 0) {
79 printk("%s: invalid count %d\n", __func__, count);
82 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
83 printk("%s: wait_for_debi_done #1 failed\n", __func__);
86 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
87 saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
89 saa7146_write(dev, DEBI_CONFIG, config);
90 saa7146_write(dev, MC2, (2 << 16) | 2);
93 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
94 printk("%s: wait_for_debi_done #2 failed\n", __func__);
98 result = saa7146_read(dev, DEBI_AD);
99 result &= (0xffffffffUL >> ((4 - count) * 8));
105 /* av7110 ARM core boot stuff */
107 void av7110_reset_arm(struct av7110 *av7110)
109 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
111 /* Disable DEBI and GPIO irq */
112 SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
113 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
115 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
116 msleep(30); /* the firmware needs some time to initialize */
118 ARM_ResetMailBox(av7110);
120 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
121 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
123 av7110->arm_ready = 1;
124 dprintk(1, "reset ARM\n");
128 static int waitdebi(struct av7110 *av7110, int adr, int state)
132 dprintk(4, "%p\n", av7110);
134 for (k = 0; k < 100; k++) {
135 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
142 static int load_dram(struct av7110 *av7110, u32 *data, int len)
146 u32 base, bootblock = AV7110_BOOT_BLOCK;
148 dprintk(4, "%p\n", av7110);
150 blocks = len / AV7110_BOOT_MAX_SIZE;
151 rest = len % AV7110_BOOT_MAX_SIZE;
152 base = DRAM_START_CODE;
154 for (i = 0; i < blocks; i++) {
155 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
156 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
159 dprintk(4, "writing DRAM block %d\n", i);
160 mwdebi(av7110, DEBISWAB, bootblock,
161 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
163 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
164 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
165 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
166 base += AV7110_BOOT_MAX_SIZE;
170 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
171 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
175 mwdebi(av7110, DEBISWAB, bootblock,
176 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, rest);
178 mwdebi(av7110, DEBISWAB, bootblock,
179 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
181 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
182 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
183 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
185 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
186 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
189 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
190 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
191 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
192 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
199 /* we cannot write av7110 DRAM directly, so load a bootloader into
200 * the DPRAM which implements a simple boot protocol */
201 static u8 bootcode[] = {
202 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
203 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
204 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
205 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
206 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
207 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
208 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
209 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
210 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
211 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
212 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
213 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
214 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
215 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
216 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
217 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
218 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
219 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
222 int av7110_bootarm(struct av7110 *av7110)
224 struct saa7146_dev *dev = av7110->dev;
228 dprintk(4, "%p\n", av7110);
230 av7110->arm_ready = 0;
232 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
234 /* Disable DEBI and GPIO irq */
235 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
236 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
239 saa7146_write(av7110->dev, MC1, 0x08800880);
240 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
241 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
244 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
245 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
246 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
248 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
249 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
250 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
254 for (i = 0; i < 8192; i += 4)
255 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
256 dprintk(2, "debi test OK\n");
259 dprintk(1, "load boot code\n");
260 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
261 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
262 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
264 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
265 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
267 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
268 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
269 "saa7146_wait_for_debi_done() timed out\n");
272 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
275 dprintk(1, "load dram code\n");
276 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
277 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
278 "load_dram() failed\n");
282 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
285 dprintk(1, "load dpram code\n");
286 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
288 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
289 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
290 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
293 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
294 msleep(30); /* the firmware needs some time to initialize */
296 //ARM_ClearIrq(av7110);
297 ARM_ResetMailBox(av7110);
298 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
299 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
301 av7110->arm_errors = 0;
302 av7110->arm_ready = 1;
307 /****************************************************************************
308 * DEBI command polling
309 ****************************************************************************/
311 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
317 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
318 /* not supported by old firmware */
326 err = time_after(jiffies, start + ARM_WAIT_FREE);
327 if (mutex_lock_interruptible(&av7110->dcomlock))
329 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
330 mutex_unlock(&av7110->dcomlock);
331 if ((stat & flags) == 0)
334 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
335 __func__, stat & flags);
343 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
348 u16 flags[2] = {0, 0};
352 // dprintk(4, "%p\n", av7110);
354 if (!av7110->arm_ready) {
355 dprintk(1, "arm not ready.\n");
361 err = time_after(jiffies, start + ARM_WAIT_FREE);
362 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
365 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
366 av7110->arm_errors++;
372 if (FW_VERSION(av7110->arm_app) <= 0x261f)
373 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
378 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
379 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
382 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
389 switch ((buf[0] >> 8) & 0xff) {
390 case COMTYPE_PIDFILTER:
391 case COMTYPE_ENCODER:
392 case COMTYPE_REC_PLAY:
393 case COMTYPE_MPEGDECODER:
404 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
415 /* non-immediate COMMAND type */
418 err = time_after(jiffies, start + ARM_WAIT_FREE);
419 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
420 if (stat & flags[0]) {
421 printk(KERN_ERR "%s: %s QUEUE overflow\n",
425 if ((stat & flags[1]) == 0)
428 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
430 av7110->arm_errors++;
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 __func__, (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", __func__);
469 else if (stat & OSDQOver) {
470 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
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", __func__);
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", __func__);
596 mutex_unlock(&av7110->dcomlock);
604 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
605 if (stat & GPMQOver) {
606 printk(KERN_ERR "%s: GPMQOver\n", __func__);
607 mutex_unlock(&av7110->dcomlock);
610 else if (stat & OSDQOver) {
611 printk(KERN_ERR "%s: OSDQOver\n", __func__);
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, char *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 */