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_timeout(av7110->bmpq,
858 av7110->bmp_state != BMP_LOADING, 10*HZ);
860 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
861 ret, av7110->bmp_state);
862 av7110->bmp_state = BMP_NONE;
868 static inline int LoadBitmap(struct av7110 *av7110,
869 u16 dx, u16 dy, int inc, u8 __user * data)
878 dprintk(4, "%p\n", av7110);
880 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
882 av7110->bmp_state = BMP_LOADING;
883 if (format == OSD_BITMAP8) {
885 } else if (format == OSD_BITMAP4) {
887 } else if (format == OSD_BITMAP2) {
889 } else if (format == OSD_BITMAP1) {
892 av7110->bmp_state = BMP_NONE;
895 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
897 if (av7110->bmplen > 32768) {
898 av7110->bmp_state = BMP_NONE;
901 for (i = 0; i < dy; i++) {
902 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
903 av7110->bmp_state = BMP_NONE;
907 if (format != OSD_BITMAP8) {
908 for (i = 0; i < dx * dy / delta; i++) {
909 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
910 for (d = delta - 2; d >= 0; d--) {
911 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
912 << ((delta - d - 1) * bpp));
913 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
917 av7110->bmplen += 1024;
918 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
919 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
921 ret = WaitUntilBmpLoaded(av7110);
925 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
927 dprintk(4, "%p\n", av7110);
929 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
932 static inline int ReleaseBitmap(struct av7110 *av7110)
934 dprintk(4, "%p\n", av7110);
936 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
938 if (av7110->bmp_state == BMP_LOADING)
939 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
940 av7110->bmp_state = BMP_NONE;
941 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
944 static u32 RGB2YUV(u16 R, u16 G, u16 B)
949 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
950 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
951 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
957 return Cr | (Cb << 16) | (Y << 8);
960 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
967 yuv = blend ? RGB2YUV(r,g,b) : 0;
969 ch = ((yuv >> 16) & 0xffff);
970 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
973 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
974 color, ((blend >> 4) & 0x0f));
978 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
981 int length = last - first + 1;
983 if (length * 4 > DATA_BUFF3_SIZE)
986 for (i = 0; i < length; i++) {
987 u32 color, blend, yuv;
989 if (get_user(color, colors + i))
991 blend = (color & 0xF0000000) >> 4;
992 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
993 (color >> 16) & 0xFF) | blend : 0;
994 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
995 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
997 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
999 bpp2pal[av7110->osdbpp[av7110->osdwin]],
1003 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
1004 int x1, int y1, int inc, u8 __user * data)
1006 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1014 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1016 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1017 bpl = ((w * bpp + 7) & ~7) / 8;
1019 lpb = (32 * 1024) / bpl;
1020 bnum = size / (lpb * bpl);
1021 brest = size - bnum * lpb * bpl;
1023 if (av7110->bmp_state == BMP_LOADING) {
1024 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1025 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1026 rc = WaitUntilBmpLoaded(av7110);
1029 /* just continue. This should work for all fw versions
1030 * if bnum==1 && !brest && LoadBitmap was successful
1035 for (i = 0; i < bnum; i++) {
1036 rc = LoadBitmap(av7110, w, lpb, inc, data);
1039 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1045 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1047 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1049 release_rc = ReleaseBitmap(av7110);
1053 dprintk(1,"returns %d\n",rc);
1057 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1061 if (mutex_lock_interruptible(&av7110->osd_mutex))
1062 return -ERESTARTSYS;
1066 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1069 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1070 ret = CreateOSDWindow(av7110, av7110->osdwin,
1071 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1072 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1076 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1079 ret = SetColorBlend(av7110, av7110->osdwin);
1083 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1086 ret = HideWindow(av7110, av7110->osdwin);
1089 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1092 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1095 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1097 case OSD_SetPalette:
1098 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1099 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1101 int i, len = dc->x0-dc->color+1;
1102 u8 __user *colors = (u8 __user *)dc->data;
1105 for (i = 0; i<len; i++) {
1106 if (get_user(r, colors + i * 4) ||
1107 get_user(g, colors + i * 4 + 1) ||
1108 get_user(b, colors + i * 4 + 2) ||
1109 get_user(blend, colors + i * 4 + 3)) {
1113 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1120 ret = DrawLine(av7110, av7110->osdwin,
1121 dc->x0, dc->y0, 0, 0, dc->color);
1127 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1130 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1131 dc->x1-dc->x0+1, dc->y1, dc->color);
1134 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1135 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1138 ret = DrawLine(av7110, av7110->osdwin,
1139 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1145 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1152 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1153 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1155 ret = FlushText(av7110);
1157 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1161 if (dc->x0 < 1 || dc->x0 > 7)
1164 av7110->osdwin = dc->x0;
1168 case OSD_MoveWindow:
1169 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1171 ret = SetColorBlend(av7110, av7110->osdwin);
1174 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1178 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1179 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1181 av7110->osdbpp[av7110->osdwin] = 0;
1182 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1183 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1187 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1189 ret = SetColorBlend(av7110, av7110->osdwin);
1197 mutex_unlock(&av7110->osd_mutex);
1198 if (ret==-ERESTARTSYS)
1199 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1201 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1206 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1209 case OSD_CAP_MEMSIZE:
1210 if (FW_4M_SDRAM(av7110->arm_app))
1219 #endif /* CONFIG_DVB_AV7110_OSD */