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 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 (down_interruptible(&av7110->dcomlock))
329 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
330 up(&av7110->dcomlock);
331 if ((stat & flags) == 0)
334 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
335 __FUNCTION__, 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", __FUNCTION__);
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", __FUNCTION__);
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",
436 for (i = 2; i < length; i++)
437 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
440 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
442 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
444 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
446 if (FW_VERSION(av7110->arm_app) <= 0x261f)
447 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
452 err = time_after(jiffies, start + ARM_WAIT_FREE);
453 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
456 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
457 __FUNCTION__, (buf[0] >> 8) & 0xff);
463 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
464 if (stat & GPMQOver) {
465 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
468 else if (stat & OSDQOver) {
469 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
477 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
481 // dprintk(4, "%p\n", av7110);
483 if (!av7110->arm_ready) {
484 dprintk(1, "arm not ready.\n");
487 if (down_interruptible(&av7110->dcomlock))
490 ret = __av7110_send_fw_cmd(av7110, buf, length);
491 up(&av7110->dcomlock);
492 if (ret && ret!=-ERESTARTSYS)
493 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
498 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
504 // dprintk(4, "%p\n", av7110);
506 buf[0] = ((type << 8) | com);
511 for (i = 0; i < num; i++)
512 buf[i + 2] = va_arg(args, u32);
516 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
517 if (ret && ret != -ERESTARTSYS)
518 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
523 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
526 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
527 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
529 dprintk(4, "%p\n", av7110);
531 for(i = 0; i < len && i < 32; i++)
534 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
536 cmd[(i / 2) + 2] |= buf[i];
539 ret = av7110_send_fw_cmd(av7110, cmd, 18);
540 if (ret && ret != -ERESTARTSYS)
541 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
546 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
547 int request_buf_len, u16 *reply_buf, int reply_buf_len)
556 dprintk(4, "%p\n", av7110);
558 if (!av7110->arm_ready) {
559 dprintk(1, "arm not ready.\n");
563 if (down_interruptible(&av7110->dcomlock))
566 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
567 up(&av7110->dcomlock);
568 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
574 err = time_after(jiffies, start + ARM_WAIT_FREE);
575 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
578 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
579 up(&av7110->dcomlock);
590 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
591 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
594 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
595 up(&av7110->dcomlock);
603 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
604 if (stat & GPMQOver) {
605 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
606 up(&av7110->dcomlock);
609 else if (stat & OSDQOver) {
610 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
611 up(&av7110->dcomlock);
616 for (i = 0; i < reply_buf_len; i++)
617 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
619 up(&av7110->dcomlock);
623 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
626 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
628 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
633 /****************************************************************************
635 ****************************************************************************/
637 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
638 int av7110_firmversion(struct av7110 *av7110)
641 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
643 dprintk(4, "%p\n", av7110);
645 if (av7110_fw_query(av7110, tag, buf, 16)) {
646 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
647 av7110->dvb_adapter.num);
651 av7110->arm_fw = (buf[0] << 16) + buf[1];
652 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
653 av7110->arm_vid = (buf[4] << 16) + buf[5];
654 av7110->arm_app = (buf[6] << 16) + buf[7];
655 av7110->avtype = (buf[8] << 16) + buf[9];
657 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
658 av7110->dvb_adapter.num, av7110->arm_fw,
659 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
661 /* print firmware capabilities */
662 if (FW_CI_LL_SUPPORT(av7110->arm_app))
663 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
664 av7110->dvb_adapter.num);
666 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
667 av7110->dvb_adapter.num);
673 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
676 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
677 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
679 dprintk(4, "%p\n", av7110);
688 buf[3] = burst ? 0x01 : 0x00;
692 for (i = 0; i < len; i++)
695 ret = av7110_send_fw_cmd(av7110, buf, 18);
696 if (ret && ret!=-ERESTARTSYS)
697 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
702 #ifdef CONFIG_DVB_AV7110_OSD
704 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
706 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
709 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
710 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
712 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
713 windownr, colordepth, index, blending);
716 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
717 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
719 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
720 windownr, colordepth, index, colorhi, colorlo);
723 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
724 u16 colorfg, u16 colorbg)
726 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
727 windownr, fontsize, colorfg, colorbg);
730 static int FlushText(struct av7110 *av7110)
735 if (down_interruptible(&av7110->dcomlock))
739 err = time_after(jiffies, start + ARM_WAIT_OSD);
740 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
743 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
745 up(&av7110->dcomlock);
750 up(&av7110->dcomlock);
754 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
758 int length = strlen(buf) + 1;
759 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
761 if (down_interruptible(&av7110->dcomlock))
766 ret = time_after(jiffies, start + ARM_WAIT_OSD);
767 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
770 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
772 up(&av7110->dcomlock);
780 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
781 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
784 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
786 up(&av7110->dcomlock);
792 for (i = 0; i < length / 2; i++)
793 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
794 swab16(*(u16 *)(buf + 2 * i)), 2);
796 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
797 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
798 up(&av7110->dcomlock);
799 if (ret && ret!=-ERESTARTSYS)
800 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
804 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
805 u16 x, u16 y, u16 dx, u16 dy, u16 color)
807 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
808 windownr, x, y, dx, dy, color);
811 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
812 u16 x, u16 y, u16 dx, u16 dy, u16 color)
814 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
815 windownr, x, y, dx, dy, color);
818 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
820 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
823 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
825 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
828 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
830 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
833 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
835 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
838 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
839 osd_raw_window_t disptype,
840 u16 width, u16 height)
842 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
843 windownr, disptype, width, height);
847 static enum av7110_osd_palette_type bpp2pal[8] = {
848 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
850 static osd_raw_window_t bpp2bit[8] = {
851 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
854 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
856 int ret = wait_event_interruptible_timeout(av7110->bmpq,
857 av7110->bmp_state != BMP_LOADING, 10*HZ);
858 if (ret == -ERESTARTSYS)
861 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
862 ret, av7110->bmp_state);
863 av7110->bmp_state = BMP_NONE;
869 static inline int LoadBitmap(struct av7110 *av7110,
870 u16 dx, u16 dy, int inc, u8 __user * data)
879 dprintk(4, "%p\n", av7110);
881 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
883 av7110->bmp_state = BMP_LOADING;
884 if (format == OSD_BITMAP8) {
886 } else if (format == OSD_BITMAP4) {
888 } else if (format == OSD_BITMAP2) {
890 } else if (format == OSD_BITMAP1) {
893 av7110->bmp_state = BMP_NONE;
896 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
898 if (av7110->bmplen > 32768) {
899 av7110->bmp_state = BMP_NONE;
902 for (i = 0; i < dy; i++) {
903 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
904 av7110->bmp_state = BMP_NONE;
908 if (format != OSD_BITMAP8) {
909 for (i = 0; i < dx * dy / delta; i++) {
910 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
911 for (d = delta - 2; d >= 0; d--) {
912 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
913 << ((delta - d - 1) * bpp));
914 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
918 av7110->bmplen += 1024;
919 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
920 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
922 ret = WaitUntilBmpLoaded(av7110);
926 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
928 dprintk(4, "%p\n", av7110);
930 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
933 static inline int ReleaseBitmap(struct av7110 *av7110)
935 dprintk(4, "%p\n", av7110);
937 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
939 if (av7110->bmp_state == BMP_LOADING)
940 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
941 av7110->bmp_state = BMP_NONE;
942 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
945 static u32 RGB2YUV(u16 R, u16 G, u16 B)
950 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
951 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
952 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
958 return Cr | (Cb << 16) | (Y << 8);
961 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
968 yuv = blend ? RGB2YUV(r,g,b) : 0;
970 ch = ((yuv >> 16) & 0xffff);
971 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
974 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
975 color, ((blend >> 4) & 0x0f));
979 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
982 int length = last - first + 1;
984 if (length * 4 > DATA_BUFF3_SIZE)
987 for (i = 0; i < length; i++) {
988 u32 color, blend, yuv;
990 if (get_user(color, colors + i))
992 blend = (color & 0xF0000000) >> 4;
993 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
994 (color >> 16) & 0xFF) | blend : 0;
995 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
996 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
998 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
1000 bpp2pal[av7110->osdbpp[av7110->osdwin]],
1004 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
1005 int x1, int y1, int inc, u8 __user * data)
1007 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1015 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1017 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1018 bpl = ((w * bpp + 7) & ~7) / 8;
1020 lpb = (32 * 1024) / bpl;
1021 bnum = size / (lpb * bpl);
1022 brest = size - bnum * lpb * bpl;
1024 if (av7110->bmp_state == BMP_LOADING) {
1025 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1026 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1027 rc = WaitUntilBmpLoaded(av7110);
1030 /* just continue. This should work for all fw versions
1031 * if bnum==1 && !brest && LoadBitmap was successful
1036 for (i = 0; i < bnum; i++) {
1037 rc = LoadBitmap(av7110, w, lpb, inc, data);
1040 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1046 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1048 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1050 release_rc = ReleaseBitmap(av7110);
1054 dprintk(1,"returns %d\n",rc);
1058 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1062 if (down_interruptible(&av7110->osd_sema))
1063 return -ERESTARTSYS;
1067 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1070 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1071 ret = CreateOSDWindow(av7110, av7110->osdwin,
1072 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1073 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1077 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1080 ret = SetColorBlend(av7110, av7110->osdwin);
1084 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1087 ret = HideWindow(av7110, av7110->osdwin);
1090 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1093 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1096 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1098 case OSD_SetPalette:
1099 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1100 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1102 int i, len = dc->x0-dc->color+1;
1103 u8 __user *colors = (u8 __user *)dc->data;
1106 for (i = 0; i<len; i++) {
1107 if (get_user(r, colors + i * 4) ||
1108 get_user(g, colors + i * 4 + 1) ||
1109 get_user(b, colors + i * 4 + 2) ||
1110 get_user(blend, colors + i * 4 + 3)) {
1114 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1121 ret = DrawLine(av7110, av7110->osdwin,
1122 dc->x0, dc->y0, 0, 0, dc->color);
1128 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1131 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1132 dc->x1-dc->x0+1, dc->y1, dc->color);
1135 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1136 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1139 ret = DrawLine(av7110, av7110->osdwin,
1140 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1146 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1153 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1154 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1156 ret = FlushText(av7110);
1158 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1162 if (dc->x0 < 1 || dc->x0 > 7)
1165 av7110->osdwin = dc->x0;
1169 case OSD_MoveWindow:
1170 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1172 ret = SetColorBlend(av7110, av7110->osdwin);
1175 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1179 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1180 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1182 av7110->osdbpp[av7110->osdwin] = 0;
1183 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1184 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1188 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1190 ret = SetColorBlend(av7110, av7110->osdwin);
1198 up(&av7110->osd_sema);
1199 if (ret==-ERESTARTSYS)
1200 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1202 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1207 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1210 case OSD_CAP_MEMSIZE:
1211 if (FW_4M_SDRAM(av7110->arm_app))
1220 #endif /* CONFIG_DVB_AV7110_OSD */