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"
44 /****************************************************************************
46 ****************************************************************************/
48 /* This DEBI code is based on the Stradis driver
49 by Nathan Laredo <laredo@gnu.org> */
51 int av7110_debiwrite(struct av7110 *av7110, u32 config,
52 int addr, u32 val, int count)
54 struct saa7146_dev *dev = av7110->dev;
56 if (count <= 0 || count > 32764) {
57 printk("%s: invalid count %d\n", __FUNCTION__, count);
60 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
61 printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
64 saa7146_write(dev, DEBI_CONFIG, config);
65 if (count <= 4) /* immediate transfer */
66 saa7146_write(dev, DEBI_AD, val);
67 else /* block transfer */
68 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
69 saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
70 saa7146_write(dev, MC2, (2 << 16) | 2);
74 u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
76 struct saa7146_dev *dev = av7110->dev;
79 if (count > 32764 || count <= 0) {
80 printk("%s: invalid count %d\n", __FUNCTION__, count);
83 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
84 printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
87 saa7146_write(dev, DEBI_AD, av7110->debi_bus);
88 saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
90 saa7146_write(dev, DEBI_CONFIG, config);
91 saa7146_write(dev, MC2, (2 << 16) | 2);
94 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
95 printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
99 result = saa7146_read(dev, DEBI_AD);
100 result &= (0xffffffffUL >> ((4 - count) * 8));
106 /* av7110 ARM core boot stuff */
108 void av7110_reset_arm(struct av7110 *av7110)
110 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
112 /* Disable DEBI and GPIO irq */
113 SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
114 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
116 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
117 msleep(30); /* the firmware needs some time to initialize */
119 ARM_ResetMailBox(av7110);
121 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
122 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
124 av7110->arm_ready = 1;
125 dprintk(1, "reset ARM\n");
129 static int waitdebi(struct av7110 *av7110, int adr, int state)
133 dprintk(4, "%p\n", av7110);
135 for (k = 0; k < 100; k++) {
136 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
143 static int load_dram(struct av7110 *av7110, u32 *data, int len)
147 u32 base, bootblock = BOOT_BLOCK;
149 dprintk(4, "%p\n", av7110);
151 blocks = len / BOOT_MAX_SIZE;
152 rest = len % BOOT_MAX_SIZE;
153 base = DRAM_START_CODE;
155 for (i = 0; i < blocks; i++) {
156 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
157 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
160 dprintk(4, "writing DRAM block %d\n", i);
161 mwdebi(av7110, DEBISWAB, bootblock,
162 ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
164 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
165 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2);
166 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
167 base += BOOT_MAX_SIZE;
171 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
172 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
176 mwdebi(av7110, DEBISWAB, bootblock,
177 ((char*)data) + i * BOOT_MAX_SIZE, rest);
179 mwdebi(av7110, DEBISWAB, bootblock,
180 ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4);
182 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
183 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
184 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
186 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
187 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
190 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
191 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
192 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) {
193 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
200 /* we cannot write av7110 DRAM directly, so load a bootloader into
201 * the DPRAM which implements a simple boot protocol */
202 static u8 bootcode[] = {
203 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
204 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
205 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
206 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
207 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
208 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
209 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
210 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
211 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
212 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
213 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
214 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
215 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
216 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
217 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
218 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
219 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
220 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
223 int av7110_bootarm(struct av7110 *av7110)
225 struct saa7146_dev *dev = av7110->dev;
229 dprintk(4, "%p\n", av7110);
231 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
233 /* Disable DEBI and GPIO irq */
234 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
235 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
238 saa7146_write(av7110->dev, MC1, 0x08800880);
239 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
240 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
243 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
244 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
245 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
246 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
250 for (i = 0; i < 8192; i += 4)
251 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
252 dprintk(2, "debi test OK\n");
255 dprintk(1, "load boot code\n");
256 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
257 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
258 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
260 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
261 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
263 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
264 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
265 "saa7146_wait_for_debi_done() timed out\n");
268 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
271 dprintk(1, "load dram code\n");
272 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
273 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
274 "load_dram() failed\n");
278 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
281 dprintk(1, "load dpram code\n");
282 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
284 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
285 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
286 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
289 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
290 msleep(30); /* the firmware needs some time to initialize */
292 //ARM_ClearIrq(av7110);
293 ARM_ResetMailBox(av7110);
294 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
295 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
297 av7110->arm_errors = 0;
298 av7110->arm_ready = 1;
303 /****************************************************************************
304 * DEBI command polling
305 ****************************************************************************/
307 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
312 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
313 /* not supported by old firmware */
321 if (down_interruptible(&av7110->dcomlock))
323 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
324 up(&av7110->dcomlock);
325 if ((stat & flags) == 0) {
328 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
329 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
330 __FUNCTION__, stat & flags);
338 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
343 u16 flags[2] = {0, 0};
346 // dprintk(4, "%p\n", av7110);
348 if (!av7110->arm_ready) {
349 dprintk(1, "arm not ready.\n");
354 while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
355 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
356 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
362 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
366 while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
367 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
368 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
375 switch ((buf[0] >> 8) & 0xff) {
376 case COMTYPE_PIDFILTER:
377 case COMTYPE_ENCODER:
378 case COMTYPE_REC_PLAY:
379 case COMTYPE_MPEGDECODER:
390 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
401 /* non-immediate COMMAND type */
404 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
405 if (stat & flags[0]) {
406 printk(KERN_ERR "%s: %s QUEUE overflow\n",
410 if ((stat & flags[1]) == 0)
412 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
413 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
421 for (i = 2; i < length; i++)
422 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
425 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
427 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
429 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
431 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
435 while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
436 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
437 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
446 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
447 if (stat & GPMQOver) {
448 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
451 else if (stat & OSDQOver) {
452 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
460 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
464 // dprintk(4, "%p\n", av7110);
466 if (!av7110->arm_ready) {
467 dprintk(1, "arm not ready.\n");
470 if (down_interruptible(&av7110->dcomlock))
473 ret = __av7110_send_fw_cmd(av7110, buf, length);
474 up(&av7110->dcomlock);
475 if (ret && ret!=-ERESTARTSYS)
476 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
481 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
487 // dprintk(4, "%p\n", av7110);
489 buf[0] = ((type << 8) | com);
494 for (i = 0; i < num; i++)
495 buf[i + 2] = va_arg(args, u32);
499 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
500 if (ret && ret != -ERESTARTSYS)
501 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
506 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
509 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
510 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
512 dprintk(4, "%p\n", av7110);
514 for(i = 0; i < len && i < 32; i++)
517 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
519 cmd[(i / 2) + 2] |= buf[i];
522 ret = av7110_send_fw_cmd(av7110, cmd, 18);
523 if (ret && ret != -ERESTARTSYS)
524 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
529 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
530 int request_buf_len, u16 *reply_buf, int reply_buf_len)
539 dprintk(4, "%p\n", av7110);
541 if (!av7110->arm_ready) {
542 dprintk(1, "arm not ready.\n");
546 if (down_interruptible(&av7110->dcomlock))
549 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
550 up(&av7110->dcomlock);
551 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
556 while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) {
557 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
558 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
559 up(&av7110->dcomlock);
569 while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
570 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
571 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
572 up(&av7110->dcomlock);
580 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
581 if (stat & GPMQOver) {
582 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
583 up(&av7110->dcomlock);
586 else if (stat & OSDQOver) {
587 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
588 up(&av7110->dcomlock);
593 for (i = 0; i < reply_buf_len; i++)
594 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
596 up(&av7110->dcomlock);
600 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
603 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
605 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
610 /****************************************************************************
612 ****************************************************************************/
614 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
615 int av7110_firmversion(struct av7110 *av7110)
618 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
620 dprintk(4, "%p\n", av7110);
622 if (av7110_fw_query(av7110, tag, buf, 16)) {
623 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
624 av7110->dvb_adapter.num);
628 av7110->arm_fw = (buf[0] << 16) + buf[1];
629 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
630 av7110->arm_vid = (buf[4] << 16) + buf[5];
631 av7110->arm_app = (buf[6] << 16) + buf[7];
632 av7110->avtype = (buf[8] << 16) + buf[9];
634 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
635 av7110->dvb_adapter.num, av7110->arm_fw,
636 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
638 /* print firmware capabilities */
639 if (FW_CI_LL_SUPPORT(av7110->arm_app))
640 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
641 av7110->dvb_adapter.num);
643 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
644 av7110->dvb_adapter.num);
650 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
653 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
654 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
656 dprintk(4, "%p\n", av7110);
665 buf[3] = burst ? 0x01 : 0x00;
669 for (i = 0; i < len; i++)
672 ret = av7110_send_fw_cmd(av7110, buf, 18);
673 if (ret && ret!=-ERESTARTSYS)
674 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
679 #ifdef CONFIG_DVB_AV7110_OSD
681 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
683 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
686 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
687 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
689 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
690 windownr, colordepth, index, blending);
693 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
694 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
696 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
697 windownr, colordepth, index, colorhi, colorlo);
700 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
701 u16 colorfg, u16 colorbg)
703 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
704 windownr, fontsize, colorfg, colorbg);
707 static int FlushText(struct av7110 *av7110)
711 if (down_interruptible(&av7110->dcomlock))
714 while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
715 if (time_after(jiffies, start + ARM_WAIT_OSD)) {
716 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
718 up(&av7110->dcomlock);
723 up(&av7110->dcomlock);
727 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
731 int length = strlen(buf) + 1;
732 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
734 if (down_interruptible(&av7110->dcomlock))
738 while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
739 if (time_after(jiffies, start + ARM_WAIT_OSD)) {
740 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
742 up(&av7110->dcomlock);
749 while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) {
750 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
751 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
753 up(&av7110->dcomlock);
759 for (i = 0; i < length / 2; i++)
760 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
761 swab16(*(u16 *)(buf + 2 * i)), 2);
763 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
764 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
765 up(&av7110->dcomlock);
766 if (ret && ret!=-ERESTARTSYS)
767 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
771 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
772 u16 x, u16 y, u16 dx, u16 dy, u16 color)
774 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
775 windownr, x, y, dx, dy, color);
778 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
779 u16 x, u16 y, u16 dx, u16 dy, u16 color)
781 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
782 windownr, x, y, dx, dy, color);
785 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
787 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
790 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
792 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
795 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
797 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
800 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
802 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
805 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
806 osd_raw_window_t disptype,
807 u16 width, u16 height)
809 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
810 windownr, disptype, width, height);
814 static enum av7110_osd_palette_type bpp2pal[8] = {
815 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
817 static osd_raw_window_t bpp2bit[8] = {
818 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
821 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
823 int ret = wait_event_interruptible_timeout(av7110->bmpq,
824 av7110->bmp_state != BMP_LOADING, 10*HZ);
825 if (ret == -ERESTARTSYS)
828 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
829 ret, av7110->bmp_state);
830 av7110->bmp_state = BMP_NONE;
836 static inline int LoadBitmap(struct av7110 *av7110,
837 u16 dx, u16 dy, int inc, u8 __user * data)
846 dprintk(4, "%p\n", av7110);
848 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
850 av7110->bmp_state = BMP_LOADING;
851 if (format == OSD_BITMAP8) {
853 } else if (format == OSD_BITMAP4) {
855 } else if (format == OSD_BITMAP2) {
857 } else if (format == OSD_BITMAP1) {
860 av7110->bmp_state = BMP_NONE;
863 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
865 if (av7110->bmplen > 32768) {
866 av7110->bmp_state = BMP_NONE;
869 for (i = 0; i < dy; i++) {
870 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
871 av7110->bmp_state = BMP_NONE;
875 if (format != OSD_BITMAP8) {
876 for (i = 0; i < dx * dy / delta; i++) {
877 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
878 for (d = delta - 2; d >= 0; d--) {
879 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
880 << ((delta - d - 1) * bpp));
881 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
885 av7110->bmplen += 1024;
886 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
887 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
889 ret = WaitUntilBmpLoaded(av7110);
893 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
895 dprintk(4, "%p\n", av7110);
897 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
900 static inline int ReleaseBitmap(struct av7110 *av7110)
902 dprintk(4, "%p\n", av7110);
904 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
906 if (av7110->bmp_state == BMP_LOADING)
907 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
908 av7110->bmp_state = BMP_NONE;
909 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
912 static u32 RGB2YUV(u16 R, u16 G, u16 B)
917 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
918 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
919 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
925 return Cr | (Cb << 16) | (Y << 8);
928 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
935 yuv = blend ? RGB2YUV(r,g,b) : 0;
937 ch = ((yuv >> 16) & 0xffff);
938 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
941 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
942 color, ((blend >> 4) & 0x0f));
946 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
949 int length = last - first + 1;
951 if (length * 4 > DATA_BUFF3_SIZE)
954 for (i = 0; i < length; i++) {
955 u32 color, blend, yuv;
957 if (get_user(color, colors + i))
959 blend = (color & 0xF0000000) >> 4;
960 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
961 (color >> 16) & 0xFF) | blend : 0;
962 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
963 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
965 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
967 bpp2pal[av7110->osdbpp[av7110->osdwin]],
971 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
972 int x1, int y1, int inc, u8 __user * data)
974 uint w, h, bpp, bpl, size, lpb, bnum, brest;
982 if (w <= 0 || w > 720 || h <= 0 || h > 576)
984 bpp = av7110->osdbpp[av7110->osdwin] + 1;
985 bpl = ((w * bpp + 7) & ~7) / 8;
987 lpb = (32 * 1024) / bpl;
988 bnum = size / (lpb * bpl);
989 brest = size - bnum * lpb * bpl;
991 if (av7110->bmp_state == BMP_LOADING) {
992 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
993 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
994 rc = WaitUntilBmpLoaded(av7110);
997 /* just continue. This should work for all fw versions
998 * if bnum==1 && !brest && LoadBitmap was successful
1003 for (i = 0; i < bnum; i++) {
1004 rc = LoadBitmap(av7110, w, lpb, inc, data);
1007 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1013 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1015 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1017 release_rc = ReleaseBitmap(av7110);
1021 dprintk(1,"returns %d\n",rc);
1025 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1029 if (down_interruptible(&av7110->osd_sema))
1030 return -ERESTARTSYS;
1034 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1037 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1038 ret = CreateOSDWindow(av7110, av7110->osdwin,
1039 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1040 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1044 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1047 ret = SetColorBlend(av7110, av7110->osdwin);
1051 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1054 ret = HideWindow(av7110, av7110->osdwin);
1057 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1060 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1063 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1065 case OSD_SetPalette:
1066 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1067 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1069 int i, len = dc->x0-dc->color+1;
1070 u8 __user *colors = (u8 __user *)dc->data;
1073 for (i = 0; i<len; i++) {
1074 if (get_user(r, colors + i * 4) ||
1075 get_user(g, colors + i * 4 + 1) ||
1076 get_user(b, colors + i * 4 + 2) ||
1077 get_user(blend, colors + i * 4 + 3)) {
1081 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1088 ret = DrawLine(av7110, av7110->osdwin,
1089 dc->x0, dc->y0, 0, 0, dc->color);
1095 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1098 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1099 dc->x1-dc->x0+1, dc->y1, dc->color);
1102 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1103 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1106 ret = DrawLine(av7110, av7110->osdwin,
1107 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1113 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1120 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1121 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1123 ret = FlushText(av7110);
1125 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1129 if (dc->x0 < 1 || dc->x0 > 7)
1132 av7110->osdwin = dc->x0;
1136 case OSD_MoveWindow:
1137 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1139 ret = SetColorBlend(av7110, av7110->osdwin);
1142 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1146 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1147 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1149 av7110->osdbpp[av7110->osdwin] = 0;
1150 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1151 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1155 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1157 ret = SetColorBlend(av7110, av7110->osdwin);
1165 up(&av7110->osd_sema);
1166 if (ret==-ERESTARTSYS)
1167 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1169 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1174 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1177 case OSD_CAP_MEMSIZE:
1178 if (FW_4M_SDRAM(av7110->arm_app))
1187 #endif /* CONFIG_DVB_AV7110_OSD */