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)
313 if (FW_VERSION(av7110->arm_app) <= 0x261c) {
314 /* not supported by old firmware */
322 err = time_after(jiffies, start + ARM_WAIT_FREE);
323 if (down_interruptible(&av7110->dcomlock))
325 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
326 up(&av7110->dcomlock);
327 if ((stat & flags) == 0)
330 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
331 __FUNCTION__, stat & flags);
339 static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
344 u16 flags[2] = {0, 0};
348 // dprintk(4, "%p\n", av7110);
350 if (!av7110->arm_ready) {
351 dprintk(1, "arm not ready.\n");
357 err = time_after(jiffies, start + ARM_WAIT_FREE);
358 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
361 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
367 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
372 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
373 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
376 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
383 switch ((buf[0] >> 8) & 0xff) {
384 case COMTYPE_PIDFILTER:
385 case COMTYPE_ENCODER:
386 case COMTYPE_REC_PLAY:
387 case COMTYPE_MPEGDECODER:
398 if (FW_VERSION(av7110->arm_app) >= 0x261d) {
409 /* non-immediate COMMAND type */
412 err = time_after(jiffies, start + ARM_WAIT_FREE);
413 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
414 if (stat & flags[0]) {
415 printk(KERN_ERR "%s: %s QUEUE overflow\n",
419 if ((stat & flags[1]) == 0)
422 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
430 for (i = 2; i < length; i++)
431 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
434 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
436 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
438 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
440 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
445 err = time_after(jiffies, start + ARM_WAIT_FREE);
446 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
449 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
450 __FUNCTION__, (buf[0] >> 8) & 0xff);
456 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
457 if (stat & GPMQOver) {
458 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
461 else if (stat & OSDQOver) {
462 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
470 static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
474 // dprintk(4, "%p\n", av7110);
476 if (!av7110->arm_ready) {
477 dprintk(1, "arm not ready.\n");
480 if (down_interruptible(&av7110->dcomlock))
483 ret = __av7110_send_fw_cmd(av7110, buf, length);
484 up(&av7110->dcomlock);
485 if (ret && ret!=-ERESTARTSYS)
486 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
491 int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
497 // dprintk(4, "%p\n", av7110);
499 buf[0] = ((type << 8) | com);
504 for (i = 0; i < num; i++)
505 buf[i + 2] = va_arg(args, u32);
509 ret = av7110_send_fw_cmd(av7110, buf, num + 2);
510 if (ret && ret != -ERESTARTSYS)
511 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
516 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
519 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
520 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
522 dprintk(4, "%p\n", av7110);
524 for(i = 0; i < len && i < 32; i++)
527 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
529 cmd[(i / 2) + 2] |= buf[i];
532 ret = av7110_send_fw_cmd(av7110, cmd, 18);
533 if (ret && ret != -ERESTARTSYS)
534 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
539 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
540 int request_buf_len, u16 *reply_buf, int reply_buf_len)
549 dprintk(4, "%p\n", av7110);
551 if (!av7110->arm_ready) {
552 dprintk(1, "arm not ready.\n");
556 if (down_interruptible(&av7110->dcomlock))
559 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
560 up(&av7110->dcomlock);
561 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
567 err = time_after(jiffies, start + ARM_WAIT_FREE);
568 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
571 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
572 up(&av7110->dcomlock);
583 err = time_after(jiffies, start + ARM_WAIT_SHAKE);
584 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
587 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
588 up(&av7110->dcomlock);
596 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
597 if (stat & GPMQOver) {
598 printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
599 up(&av7110->dcomlock);
602 else if (stat & OSDQOver) {
603 printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
604 up(&av7110->dcomlock);
609 for (i = 0; i < reply_buf_len; i++)
610 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
612 up(&av7110->dcomlock);
616 static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
619 ret = av7110_fw_request(av7110, &tag, 0, buf, length);
621 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
626 /****************************************************************************
628 ****************************************************************************/
630 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
631 int av7110_firmversion(struct av7110 *av7110)
634 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
636 dprintk(4, "%p\n", av7110);
638 if (av7110_fw_query(av7110, tag, buf, 16)) {
639 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
640 av7110->dvb_adapter.num);
644 av7110->arm_fw = (buf[0] << 16) + buf[1];
645 av7110->arm_rtsl = (buf[2] << 16) + buf[3];
646 av7110->arm_vid = (buf[4] << 16) + buf[5];
647 av7110->arm_app = (buf[6] << 16) + buf[7];
648 av7110->avtype = (buf[8] << 16) + buf[9];
650 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
651 av7110->dvb_adapter.num, av7110->arm_fw,
652 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
654 /* print firmware capabilities */
655 if (FW_CI_LL_SUPPORT(av7110->arm_app))
656 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
657 av7110->dvb_adapter.num);
659 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
660 av7110->dvb_adapter.num);
666 int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
669 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
670 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
672 dprintk(4, "%p\n", av7110);
681 buf[3] = burst ? 0x01 : 0x00;
685 for (i = 0; i < len; i++)
688 ret = av7110_send_fw_cmd(av7110, buf, 18);
689 if (ret && ret!=-ERESTARTSYS)
690 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
695 #ifdef CONFIG_DVB_AV7110_OSD
697 static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
699 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
702 static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
703 enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
705 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
706 windownr, colordepth, index, blending);
709 static inline int SetColor_(struct av7110 *av7110, u8 windownr,
710 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
712 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
713 windownr, colordepth, index, colorhi, colorlo);
716 static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
717 u16 colorfg, u16 colorbg)
719 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
720 windownr, fontsize, colorfg, colorbg);
723 static int FlushText(struct av7110 *av7110)
728 if (down_interruptible(&av7110->dcomlock))
732 err = time_after(jiffies, start + ARM_WAIT_OSD);
733 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
736 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
738 up(&av7110->dcomlock);
743 up(&av7110->dcomlock);
747 static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
751 int length = strlen(buf) + 1;
752 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
754 if (down_interruptible(&av7110->dcomlock))
759 ret = time_after(jiffies, start + ARM_WAIT_OSD);
760 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
763 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
765 up(&av7110->dcomlock);
773 ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
774 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
777 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
779 up(&av7110->dcomlock);
785 for (i = 0; i < length / 2; i++)
786 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
787 swab16(*(u16 *)(buf + 2 * i)), 2);
789 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
790 ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
791 up(&av7110->dcomlock);
792 if (ret && ret!=-ERESTARTSYS)
793 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
797 static inline int DrawLine(struct av7110 *av7110, u8 windownr,
798 u16 x, u16 y, u16 dx, u16 dy, u16 color)
800 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
801 windownr, x, y, dx, dy, color);
804 static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
805 u16 x, u16 y, u16 dx, u16 dy, u16 color)
807 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
808 windownr, x, y, dx, dy, color);
811 static inline int HideWindow(struct av7110 *av7110, u8 windownr)
813 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
816 static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
818 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
821 static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
823 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
826 static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
828 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
831 static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
832 osd_raw_window_t disptype,
833 u16 width, u16 height)
835 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
836 windownr, disptype, width, height);
840 static enum av7110_osd_palette_type bpp2pal[8] = {
841 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
843 static osd_raw_window_t bpp2bit[8] = {
844 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
847 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
849 int ret = wait_event_interruptible_timeout(av7110->bmpq,
850 av7110->bmp_state != BMP_LOADING, 10*HZ);
851 if (ret == -ERESTARTSYS)
854 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
855 ret, av7110->bmp_state);
856 av7110->bmp_state = BMP_NONE;
862 static inline int LoadBitmap(struct av7110 *av7110,
863 u16 dx, u16 dy, int inc, u8 __user * data)
872 dprintk(4, "%p\n", av7110);
874 format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
876 av7110->bmp_state = BMP_LOADING;
877 if (format == OSD_BITMAP8) {
879 } else if (format == OSD_BITMAP4) {
881 } else if (format == OSD_BITMAP2) {
883 } else if (format == OSD_BITMAP1) {
886 av7110->bmp_state = BMP_NONE;
889 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
891 if (av7110->bmplen > 32768) {
892 av7110->bmp_state = BMP_NONE;
895 for (i = 0; i < dy; i++) {
896 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
897 av7110->bmp_state = BMP_NONE;
901 if (format != OSD_BITMAP8) {
902 for (i = 0; i < dx * dy / delta; i++) {
903 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
904 for (d = delta - 2; d >= 0; d--) {
905 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
906 << ((delta - d - 1) * bpp));
907 ((u8 *)av7110->bmpbuf)[1024 + i] = c;
911 av7110->bmplen += 1024;
912 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
913 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
915 ret = WaitUntilBmpLoaded(av7110);
919 static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
921 dprintk(4, "%p\n", av7110);
923 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
926 static inline int ReleaseBitmap(struct av7110 *av7110)
928 dprintk(4, "%p\n", av7110);
930 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
932 if (av7110->bmp_state == BMP_LOADING)
933 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
934 av7110->bmp_state = BMP_NONE;
935 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
938 static u32 RGB2YUV(u16 R, u16 G, u16 B)
943 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
944 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
945 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
951 return Cr | (Cb << 16) | (Y << 8);
954 static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
961 yuv = blend ? RGB2YUV(r,g,b) : 0;
963 ch = ((yuv >> 16) & 0xffff);
964 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
967 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
968 color, ((blend >> 4) & 0x0f));
972 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
975 int length = last - first + 1;
977 if (length * 4 > DATA_BUFF3_SIZE)
980 for (i = 0; i < length; i++) {
981 u32 color, blend, yuv;
983 if (get_user(color, colors + i))
985 blend = (color & 0xF0000000) >> 4;
986 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
987 (color >> 16) & 0xFF) | blend : 0;
988 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
989 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
991 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
993 bpp2pal[av7110->osdbpp[av7110->osdwin]],
997 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
998 int x1, int y1, int inc, u8 __user * data)
1000 uint w, h, bpp, bpl, size, lpb, bnum, brest;
1008 if (w <= 0 || w > 720 || h <= 0 || h > 576)
1010 bpp = av7110->osdbpp[av7110->osdwin] + 1;
1011 bpl = ((w * bpp + 7) & ~7) / 8;
1013 lpb = (32 * 1024) / bpl;
1014 bnum = size / (lpb * bpl);
1015 brest = size - bnum * lpb * bpl;
1017 if (av7110->bmp_state == BMP_LOADING) {
1018 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1019 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
1020 rc = WaitUntilBmpLoaded(av7110);
1023 /* just continue. This should work for all fw versions
1024 * if bnum==1 && !brest && LoadBitmap was successful
1029 for (i = 0; i < bnum; i++) {
1030 rc = LoadBitmap(av7110, w, lpb, inc, data);
1033 rc = BlitBitmap(av7110, x0, y0 + i * lpb);
1039 rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
1041 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
1043 release_rc = ReleaseBitmap(av7110);
1047 dprintk(1,"returns %d\n",rc);
1051 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
1055 if (down_interruptible(&av7110->osd_sema))
1056 return -ERESTARTSYS;
1060 ret = DestroyOSDWindow(av7110, av7110->osdwin);
1063 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
1064 ret = CreateOSDWindow(av7110, av7110->osdwin,
1065 bpp2bit[av7110->osdbpp[av7110->osdwin]],
1066 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1070 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1073 ret = SetColorBlend(av7110, av7110->osdwin);
1077 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
1080 ret = HideWindow(av7110, av7110->osdwin);
1083 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
1086 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
1089 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
1091 case OSD_SetPalette:
1092 if (FW_VERSION(av7110->arm_app) >= 0x2618)
1093 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
1095 int i, len = dc->x0-dc->color+1;
1096 u8 __user *colors = (u8 __user *)dc->data;
1099 for (i = 0; i<len; i++) {
1100 if (get_user(r, colors + i * 4) ||
1101 get_user(g, colors + i * 4 + 1) ||
1102 get_user(b, colors + i * 4 + 2) ||
1103 get_user(blend, colors + i * 4 + 3)) {
1107 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
1114 ret = DrawLine(av7110, av7110->osdwin,
1115 dc->x0, dc->y0, 0, 0, dc->color);
1121 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
1124 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1125 dc->x1-dc->x0+1, dc->y1, dc->color);
1128 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
1129 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
1132 ret = DrawLine(av7110, av7110->osdwin,
1133 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
1139 if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
1146 ret = SetFont(av7110, av7110->osdwin, dc->x1,
1147 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
1149 ret = FlushText(av7110);
1151 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
1155 if (dc->x0 < 1 || dc->x0 > 7)
1158 av7110->osdwin = dc->x0;
1162 case OSD_MoveWindow:
1163 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1165 ret = SetColorBlend(av7110, av7110->osdwin);
1168 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
1172 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
1173 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
1175 av7110->osdbpp[av7110->osdwin] = 0;
1176 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
1177 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
1181 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
1183 ret = SetColorBlend(av7110, av7110->osdwin);
1191 up(&av7110->osd_sema);
1192 if (ret==-ERESTARTSYS)
1193 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
1195 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
1200 int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
1203 case OSD_CAP_MEMSIZE:
1204 if (FW_4M_SDRAM(av7110->arm_app))
1213 #endif /* CONFIG_DVB_AV7110_OSD */