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)
158 dprintk(4, "writing DRAM block %d\n", i);
159 mwdebi(av7110, DEBISWAB, bootblock,
160 ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
162 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
163 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2);
164 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
165 base += BOOT_MAX_SIZE;
169 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0)
172 mwdebi(av7110, DEBISWAB, bootblock,
173 ((char*)data) + i * BOOT_MAX_SIZE, rest);
175 mwdebi(av7110, DEBISWAB, bootblock,
176 ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4);
178 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
179 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
180 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
182 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0)
184 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
185 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
186 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0)
192 /* we cannot write av7110 DRAM directly, so load a bootloader into
193 * the DPRAM which implements a simple boot protocol */
194 static u8 bootcode[] = {
195 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04,
196 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04,
197 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24,
198 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34,
199 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55,
200 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74,
201 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04,
202 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64,
203 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02,
204 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0,
205 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d,
206 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f,
207 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0,
208 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0,
209 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01,
210 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec,
211 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00,
212 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0
215 int av7110_bootarm(struct av7110 *av7110)
217 struct saa7146_dev *dev = av7110->dev;
221 dprintk(4, "%p\n", av7110);
223 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
225 /* Disable DEBI and GPIO irq */
226 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
227 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
230 saa7146_write(av7110->dev, MC1, 0x08800880);
231 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
232 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
235 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
236 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
237 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
238 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
242 for (i = 0; i < 8192; i += 4)
243 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
244 dprintk(2, "debi test OK\n");
247 dprintk(1, "load boot code\n");
248 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
249 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
250 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
252 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
253 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
255 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
256 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
257 "saa7146_wait_for_debi_done() timed out\n");
260 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
263 dprintk(1, "load dram code\n");
264 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0)
267 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
270 dprintk(1, "load dpram code\n");
271 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
273 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
274 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
275 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
278 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
279 msleep(30); /* the firmware needs some time to initialize */
281 //ARM_ClearIrq(av7110);
282 ARM_ResetMailBox(av7110);
283 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
284 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
286 av7110->arm_errors = 0;
287 av7110->arm_ready = 1;
292 /****************************************************************************
293 * DEBI command polling
294 ****************************************************************************/
296 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
301 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
302 /* not supported by old firmware */
310 if (down_interruptible(&av7110->dcomlock))
312 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
313 up(&av7110->dcomlock);
314 if ((stat & flags) == 0) {
317 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
318 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
319 __FUNCTION__, stat & flags);
327 int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
332 u16 flags[2] = {0, 0};
335 // dprintk(4, "%p\n", av7110);
337 if (!av7110->arm_ready) {
338 dprintk(1, "arm not ready.\n");
343 while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
345 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
346 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
351 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
355 while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
357 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
358 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
364 switch ((buf[0] >> 8) & 0xff) {
365 case COMTYPE_PIDFILTER:
366 case COMTYPE_ENCODER:
367 case COMTYPE_REC_PLAY:
368 case COMTYPE_MPEGDECODER:
383 /* non-immediate COMMAND type */
386 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
387 if (stat & flags[0]) {
388 printk(KERN_ERR "%s: %s QUEUE overflow\n",
392 if ((stat & flags[1]) == 0)
394 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
395 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
403 for (i = 2; i < length; i++)
404 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
407 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
409 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
411 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
413 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
417 while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
419 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
420 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND to complete\n",
426 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
427 if (stat & GPMQOver) {
428 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
431 else if (stat & OSDQOver) {
432 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
440 int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
444 // dprintk(4, "%p\n", av7110);
446 if (!av7110->arm_ready) {
447 dprintk(1, "arm not ready.\n");
450 if (down_interruptible(&av7110->dcomlock))
453 ret = __av7110_send_fw_cmd(av7110, buf, length);
454 up(&av7110->dcomlock);
456 printk("dvb-ttpci: %s(): av7110_send_fw_cmd error\n", __FUNCTION__);
460 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
466 // dprintk(4, "%p\n", av7110);
468 buf[0] = ((type << 8) | com);
473 for (i = 0; i < num; i++)
474 buf[i + 2] = va_arg(args, u32);
478 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
480 printk("dvb-ttpci: av7110_fw_cmd error\n");
484 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
487 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
488 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
490 dprintk(4, "%p\n", av7110);
492 for(i = 0; i < len && i < 32; i++)
495 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
497 cmd[(i / 2) + 2] |= buf[i];
500 ret = av7110_send_fw_cmd(av7110, cmd, 18);
502 printk("dvb-ttpci: av7110_send_ci_cmd error\n");
506 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
507 int request_buf_len, u16 *reply_buf, int reply_buf_len)
516 dprintk(4, "%p\n", av7110);
518 if (!av7110->arm_ready) {
519 dprintk(1, "arm not ready.\n");
523 if (down_interruptible(&av7110->dcomlock))
526 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
527 up(&av7110->dcomlock);
528 printk("dvb-ttpci: av7110_fw_request error\n");
533 while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) {
537 if (time_after(jiffies, start + ARM_WAIT_FREE)) {
538 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
539 up(&av7110->dcomlock);
546 while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
548 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
549 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
550 up(&av7110->dcomlock);
557 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
558 if (stat & GPMQOver) {
559 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
560 up(&av7110->dcomlock);
563 else if (stat & OSDQOver) {
564 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
565 up(&av7110->dcomlock);
570 for (i = 0; i < reply_buf_len; i++)
571 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
573 up(&av7110->dcomlock);
577 int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
580 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
582 printk("dvb-ttpci: av7110_fw_query error\n");
587 /****************************************************************************
589 ****************************************************************************/
591 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
592 int av7110_firmversion(struct av7110 *av7110)
595 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
597 dprintk(4, "%p\n", av7110);
599 if (av7110_fw_query(av7110, tag, buf, 16)) {
600 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
601 av7110->dvb_adapter->num);
605 av7110->arm_fw = (buf[0] << 16) + buf[1];
606 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
607 av7110->arm_vid = (buf[4] << 16) + buf[5];
608 av7110->arm_app = (buf[6] << 16) + buf[7];
609 av7110->avtype = (buf[8] << 16) + buf[9];
611 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
612 av7110->dvb_adapter->num, av7110->arm_fw,
613 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
615 /* print firmware capabilities */
616 if (FW_CI_LL_SUPPORT(av7110->arm_app))
617 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
618 av7110->dvb_adapter->num);
620 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
621 av7110->dvb_adapter->num);
627 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
630 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
631 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
633 dprintk(4, "%p\n", av7110);
642 buf[3] = burst ? 0x01 : 0x00;
646 for (i = 0; i < len; i++)
649 if (av7110_send_fw_cmd(av7110, buf, 18))
650 printk("dvb-ttpci: av7110_diseqc_send error\n");
656 #ifdef CONFIG_DVB_AV7110_OSD
658 static inline int ResetBlend(struct av7110 *av7110, u8 windownr)
660 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetNonBlend, 1, windownr);
663 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
665 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
668 static inline int SetWindowBlend(struct av7110 *av7110, u8 windownr, u8 blending)
670 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetWBlend, 2, windownr, blending);
673 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
674 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
676 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
677 windownr, colordepth, index, blending);
680 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
681 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
683 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
684 windownr, colordepth, index, colorhi, colorlo);
687 static inline int BringToTop(struct av7110 *av7110, u8 windownr)
689 return av7110_fw_cmd(av7110, COMTYPE_OSD, WTop, 1, windownr);
692 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
693 u16 colorfg, u16 colorbg)
695 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
696 windownr, fontsize, colorfg, colorbg);
699 static int FlushText(struct av7110 *av7110)
703 if (down_interruptible(&av7110->dcomlock))
706 while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
708 if (time_after(jiffies, start + ARM_WAIT_OSD)) {
709 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
711 up(&av7110->dcomlock);
715 up(&av7110->dcomlock);
719 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
723 int length = strlen(buf) + 1;
724 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
726 if (down_interruptible(&av7110->dcomlock))
730 while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
732 if (time_after(jiffies, start + ARM_WAIT_OSD)) {
733 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
735 up(&av7110->dcomlock);
741 while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) {
743 if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
744 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
746 up(&av7110->dcomlock);
751 for (i = 0; i < length / 2; i++)
752 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
753 swab16(*(u16 *)(buf + 2 * i)), 2);
755 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
756 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
757 up(&av7110->dcomlock);
759 printk("dvb-ttpci: WriteText error\n");
763 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
764 u16 x, u16 y, u16 dx, u16 dy, u16 color)
766 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
767 windownr, x, y, dx, dy, color);
770 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
771 u16 x, u16 y, u16 dx, u16 dy, u16 color)
773 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
774 windownr, x, y, dx, dy, color);
777 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
779 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
782 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
784 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
787 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
789 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
792 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
794 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
797 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
798 osd_raw_window_t disptype,
799 u16 width, u16 height)
801 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
802 windownr, disptype, width, height);
806 static enum av7110_osd_palette_type bpp2pal[8] = {
807 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
809 static osd_raw_window_t bpp2bit[8] = {
810 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
813 static inline int LoadBitmap(struct av7110 *av7110, u16 format,
814 u16 dx, u16 dy, int inc, u8 __user * data)
822 dprintk(4, "%p\n", av7110);
824 ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ);
825 if (ret == -ERESTARTSYS || ret == 0) {
826 printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__);
827 av7110->bmp_state = BMP_NONE;
830 BUG_ON (av7110->bmp_state == BMP_LOADING);
832 av7110->bmp_state = BMP_LOADING;
833 if (format == OSD_BITMAP8) {
835 } else if (format == OSD_BITMAP4) {
837 } else if (format == OSD_BITMAP2) {
839 } else if (format == OSD_BITMAP1) {
842 av7110->bmp_state = BMP_NONE;
845 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
847 if (av7110->bmplen > 32768) {
848 av7110->bmp_state = BMP_NONE;
851 for (i = 0; i < dy; i++) {
852 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
853 av7110->bmp_state = BMP_NONE;
857 if (format != OSD_BITMAP8) {
858 for (i = 0; i < dx * dy / delta; i++) {
859 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
860 for (d = delta - 2; d >= 0; d--) {
861 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
862 << ((delta - d - 1) * bpp));
863 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
867 av7110->bmplen += 1024;
868 return av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
871 static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans)
875 dprintk(4, "%p\n", av7110);
877 BUG_ON (av7110->bmp_state == BMP_NONE);
879 ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ);
880 if (ret == -ERESTARTSYS || ret == 0) {
881 printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__);
882 av7110->bmp_state = BMP_NONE;
886 BUG_ON (av7110->bmp_state != BMP_LOADED);
888 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, win, x, y, trans);
891 static inline int ReleaseBitmap(struct av7110 *av7110)
893 dprintk(4, "%p\n", av7110);
895 if (av7110->bmp_state != BMP_LOADED)
897 av7110->bmp_state = BMP_NONE;
898 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
901 static u32 RGB2YUV(u16 R, u16 G, u16 B)
906 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
907 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
908 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
914 return Cr | (Cb << 16) | (Y << 8);
917 static void OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
922 yuv = blend ? RGB2YUV(r,g,b) : 0;
924 ch = ((yuv >> 16) & 0xffff);
925 SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
927 SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
928 color, ((blend >> 4) & 0x0f));
931 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
934 int length = last - first + 1;
936 if (length * 4 > DATA_BUFF3_SIZE)
939 for (i = 0; i < length; i++) {
940 u32 color, blend, yuv;
942 if (get_user(color, colors + i))
944 blend = (color & 0xF0000000) >> 4;
945 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
946 (color >> 16) & 0xFF) | blend : 0;
947 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
948 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
950 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
952 bpp2pal[av7110->osdbpp[av7110->osdwin]],
956 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
957 int x1, int y1, int inc, u8 __user *data)
959 uint w, h, bpp, bpl, size, lpb, bnum, brest;
966 if (w <= 0 || w > 720 || h <= 0 || h > 576)
968 bpp = av7110->osdbpp[av7110->osdwin] + 1;
969 bpl = ((w * bpp + 7) & ~7) / 8;
971 lpb = (32 * 1024) / bpl;
972 bnum = size / (lpb * bpl);
973 brest = size - bnum * lpb * bpl;
975 for (i = 0; i < bnum; i++) {
976 LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
978 BlitBitmap(av7110, av7110->osdwin, x0, y0 + i * lpb, 0);
982 LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
983 w, brest / bpl, inc, data);
984 BlitBitmap(av7110, av7110->osdwin, x0, y0 + bnum * lpb, 0);
986 ReleaseBitmap(av7110);
990 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
994 ret = down_interruptible(&av7110->osd_sema);
998 /* stupid, but OSD functions don't provide a return code anyway */
1003 DestroyOSDWindow(av7110, av7110->osdwin);
1006 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1007 CreateOSDWindow(av7110, av7110->osdwin,
1008 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1009 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1011 MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1012 SetColorBlend(av7110, av7110->osdwin);
1016 MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1019 HideWindow(av7110, av7110->osdwin);
1022 DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1025 DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1028 OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1030 case OSD_SetPalette:
1032 if (FW_VERSION(av7110->arm_app) >= 0x2618) {
1033 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1036 int i, len = dc->x0-dc->color+1;
1037 u8 __user *colors = (u8 *)dc->data;
1040 for (i = 0; i<len; i++) {
1041 if (get_user(r, colors + i * 4) ||
1042 get_user(g, colors + i * 4 + 1) ||
1043 get_user(b, colors + i * 4 + 2) ||
1044 get_user(blend, colors + i * 4 + 3)) {
1048 OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1057 DrawLine(av7110, av7110->osdwin,
1058 dc->x0, dc->y0, 0, 0, dc->color);
1066 OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1069 DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1070 dc->x1-dc->x0+1, dc->y1, dc->color);
1073 DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1074 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1077 DrawLine(av7110, av7110->osdwin,
1078 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1088 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1095 SetFont(av7110, av7110->osdwin, dc->x1,
1096 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1098 WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1102 if (dc->x0 < 1 || dc->x0 > 7) {
1106 av7110->osdwin = dc->x0;
1108 case OSD_MoveWindow:
1109 MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1110 SetColorBlend(av7110, av7110->osdwin);
1113 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1117 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR) {
1118 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1121 av7110->osdbpp[av7110->osdwin] = 0;
1123 CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1124 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1126 MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1127 SetColorBlend(av7110, av7110->osdwin);
1136 up(&av7110->osd_sema);
1140 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1143 case OSD_CAP_MEMSIZE:
1144 if (FW_4M_SDRAM(av7110->arm_app))
1153 #endif /* CONFIG_DVB_AV7110_OSD */