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 = BOOT_BLOCK;
151 dprintk(4, "%p\n", av7110);
153 blocks = len / BOOT_MAX_SIZE;
154 rest = len % BOOT_MAX_SIZE;
155 base = DRAM_START_CODE;
157 for (i = 0; i < blocks; i++) {
158 if (waitdebi(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 * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
166 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
167 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2);
168 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
169 base += BOOT_MAX_SIZE;
173 if (waitdebi(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 * BOOT_MAX_SIZE, rest);
181 mwdebi(av7110, DEBISWAB, bootblock,
182 ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4);
184 iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
185 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
186 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
188 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
189 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
192 iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
193 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
194 if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_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 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
235 /* Disable DEBI and GPIO irq */
236 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
237 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
240 saa7146_write(av7110->dev, MC1, 0x08800880);
241 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
242 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
245 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
246 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
247 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
248 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
252 for (i = 0; i < 8192; i += 4)
253 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
254 dprintk(2, "debi test OK\n");
257 dprintk(1, "load boot code\n");
258 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
259 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
260 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
262 mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
263 iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
265 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
266 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
267 "saa7146_wait_for_debi_done() timed out\n");
270 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
273 dprintk(1, "load dram code\n");
274 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
275 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
276 "load_dram() failed\n");
280 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
283 dprintk(1, "load dpram code\n");
284 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
286 if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
287 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
288 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
291 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
292 msleep(30); /* the firmware needs some time to initialize */
294 //ARM_ClearIrq(av7110);
295 ARM_ResetMailBox(av7110);
296 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
297 SAA7146_IER_ENABLE(av7110->dev, MASK_03);
299 av7110->arm_errors = 0;
300 av7110->arm_ready = 1;
305 /****************************************************************************
306 * DEBI command polling
307 ****************************************************************************/
309 int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
315 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
316 /* not supported by old firmware */
324 err = time_after(jiffies, start + ARM_WAIT_FREE);
325 if (down_interruptible(&av7110->dcomlock))
327 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
328 up(&av7110->dcomlock);
329 if ((stat & flags) == 0)
332 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
333 __FUNCTION__, stat & flags);
341 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
346 u16 flags[2] = {0, 0};
350 // dprintk(4, "%p\n", av7110);
352 if (!av7110->arm_ready) {
353 dprintk(1, "arm not ready.\n");
359 err = time_after(jiffies, start + ARM_WAIT_FREE);
360 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
363 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
369 if (FW_VERSION(av7110->arm_app) <= 0x261f)
370 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
375 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
376 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
379 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
386 switch ((buf[0] >> 8) & 0xff) {
387 case COMTYPE_PIDFILTER:
388 case COMTYPE_ENCODER:
389 case COMTYPE_REC_PLAY:
390 case COMTYPE_MPEGDECODER:
401 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
412 /* non-immediate COMMAND type */
415 err = time_after(jiffies, start + ARM_WAIT_FREE);
416 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
417 if (stat & flags[0]) {
418 printk(KERN_ERR "%s: %s QUEUE overflow\n",
422 if ((stat & flags[1]) == 0)
425 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
433 for (i = 2; i < length; i++)
434 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
437 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
439 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
441 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
443 if (FW_VERSION(av7110->arm_app) <= 0x261f)
444 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
449 err = time_after(jiffies, start + ARM_WAIT_FREE);
450 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
453 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
454 __FUNCTION__, (buf[0] >> 8) & 0xff);
460 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
461 if (stat & GPMQOver) {
462 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
465 else if (stat & OSDQOver) {
466 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
474 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
478 // dprintk(4, "%p\n", av7110);
480 if (!av7110->arm_ready) {
481 dprintk(1, "arm not ready.\n");
484 if (down_interruptible(&av7110->dcomlock))
487 ret = __av7110_send_fw_cmd(av7110, buf, length);
488 up(&av7110->dcomlock);
489 if (ret && ret!=-ERESTARTSYS)
490 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
495 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
501 // dprintk(4, "%p\n", av7110);
503 buf[0] = ((type << 8) | com);
508 for (i = 0; i < num; i++)
509 buf[i + 2] = va_arg(args, u32);
513 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
514 if (ret && ret != -ERESTARTSYS)
515 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
520 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
523 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
524 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
526 dprintk(4, "%p\n", av7110);
528 for(i = 0; i < len && i < 32; i++)
531 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
533 cmd[(i / 2) + 2] |= buf[i];
536 ret = av7110_send_fw_cmd(av7110, cmd, 18);
537 if (ret && ret != -ERESTARTSYS)
538 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
543 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
544 int request_buf_len, u16 *reply_buf, int reply_buf_len)
553 dprintk(4, "%p\n", av7110);
555 if (!av7110->arm_ready) {
556 dprintk(1, "arm not ready.\n");
560 if (down_interruptible(&av7110->dcomlock))
563 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
564 up(&av7110->dcomlock);
565 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
571 err = time_after(jiffies, start + ARM_WAIT_FREE);
572 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
575 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
576 up(&av7110->dcomlock);
587 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
588 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
591 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
592 up(&av7110->dcomlock);
600 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
601 if (stat & GPMQOver) {
602 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
603 up(&av7110->dcomlock);
606 else if (stat & OSDQOver) {
607 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
608 up(&av7110->dcomlock);
613 for (i = 0; i < reply_buf_len; i++)
614 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
616 up(&av7110->dcomlock);
620 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
623 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
625 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
630 /****************************************************************************
632 ****************************************************************************/
634 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
635 int av7110_firmversion(struct av7110 *av7110)
638 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
640 dprintk(4, "%p\n", av7110);
642 if (av7110_fw_query(av7110, tag, buf, 16)) {
643 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
644 av7110->dvb_adapter.num);
648 av7110->arm_fw = (buf[0] << 16) + buf[1];
649 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
650 av7110->arm_vid = (buf[4] << 16) + buf[5];
651 av7110->arm_app = (buf[6] << 16) + buf[7];
652 av7110->avtype = (buf[8] << 16) + buf[9];
654 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
655 av7110->dvb_adapter.num, av7110->arm_fw,
656 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
658 /* print firmware capabilities */
659 if (FW_CI_LL_SUPPORT(av7110->arm_app))
660 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
661 av7110->dvb_adapter.num);
663 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
664 av7110->dvb_adapter.num);
670 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
673 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
674 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
676 dprintk(4, "%p\n", av7110);
685 buf[3] = burst ? 0x01 : 0x00;
689 for (i = 0; i < len; i++)
692 ret = av7110_send_fw_cmd(av7110, buf, 18);
693 if (ret && ret!=-ERESTARTSYS)
694 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
699 #ifdef CONFIG_DVB_AV7110_OSD
701 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
703 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
706 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
707 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
709 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
710 windownr, colordepth, index, blending);
713 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
714 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
716 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
717 windownr, colordepth, index, colorhi, colorlo);
720 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
721 u16 colorfg, u16 colorbg)
723 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
724 windownr, fontsize, colorfg, colorbg);
727 static int FlushText(struct av7110 *av7110)
732 if (down_interruptible(&av7110->dcomlock))
736 err = time_after(jiffies, start + ARM_WAIT_OSD);
737 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
740 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
742 up(&av7110->dcomlock);
747 up(&av7110->dcomlock);
751 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
755 int length = strlen(buf) + 1;
756 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
758 if (down_interruptible(&av7110->dcomlock))
763 ret = time_after(jiffies, start + ARM_WAIT_OSD);
764 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
767 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
769 up(&av7110->dcomlock);
777 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
778 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
781 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
783 up(&av7110->dcomlock);
789 for (i = 0; i < length / 2; i++)
790 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
791 swab16(*(u16 *)(buf + 2 * i)), 2);
793 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
794 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
795 up(&av7110->dcomlock);
796 if (ret && ret!=-ERESTARTSYS)
797 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
801 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
802 u16 x, u16 y, u16 dx, u16 dy, u16 color)
804 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
805 windownr, x, y, dx, dy, color);
808 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
809 u16 x, u16 y, u16 dx, u16 dy, u16 color)
811 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
812 windownr, x, y, dx, dy, color);
815 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
817 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
820 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
822 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
825 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
827 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
830 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
832 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
835 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
836 osd_raw_window_t disptype,
837 u16 width, u16 height)
839 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
840 windownr, disptype, width, height);
844 static enum av7110_osd_palette_type bpp2pal[8] = {
845 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
847 static osd_raw_window_t bpp2bit[8] = {
848 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
851 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
853 int ret = wait_event_interruptible_timeout(av7110->bmpq,
854 av7110->bmp_state != BMP_LOADING, 10*HZ);
855 if (ret == -ERESTARTSYS)
858 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
859 ret, av7110->bmp_state);
860 av7110->bmp_state = BMP_NONE;
866 static inline int LoadBitmap(struct av7110 *av7110,
867 u16 dx, u16 dy, int inc, u8 __user * data)
876 dprintk(4, "%p\n", av7110);
878 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
880 av7110->bmp_state = BMP_LOADING;
881 if (format == OSD_BITMAP8) {
883 } else if (format == OSD_BITMAP4) {
885 } else if (format == OSD_BITMAP2) {
887 } else if (format == OSD_BITMAP1) {
890 av7110->bmp_state = BMP_NONE;
893 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
895 if (av7110->bmplen > 32768) {
896 av7110->bmp_state = BMP_NONE;
899 for (i = 0; i < dy; i++) {
900 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
901 av7110->bmp_state = BMP_NONE;
905 if (format != OSD_BITMAP8) {
906 for (i = 0; i < dx * dy / delta; i++) {
907 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
908 for (d = delta - 2; d >= 0; d--) {
909 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
910 << ((delta - d - 1) * bpp));
911 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
915 av7110->bmplen += 1024;
916 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
917 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
919 ret = WaitUntilBmpLoaded(av7110);
923 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
925 dprintk(4, "%p\n", av7110);
927 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
930 static inline int ReleaseBitmap(struct av7110 *av7110)
932 dprintk(4, "%p\n", av7110);
934 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
936 if (av7110->bmp_state == BMP_LOADING)
937 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
938 av7110->bmp_state = BMP_NONE;
939 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
942 static u32 RGB2YUV(u16 R, u16 G, u16 B)
947 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
948 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
949 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
955 return Cr | (Cb << 16) | (Y << 8);
958 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
965 yuv = blend ? RGB2YUV(r,g,b) : 0;
967 ch = ((yuv >> 16) & 0xffff);
968 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
971 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
972 color, ((blend >> 4) & 0x0f));
976 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
979 int length = last - first + 1;
981 if (length * 4 > DATA_BUFF3_SIZE)
984 for (i = 0; i < length; i++) {
985 u32 color, blend, yuv;
987 if (get_user(color, colors + i))
989 blend = (color & 0xF0000000) >> 4;
990 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
991 (color >> 16) & 0xFF) | blend : 0;
992 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
993 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
995 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
997 bpp2pal[av7110->osdbpp[av7110->osdwin]],
1001 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
1002 int x1, int y1, int inc, u8 __user * data)
1004 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1012 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1014 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1015 bpl = ((w * bpp + 7) & ~7) / 8;
1017 lpb = (32 * 1024) / bpl;
1018 bnum = size / (lpb * bpl);
1019 brest = size - bnum * lpb * bpl;
1021 if (av7110->bmp_state == BMP_LOADING) {
1022 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1023 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1024 rc = WaitUntilBmpLoaded(av7110);
1027 /* just continue. This should work for all fw versions
1028 * if bnum==1 && !brest && LoadBitmap was successful
1033 for (i = 0; i < bnum; i++) {
1034 rc = LoadBitmap(av7110, w, lpb, inc, data);
1037 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1043 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1045 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1047 release_rc = ReleaseBitmap(av7110);
1051 dprintk(1,"returns %d\n",rc);
1055 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1059 if (down_interruptible(&av7110->osd_sema))
1060 return -ERESTARTSYS;
1064 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1067 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1068 ret = CreateOSDWindow(av7110, av7110->osdwin,
1069 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1070 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1074 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1077 ret = SetColorBlend(av7110, av7110->osdwin);
1081 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1084 ret = HideWindow(av7110, av7110->osdwin);
1087 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1090 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1093 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1095 case OSD_SetPalette:
1096 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1097 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1099 int i, len = dc->x0-dc->color+1;
1100 u8 __user *colors = (u8 __user *)dc->data;
1103 for (i = 0; i<len; i++) {
1104 if (get_user(r, colors + i * 4) ||
1105 get_user(g, colors + i * 4 + 1) ||
1106 get_user(b, colors + i * 4 + 2) ||
1107 get_user(blend, colors + i * 4 + 3)) {
1111 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1118 ret = DrawLine(av7110, av7110->osdwin,
1119 dc->x0, dc->y0, 0, 0, dc->color);
1125 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1128 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1129 dc->x1-dc->x0+1, dc->y1, dc->color);
1132 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1133 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1136 ret = DrawLine(av7110, av7110->osdwin,
1137 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1143 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1150 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1151 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1153 ret = FlushText(av7110);
1155 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1159 if (dc->x0 < 1 || dc->x0 > 7)
1162 av7110->osdwin = dc->x0;
1166 case OSD_MoveWindow:
1167 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1169 ret = SetColorBlend(av7110, av7110->osdwin);
1172 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1176 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1177 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1179 av7110->osdbpp[av7110->osdwin] = 0;
1180 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1181 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1185 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1187 ret = SetColorBlend(av7110, av7110->osdwin);
1195 up(&av7110->osd_sema);
1196 if (ret==-ERESTARTSYS)
1197 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1199 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1204 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1207 case OSD_CAP_MEMSIZE:
1208 if (FW_4M_SDRAM(av7110->arm_app))
1217 #endif /* CONFIG_DVB_AV7110_OSD */