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/byteorder/swabb.h>
38 #include <linux/smp_lock.h>
42 #include "av7110_hw.h"
46 /****************************************************************************
48 ****************************************************************************/
50 /* This DEBI code is based on the Stradis driver
51 by Nathan Laredo <laredo@gnu.org> */
53 int av7110_debiwrite(struct av7110 *av7110, u32 config,
54 int addr, u32 val, int count)
56 struct saa7146_dev *dev = av7110->dev;
58 if (count <= 0 || count > 32764) {
59 printk("%s: invalid count %d\n", __FUNCTION__, count);
62 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
63 printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
66 saa7146_write(dev, DEBI_CONFIG, config);
67 if (count <= 4) /* immediate transfer */
68 saa7146_write(dev, DEBI_AD, val);
69 else /* block transfer */
70 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
71 saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
72 saa7146_write(dev, MC2, (2 << 16) | 2);
76 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
78 struct saa7146_dev *dev = av7110->dev;
81 if (count > 32764 || count <= 0) {
82 printk("%s: invalid count %d\n", __FUNCTION__, count);
85 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
86 printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
89 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
90 saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
92 saa7146_write(dev, DEBI_CONFIG, config);
93 saa7146_write(dev, MC2, (2 << 16) | 2);
96 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
97 printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
101 result = saa7146_read(dev, DEBI_AD);
102 result &= (0xffffffffUL >> ((4 - count) * 8));
108 /* av7110 ARM core boot stuff */
110 void av7110_reset_arm(struct av7110 *av7110)
112 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
114 /* Disable DEBI and GPIO irq */
115 SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
116 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
118 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
119 msleep(30); /* the firmware needs some time to initialize */
121 ARM_ResetMailBox(av7110);
123 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
124 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
126 av7110->arm_ready = 1;
127 dprintk(1, "reset ARM\n");
131 static int waitdebi(struct av7110 *av7110, int adr, int state)
135 dprintk(4, "%p\n", av7110);
137 for (k = 0; k < 100; k++) {
138 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
145 static int load_dram(struct av7110 *av7110, u32 *data, int len)
149 u32 base, bootblock = AV7110_BOOT_BLOCK;
151 dprintk(4, "%p\n", av7110);
153 blocks = len / AV7110_BOOT_MAX_SIZE;
154 rest = len % AV7110_BOOT_MAX_SIZE;
155 base = DRAM_START_CODE;
157 for (i = 0; i < blocks; i++) {
158 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
159 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
162 dprintk(4, "writing DRAM block %d\n", i);
163 mwdebi(av7110, DEBISWAB, bootblock,
164 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
166 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
167 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
168 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
169 base += AV7110_BOOT_MAX_SIZE;
173 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
174 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
178 mwdebi(av7110, DEBISWAB, bootblock,
179 ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
181 mwdebi(av7110, DEBISWAB, bootblock,
182 ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
184 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
185 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
186 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
188 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
189 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
192 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
193 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
194 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
195 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
202 /* we cannot write av7110 DRAM directly, so load a bootloader into
203 * the DPRAM which implements a simple boot protocol */
204 static u8 bootcode[] = {
205 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
206 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
207 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
208 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
209 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
210 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
211 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
212 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
213 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
214 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
215 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
216 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
217 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
218 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
219 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
220 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
221 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
222 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
225 int av7110_bootarm(struct av7110 *av7110)
227 struct saa7146_dev *dev = av7110->dev;
231 dprintk(4, "%p\n", av7110);
233 av7110->arm_ready = 0;
235 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
237 /* Disable DEBI and GPIO irq */
238 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
239 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
242 saa7146_write(av7110->dev, MC1, 0x08800880);
243 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
244 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
247 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
248 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
249 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
251 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
252 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
253 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
257 for (i = 0; i < 8192; i += 4)
258 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
259 dprintk(2, "debi test OK\n");
262 dprintk(1, "load boot code\n");
263 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
264 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
265 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
267 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
268 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
270 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
271 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
272 "saa7146_wait_for_debi_done() timed out\n");
275 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
278 dprintk(1, "load dram code\n");
279 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
280 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
281 "load_dram() failed\n");
285 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
288 dprintk(1, "load dpram code\n");
289 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
291 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
292 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
293 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
296 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
297 msleep(30); /* the firmware needs some time to initialize */
299 //ARM_ClearIrq(av7110);
300 ARM_ResetMailBox(av7110);
301 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
302 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
304 av7110->arm_errors = 0;
305 av7110->arm_ready = 1;
310 /****************************************************************************
311 * DEBI command polling
312 ****************************************************************************/
314 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
320 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
321 /* not supported by old firmware */
329 err = time_after(jiffies, start + ARM_WAIT_FREE);
330 if (down_interruptible(&av7110->dcomlock))
332 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
333 up(&av7110->dcomlock);
334 if ((stat & flags) == 0)
337 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
338 __FUNCTION__, stat & flags);
346 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
351 u16 flags[2] = {0, 0};
355 // dprintk(4, "%p\n", av7110);
357 if (!av7110->arm_ready) {
358 dprintk(1, "arm not ready.\n");
364 err = time_after(jiffies, start + ARM_WAIT_FREE);
365 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
368 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
369 av7110->arm_errors++;
375 if (FW_VERSION(av7110->arm_app) <= 0x261f)
376 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
381 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
382 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
385 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
392 switch ((buf[0] >> 8) & 0xff) {
393 case COMTYPE_PIDFILTER:
394 case COMTYPE_ENCODER:
395 case COMTYPE_REC_PLAY:
396 case COMTYPE_MPEGDECODER:
407 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
418 /* non-immediate COMMAND type */
421 err = time_after(jiffies, start + ARM_WAIT_FREE);
422 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
423 if (stat & flags[0]) {
424 printk(KERN_ERR "%s: %s QUEUE overflow\n",
428 if ((stat & flags[1]) == 0)
431 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
439 for (i = 2; i < length; i++)
440 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
443 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
445 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
447 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
449 if (FW_VERSION(av7110->arm_app) <= 0x261f)
450 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
455 err = time_after(jiffies, start + ARM_WAIT_FREE);
456 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
459 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
460 __FUNCTION__, (buf[0] >> 8) & 0xff);
466 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
467 if (stat & GPMQOver) {
468 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
471 else if (stat & OSDQOver) {
472 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
480 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
484 // dprintk(4, "%p\n", av7110);
486 if (!av7110->arm_ready) {
487 dprintk(1, "arm not ready.\n");
490 if (down_interruptible(&av7110->dcomlock))
493 ret = __av7110_send_fw_cmd(av7110, buf, length);
494 up(&av7110->dcomlock);
495 if (ret && ret!=-ERESTARTSYS)
496 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
501 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
507 // dprintk(4, "%p\n", av7110);
509 buf[0] = ((type << 8) | com);
514 for (i = 0; i < num; i++)
515 buf[i + 2] = va_arg(args, u32);
519 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
520 if (ret && ret != -ERESTARTSYS)
521 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
526 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
529 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
530 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
532 dprintk(4, "%p\n", av7110);
534 for(i = 0; i < len && i < 32; i++)
537 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
539 cmd[(i / 2) + 2] |= buf[i];
542 ret = av7110_send_fw_cmd(av7110, cmd, 18);
543 if (ret && ret != -ERESTARTSYS)
544 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
549 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
550 int request_buf_len, u16 *reply_buf, int reply_buf_len)
559 dprintk(4, "%p\n", av7110);
561 if (!av7110->arm_ready) {
562 dprintk(1, "arm not ready.\n");
566 if (down_interruptible(&av7110->dcomlock))
569 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
570 up(&av7110->dcomlock);
571 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
577 err = time_after(jiffies, start + ARM_WAIT_FREE);
578 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
581 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
582 up(&av7110->dcomlock);
593 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
594 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
597 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
598 up(&av7110->dcomlock);
606 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
607 if (stat & GPMQOver) {
608 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
609 up(&av7110->dcomlock);
612 else if (stat & OSDQOver) {
613 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
614 up(&av7110->dcomlock);
619 for (i = 0; i < reply_buf_len; i++)
620 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
622 up(&av7110->dcomlock);
626 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
629 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
631 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
636 /****************************************************************************
638 ****************************************************************************/
640 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
641 int av7110_firmversion(struct av7110 *av7110)
644 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
646 dprintk(4, "%p\n", av7110);
648 if (av7110_fw_query(av7110, tag, buf, 16)) {
649 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
650 av7110->dvb_adapter.num);
654 av7110->arm_fw = (buf[0] << 16) + buf[1];
655 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
656 av7110->arm_vid = (buf[4] << 16) + buf[5];
657 av7110->arm_app = (buf[6] << 16) + buf[7];
658 av7110->avtype = (buf[8] << 16) + buf[9];
660 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
661 av7110->dvb_adapter.num, av7110->arm_fw,
662 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
664 /* print firmware capabilities */
665 if (FW_CI_LL_SUPPORT(av7110->arm_app))
666 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
667 av7110->dvb_adapter.num);
669 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
670 av7110->dvb_adapter.num);
676 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
679 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
680 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
682 dprintk(4, "%p\n", av7110);
691 buf[3] = burst ? 0x01 : 0x00;
695 for (i = 0; i < len; i++)
698 ret = av7110_send_fw_cmd(av7110, buf, 18);
699 if (ret && ret!=-ERESTARTSYS)
700 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
705 #ifdef CONFIG_DVB_AV7110_OSD
707 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
709 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
712 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
713 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
715 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
716 windownr, colordepth, index, blending);
719 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
720 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
722 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
723 windownr, colordepth, index, colorhi, colorlo);
726 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
727 u16 colorfg, u16 colorbg)
729 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
730 windownr, fontsize, colorfg, colorbg);
733 static int FlushText(struct av7110 *av7110)
738 if (down_interruptible(&av7110->dcomlock))
742 err = time_after(jiffies, start + ARM_WAIT_OSD);
743 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
746 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
748 up(&av7110->dcomlock);
753 up(&av7110->dcomlock);
757 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
761 int length = strlen(buf) + 1;
762 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
764 if (down_interruptible(&av7110->dcomlock))
769 ret = time_after(jiffies, start + ARM_WAIT_OSD);
770 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
773 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
775 up(&av7110->dcomlock);
783 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
784 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
787 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
789 up(&av7110->dcomlock);
795 for (i = 0; i < length / 2; i++)
796 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
797 swab16(*(u16 *)(buf + 2 * i)), 2);
799 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
800 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
801 up(&av7110->dcomlock);
802 if (ret && ret!=-ERESTARTSYS)
803 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
807 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
808 u16 x, u16 y, u16 dx, u16 dy, u16 color)
810 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
811 windownr, x, y, dx, dy, color);
814 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
815 u16 x, u16 y, u16 dx, u16 dy, u16 color)
817 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
818 windownr, x, y, dx, dy, color);
821 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
823 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
826 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
828 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
831 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
833 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
836 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
838 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
841 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
842 osd_raw_window_t disptype,
843 u16 width, u16 height)
845 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
846 windownr, disptype, width, height);
850 static enum av7110_osd_palette_type bpp2pal[8] = {
851 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
853 static osd_raw_window_t bpp2bit[8] = {
854 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
857 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
859 int ret = wait_event_interruptible_timeout(av7110->bmpq,
860 av7110->bmp_state != BMP_LOADING, 10*HZ);
861 if (ret == -ERESTARTSYS)
864 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
865 ret, av7110->bmp_state);
866 av7110->bmp_state = BMP_NONE;
872 static inline int LoadBitmap(struct av7110 *av7110,
873 u16 dx, u16 dy, int inc, u8 __user * data)
882 dprintk(4, "%p\n", av7110);
884 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
886 av7110->bmp_state = BMP_LOADING;
887 if (format == OSD_BITMAP8) {
889 } else if (format == OSD_BITMAP4) {
891 } else if (format == OSD_BITMAP2) {
893 } else if (format == OSD_BITMAP1) {
896 av7110->bmp_state = BMP_NONE;
899 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
901 if (av7110->bmplen > 32768) {
902 av7110->bmp_state = BMP_NONE;
905 for (i = 0; i < dy; i++) {
906 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
907 av7110->bmp_state = BMP_NONE;
911 if (format != OSD_BITMAP8) {
912 for (i = 0; i < dx * dy / delta; i++) {
913 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
914 for (d = delta - 2; d >= 0; d--) {
915 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
916 << ((delta - d - 1) * bpp));
917 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
921 av7110->bmplen += 1024;
922 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
923 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
925 ret = WaitUntilBmpLoaded(av7110);
929 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
931 dprintk(4, "%p\n", av7110);
933 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
936 static inline int ReleaseBitmap(struct av7110 *av7110)
938 dprintk(4, "%p\n", av7110);
940 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
942 if (av7110->bmp_state == BMP_LOADING)
943 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
944 av7110->bmp_state = BMP_NONE;
945 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
948 static u32 RGB2YUV(u16 R, u16 G, u16 B)
953 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
954 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
955 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
961 return Cr | (Cb << 16) | (Y << 8);
964 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
971 yuv = blend ? RGB2YUV(r,g,b) : 0;
973 ch = ((yuv >> 16) & 0xffff);
974 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
977 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
978 color, ((blend >> 4) & 0x0f));
982 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
985 int length = last - first + 1;
987 if (length * 4 > DATA_BUFF3_SIZE)
990 for (i = 0; i < length; i++) {
991 u32 color, blend, yuv;
993 if (get_user(color, colors + i))
995 blend = (color & 0xF0000000) >> 4;
996 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
997 (color >> 16) & 0xFF) | blend : 0;
998 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
999 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
1001 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
1003 bpp2pal[av7110->osdbpp[av7110->osdwin]],
1007 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
1008 int x1, int y1, int inc, u8 __user * data)
1010 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1018 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1020 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1021 bpl = ((w * bpp + 7) & ~7) / 8;
1023 lpb = (32 * 1024) / bpl;
1024 bnum = size / (lpb * bpl);
1025 brest = size - bnum * lpb * bpl;
1027 if (av7110->bmp_state == BMP_LOADING) {
1028 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1029 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1030 rc = WaitUntilBmpLoaded(av7110);
1033 /* just continue. This should work for all fw versions
1034 * if bnum==1 && !brest && LoadBitmap was successful
1039 for (i = 0; i < bnum; i++) {
1040 rc = LoadBitmap(av7110, w, lpb, inc, data);
1043 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1049 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1051 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1053 release_rc = ReleaseBitmap(av7110);
1057 dprintk(1,"returns %d\n",rc);
1061 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1065 if (down_interruptible(&av7110->osd_sema))
1066 return -ERESTARTSYS;
1070 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1073 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1074 ret = CreateOSDWindow(av7110, av7110->osdwin,
1075 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1076 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1080 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1083 ret = SetColorBlend(av7110, av7110->osdwin);
1087 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1090 ret = HideWindow(av7110, av7110->osdwin);
1093 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1096 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1099 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1101 case OSD_SetPalette:
1102 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1103 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1105 int i, len = dc->x0-dc->color+1;
1106 u8 __user *colors = (u8 __user *)dc->data;
1109 for (i = 0; i<len; i++) {
1110 if (get_user(r, colors + i * 4) ||
1111 get_user(g, colors + i * 4 + 1) ||
1112 get_user(b, colors + i * 4 + 2) ||
1113 get_user(blend, colors + i * 4 + 3)) {
1117 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1124 ret = DrawLine(av7110, av7110->osdwin,
1125 dc->x0, dc->y0, 0, 0, dc->color);
1131 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1134 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1135 dc->x1-dc->x0+1, dc->y1, dc->color);
1138 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1139 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1142 ret = DrawLine(av7110, av7110->osdwin,
1143 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1149 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1156 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1157 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1159 ret = FlushText(av7110);
1161 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1165 if (dc->x0 < 1 || dc->x0 > 7)
1168 av7110->osdwin = dc->x0;
1172 case OSD_MoveWindow:
1173 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1175 ret = SetColorBlend(av7110, av7110->osdwin);
1178 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1182 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1183 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1185 av7110->osdbpp[av7110->osdwin] = 0;
1186 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1187 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1191 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1193 ret = SetColorBlend(av7110, av7110->osdwin);
1201 up(&av7110->osd_sema);
1202 if (ret==-ERESTARTSYS)
1203 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1205 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1210 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1213 case OSD_CAP_MEMSIZE:
1214 if (FW_4M_SDRAM(av7110->arm_app))
1223 #endif /* CONFIG_DVB_AV7110_OSD */