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/
28 /* for debugging ARM communication: */
32 #include <linux/types.h>
33 #include <linux/kernel.h>
34 #include <linux/string.h>
35 #include <linux/delay.h>
39 #include "av7110_hw.h"
44 * Max transfer size done by av7110_fw_cmd()
46 * The maximum size passed to this function is 6 bytes. The buffer also
47 * uses two additional ones for type and size. So, 8 bytes is enough.
49 #define MAX_XFER_SIZE 8
51 /****************************************************************************
53 ****************************************************************************/
55 /* This DEBI code is based on the Stradis driver
56 by Nathan Laredo <laredo@gnu.org> */
58 int av7110_debiwrite(struct av7110
*av7110
, u32 config
,
59 int addr
, u32 val
, int count
)
61 struct saa7146_dev
*dev
= av7110
->dev
;
63 if (count
<= 0 || count
> 32764) {
64 printk("%s: invalid count %d\n", __func__
, count
);
67 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
68 printk("%s: wait_for_debi_done failed\n", __func__
);
71 saa7146_write(dev
, DEBI_CONFIG
, config
);
72 if (count
<= 4) /* immediate transfer */
73 saa7146_write(dev
, DEBI_AD
, val
);
74 else /* block transfer */
75 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
76 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | (addr
& 0xffff));
77 saa7146_write(dev
, MC2
, (2 << 16) | 2);
81 u32
av7110_debiread(struct av7110
*av7110
, u32 config
, int addr
, int count
)
83 struct saa7146_dev
*dev
= av7110
->dev
;
86 if (count
> 32764 || count
<= 0) {
87 printk("%s: invalid count %d\n", __func__
, count
);
90 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
91 printk("%s: wait_for_debi_done #1 failed\n", __func__
);
94 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
95 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | 0x10000 | (addr
& 0xffff));
97 saa7146_write(dev
, DEBI_CONFIG
, config
);
98 saa7146_write(dev
, MC2
, (2 << 16) | 2);
101 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
102 printk("%s: wait_for_debi_done #2 failed\n", __func__
);
106 result
= saa7146_read(dev
, DEBI_AD
);
107 result
&= (0xffffffffUL
>> ((4 - count
) * 8));
113 /* av7110 ARM core boot stuff */
115 void av7110_reset_arm(struct av7110
*av7110
)
117 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
119 /* Disable DEBI and GPIO irq */
120 SAA7146_IER_DISABLE(av7110
->dev
, MASK_19
| MASK_03
);
121 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
123 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
124 msleep(30); /* the firmware needs some time to initialize */
126 ARM_ResetMailBox(av7110
);
128 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
129 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
131 av7110
->arm_ready
= 1;
132 dprintk(1, "reset ARM\n");
136 static int waitdebi(struct av7110
*av7110
, int adr
, int state
)
140 dprintk(4, "%p\n", av7110
);
142 for (k
= 0; k
< 100; k
++) {
143 if (irdebi(av7110
, DEBINOSWAP
, adr
, 0, 2) == state
)
150 static int load_dram(struct av7110
*av7110
, u32
*data
, int len
)
154 u32 base
, bootblock
= AV7110_BOOT_BLOCK
;
156 dprintk(4, "%p\n", av7110
);
158 blocks
= len
/ AV7110_BOOT_MAX_SIZE
;
159 rest
= len
% AV7110_BOOT_MAX_SIZE
;
160 base
= DRAM_START_CODE
;
162 for (i
= 0; i
< blocks
; i
++) {
163 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
164 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at block %d\n", i
);
167 dprintk(4, "writing DRAM block %d\n", i
);
168 mwdebi(av7110
, DEBISWAB
, bootblock
,
169 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, AV7110_BOOT_MAX_SIZE
);
171 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
172 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, AV7110_BOOT_MAX_SIZE
, 2);
173 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
174 base
+= AV7110_BOOT_MAX_SIZE
;
178 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
179 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at last block\n");
183 mwdebi(av7110
, DEBISWAB
, bootblock
,
184 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, rest
);
186 mwdebi(av7110
, DEBISWAB
, bootblock
,
187 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
- 4, rest
+ 4);
189 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
190 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, rest
, 2);
191 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
193 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
194 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout after last block\n");
197 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, 0, 2);
198 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
199 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_AV7110_BOOT_COMPLETE
) < 0) {
200 printk(KERN_ERR
"dvb-ttpci: load_dram(): final handshake timeout\n");
207 /* we cannot write av7110 DRAM directly, so load a bootloader into
208 * the DPRAM which implements a simple boot protocol */
209 int av7110_bootarm(struct av7110
*av7110
)
211 const struct firmware
*fw
;
212 const char *fw_name
= "av7110/bootcode.bin";
213 struct saa7146_dev
*dev
= av7110
->dev
;
217 dprintk(4, "%p\n", av7110
);
219 av7110
->arm_ready
= 0;
221 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
223 /* Disable DEBI and GPIO irq */
224 SAA7146_IER_DISABLE(av7110
->dev
, MASK_03
| MASK_19
);
225 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
228 saa7146_write(av7110
->dev
, MC1
, 0x08800880);
229 saa7146_write(av7110
->dev
, DD1_STREAM_B
, 0x00000000);
230 saa7146_write(av7110
->dev
, MC2
, (MASK_09
| MASK_25
| MASK_10
| MASK_26
));
233 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
234 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
235 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
237 if ((ret
=irdebi(av7110
, DEBINOSWAP
, DPRAM_BASE
, 0, 4)) != 0x10325476) {
238 printk(KERN_ERR
"dvb-ttpci: debi test in av7110_bootarm() failed: "
239 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
243 for (i
= 0; i
< 8192; i
+= 4)
244 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
+ i
, 0x00, 4);
245 dprintk(2, "debi test OK\n");
248 dprintk(1, "load boot code\n");
249 saa7146_setgpio(dev
, ARM_IRQ_LINE
, SAA7146_GPIO_IRQLO
);
250 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
251 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
253 ret
= request_firmware(&fw
, fw_name
, &dev
->pci
->dev
);
255 printk(KERN_ERR
"dvb-ttpci: Failed to load firmware \"%s\"\n",
260 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, fw
->data
, fw
->size
);
261 release_firmware(fw
);
262 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
264 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
265 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
266 "saa7146_wait_for_debi_done() timed out\n");
269 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
272 dprintk(1, "load dram code\n");
273 if (load_dram(av7110
, (u32
*)av7110
->bin_root
, av7110
->size_root
) < 0) {
274 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
275 "load_dram() failed\n");
279 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
282 dprintk(1, "load dpram code\n");
283 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, av7110
->bin_dpram
, av7110
->size_dpram
);
285 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
286 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
287 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
290 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
291 msleep(30); /* the firmware needs some time to initialize */
293 //ARM_ClearIrq(av7110);
294 ARM_ResetMailBox(av7110
);
295 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
296 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
298 av7110
->arm_errors
= 0;
299 av7110
->arm_ready
= 1;
302 MODULE_FIRMWARE("av7110/bootcode.bin");
304 /****************************************************************************
305 * DEBI command polling
306 ****************************************************************************/
308 int av7110_wait_msgstate(struct av7110
*av7110
, u16 flags
)
314 if (FW_VERSION(av7110
->arm_app
) <= 0x261c) {
315 /* not supported by old firmware */
323 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
324 if (mutex_lock_interruptible(&av7110
->dcomlock
))
326 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
327 mutex_unlock(&av7110
->dcomlock
);
328 if ((stat
& flags
) == 0)
331 printk(KERN_ERR
"%s: timeout waiting for MSGSTATE %04x\n",
332 __func__
, stat
& flags
);
340 static int __av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
345 u16 flags
[2] = {0, 0};
349 // dprintk(4, "%p\n", av7110);
351 if (!av7110
->arm_ready
) {
352 dprintk(1, "arm not ready.\n");
358 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
359 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
362 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__
);
363 av7110
->arm_errors
++;
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", __func__
);
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",
427 av7110
->arm_errors
++;
434 for (i
= 2; i
< length
; i
++)
435 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2 * i
, (u32
) buf
[i
], 2);
438 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, (u32
) buf
[1], 2);
440 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, 0, 2);
442 wdebi(av7110
, DEBINOSWAP
, COMMAND
, (u32
) buf
[0], 2);
444 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
445 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0x0000, 2);
450 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
451 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
454 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
455 __func__
, (buf
[0] >> 8) & 0xff);
461 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
462 if (stat
& GPMQOver
) {
463 printk(KERN_ERR
"dvb-ttpci: %s(): GPMQOver\n", __func__
);
466 else if (stat
& OSDQOver
) {
467 printk(KERN_ERR
"dvb-ttpci: %s(): OSDQOver\n", __func__
);
475 static int av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
479 // dprintk(4, "%p\n", av7110);
481 if (!av7110
->arm_ready
) {
482 dprintk(1, "arm not ready.\n");
485 if (mutex_lock_interruptible(&av7110
->dcomlock
))
488 ret
= __av7110_send_fw_cmd(av7110
, buf
, length
);
489 mutex_unlock(&av7110
->dcomlock
);
490 if (ret
&& ret
!=-ERESTARTSYS
)
491 printk(KERN_ERR
"dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
496 int av7110_fw_cmd(struct av7110
*av7110
, int type
, int com
, int num
, ...)
499 u16 buf
[MAX_XFER_SIZE
];
502 // dprintk(4, "%p\n", av7110);
504 if (2 + num
> sizeof(buf
)) {
506 "%s: %s len=%d is too big!\n",
507 KBUILD_MODNAME
, __func__
, num
);
511 buf
[0] = ((type
<< 8) | com
);
516 for (i
= 0; i
< num
; i
++)
517 buf
[i
+ 2] = va_arg(args
, u32
);
521 ret
= av7110_send_fw_cmd(av7110
, buf
, num
+ 2);
522 if (ret
&& ret
!= -ERESTARTSYS
)
523 printk(KERN_ERR
"dvb-ttpci: av7110_fw_cmd error %d\n", ret
);
528 int av7110_send_ci_cmd(struct av7110
*av7110
, u8 subcom
, u8
*buf
, u8 len
)
531 u16 cmd
[18] = { ((COMTYPE_COMMON_IF
<< 8) + subcom
),
532 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
534 dprintk(4, "%p\n", av7110
);
536 for(i
= 0; i
< len
&& i
< 32; i
++)
539 cmd
[(i
/ 2) + 2] = (u16
)(buf
[i
]) << 8;
541 cmd
[(i
/ 2) + 2] |= buf
[i
];
544 ret
= av7110_send_fw_cmd(av7110
, cmd
, 18);
545 if (ret
&& ret
!= -ERESTARTSYS
)
546 printk(KERN_ERR
"dvb-ttpci: av7110_send_ci_cmd error %d\n", ret
);
551 int av7110_fw_request(struct av7110
*av7110
, u16
*request_buf
,
552 int request_buf_len
, u16
*reply_buf
, int reply_buf_len
)
561 dprintk(4, "%p\n", av7110
);
563 if (!av7110
->arm_ready
) {
564 dprintk(1, "arm not ready.\n");
568 if (mutex_lock_interruptible(&av7110
->dcomlock
))
571 if ((err
= __av7110_send_fw_cmd(av7110
, request_buf
, request_buf_len
)) < 0) {
572 mutex_unlock(&av7110
->dcomlock
);
573 printk(KERN_ERR
"dvb-ttpci: av7110_fw_request error %d\n", err
);
579 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
580 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
583 printk(KERN_ERR
"%s: timeout waiting for COMMAND to complete\n", __func__
);
584 mutex_unlock(&av7110
->dcomlock
);
595 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
596 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
599 printk(KERN_ERR
"%s: timeout waiting for HANDSHAKE_REG\n", __func__
);
600 mutex_unlock(&av7110
->dcomlock
);
608 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
609 if (stat
& GPMQOver
) {
610 printk(KERN_ERR
"%s: GPMQOver\n", __func__
);
611 mutex_unlock(&av7110
->dcomlock
);
614 else if (stat
& OSDQOver
) {
615 printk(KERN_ERR
"%s: OSDQOver\n", __func__
);
616 mutex_unlock(&av7110
->dcomlock
);
621 for (i
= 0; i
< reply_buf_len
; i
++)
622 reply_buf
[i
] = rdebi(av7110
, DEBINOSWAP
, COM_BUFF
+ 2 * i
, 0, 2);
624 mutex_unlock(&av7110
->dcomlock
);
628 static int av7110_fw_query(struct av7110
*av7110
, u16 tag
, u16
* buf
, s16 length
)
631 ret
= av7110_fw_request(av7110
, &tag
, 0, buf
, length
);
633 printk(KERN_ERR
"dvb-ttpci: av7110_fw_query error %d\n", ret
);
638 /****************************************************************************
640 ****************************************************************************/
642 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
643 int av7110_firmversion(struct av7110
*av7110
)
646 u16 tag
= ((COMTYPE_REQUEST
<< 8) + ReqVersion
);
648 dprintk(4, "%p\n", av7110
);
650 if (av7110_fw_query(av7110
, tag
, buf
, 16)) {
651 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
652 av7110
->dvb_adapter
.num
);
656 av7110
->arm_fw
= (buf
[0] << 16) + buf
[1];
657 av7110
->arm_rtsl
= (buf
[2] << 16) + buf
[3];
658 av7110
->arm_vid
= (buf
[4] << 16) + buf
[5];
659 av7110
->arm_app
= (buf
[6] << 16) + buf
[7];
660 av7110
->avtype
= (buf
[8] << 16) + buf
[9];
662 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
663 av7110
->dvb_adapter
.num
, av7110
->arm_fw
,
664 av7110
->arm_rtsl
, av7110
->arm_vid
, av7110
->arm_app
);
666 /* print firmware capabilities */
667 if (FW_CI_LL_SUPPORT(av7110
->arm_app
))
668 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
669 av7110
->dvb_adapter
.num
);
671 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
672 av7110
->dvb_adapter
.num
);
678 int av7110_diseqc_send(struct av7110
*av7110
, int len
, u8
*msg
, unsigned long burst
)
681 u16 buf
[18] = { ((COMTYPE_AUDIODAC
<< 8) + SendDiSEqC
),
682 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
684 dprintk(4, "%p\n", av7110
);
693 buf
[3] = burst
? 0x01 : 0x00;
697 for (i
= 0; i
< len
; i
++)
700 ret
= av7110_send_fw_cmd(av7110
, buf
, 18);
701 if (ret
&& ret
!=-ERESTARTSYS
)
702 printk(KERN_ERR
"dvb-ttpci: av7110_diseqc_send error %d\n", ret
);
707 #ifdef CONFIG_DVB_AV7110_OSD
709 static inline int SetColorBlend(struct av7110
*av7110
, u8 windownr
)
711 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetCBlend
, 1, windownr
);
714 static inline int SetBlend_(struct av7110
*av7110
, u8 windownr
,
715 enum av7110_osd_palette_type colordepth
, u16 index
, u8 blending
)
717 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetBlend
, 4,
718 windownr
, colordepth
, index
, blending
);
721 static inline int SetColor_(struct av7110
*av7110
, u8 windownr
,
722 enum av7110_osd_palette_type colordepth
, u16 index
, u16 colorhi
, u16 colorlo
)
724 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetColor
, 5,
725 windownr
, colordepth
, index
, colorhi
, colorlo
);
728 static inline int SetFont(struct av7110
*av7110
, u8 windownr
, u8 fontsize
,
729 u16 colorfg
, u16 colorbg
)
731 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Font
, 4,
732 windownr
, fontsize
, colorfg
, colorbg
);
735 static int FlushText(struct av7110
*av7110
)
740 if (mutex_lock_interruptible(&av7110
->dcomlock
))
744 err
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
745 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
748 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
750 mutex_unlock(&av7110
->dcomlock
);
755 mutex_unlock(&av7110
->dcomlock
);
759 static int WriteText(struct av7110
*av7110
, u8 win
, u16 x
, u16 y
, char *buf
)
763 int length
= strlen(buf
) + 1;
764 u16 cbuf
[5] = { (COMTYPE_OSD
<< 8) + DText
, 3, win
, x
, y
};
766 if (mutex_lock_interruptible(&av7110
->dcomlock
))
771 ret
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
772 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
775 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
777 mutex_unlock(&av7110
->dcomlock
);
785 ret
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
786 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
789 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
791 mutex_unlock(&av7110
->dcomlock
);
797 for (i
= 0; i
< length
/ 2; i
++)
798 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2,
799 swab16(*(u16
*)(buf
+ 2 * i
)), 2);
801 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2, 0, 2);
802 ret
= __av7110_send_fw_cmd(av7110
, cbuf
, 5);
803 mutex_unlock(&av7110
->dcomlock
);
804 if (ret
&& ret
!=-ERESTARTSYS
)
805 printk(KERN_ERR
"dvb-ttpci: WriteText error %d\n", ret
);
809 static inline int DrawLine(struct av7110
*av7110
, u8 windownr
,
810 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
812 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DLine
, 6,
813 windownr
, x
, y
, dx
, dy
, color
);
816 static inline int DrawBlock(struct av7110
*av7110
, u8 windownr
,
817 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
819 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DBox
, 6,
820 windownr
, x
, y
, dx
, dy
, color
);
823 static inline int HideWindow(struct av7110
*av7110
, u8 windownr
)
825 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WHide
, 1, windownr
);
828 static inline int MoveWindowRel(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
830 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveD
, 3, windownr
, x
, y
);
833 static inline int MoveWindowAbs(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
835 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveA
, 3, windownr
, x
, y
);
838 static inline int DestroyOSDWindow(struct av7110
*av7110
, u8 windownr
)
840 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WDestroy
, 1, windownr
);
843 static inline int CreateOSDWindow(struct av7110
*av7110
, u8 windownr
,
844 osd_raw_window_t disptype
,
845 u16 width
, u16 height
)
847 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WCreate
, 4,
848 windownr
, disptype
, width
, height
);
852 static enum av7110_osd_palette_type bpp2pal
[8] = {
853 Pal1Bit
, Pal2Bit
, 0, Pal4Bit
, 0, 0, 0, Pal8Bit
855 static osd_raw_window_t bpp2bit
[8] = {
856 OSD_BITMAP1
, OSD_BITMAP2
, 0, OSD_BITMAP4
, 0, 0, 0, OSD_BITMAP8
859 static inline int WaitUntilBmpLoaded(struct av7110
*av7110
)
861 int ret
= wait_event_timeout(av7110
->bmpq
,
862 av7110
->bmp_state
!= BMP_LOADING
, 10*HZ
);
864 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
865 ret
, av7110
->bmp_state
);
866 av7110
->bmp_state
= BMP_NONE
;
872 static inline int LoadBitmap(struct av7110
*av7110
,
873 u16 dx
, u16 dy
, int inc
, u8 __user
* data
)
882 dprintk(4, "%p\n", av7110
);
884 format
= bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]];
886 av7110
->bmp_state
= BMP_LOADING
;
887 if (format
== OSD_BITMAP8
) {
889 } else if (format
== OSD_BITMAP4
) {
891 } else if (format
== OSD_BITMAP2
) {
893 } else if (format
== OSD_BITMAP1
) {
896 av7110
->bmp_state
= BMP_NONE
;
899 av7110
->bmplen
= ((dx
* dy
* bpp
+ 7) & ~7) / 8;
901 if (av7110
->bmplen
> 32768) {
902 av7110
->bmp_state
= BMP_NONE
;
905 for (i
= 0; i
< dy
; i
++) {
906 if (copy_from_user(av7110
->bmpbuf
+ 1024 + i
* dx
, data
+ i
* inc
, dx
)) {
907 av7110
->bmp_state
= BMP_NONE
;
911 if (format
!= OSD_BITMAP8
) {
912 for (i
= 0; i
< dx
* dy
/ delta
; i
++) {
913 c
= ((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ delta
- 1];
914 for (d
= delta
- 2; d
>= 0; d
--) {
915 c
|= (((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ d
]
916 << ((delta
- d
- 1) * bpp
));
917 ((u8
*)av7110
->bmpbuf
)[1024 + i
] = c
;
921 av7110
->bmplen
+= 1024;
922 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110
->bmplen
);
923 ret
= av7110_fw_cmd(av7110
, COMTYPE_OSD
, LoadBmp
, 3, format
, dx
, dy
);
925 ret
= WaitUntilBmpLoaded(av7110
);
929 static int BlitBitmap(struct av7110
*av7110
, u16 x
, u16 y
)
931 dprintk(4, "%p\n", av7110
);
933 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, BlitBmp
, 4, av7110
->osdwin
, x
, y
, 0);
936 static inline int ReleaseBitmap(struct av7110
*av7110
)
938 dprintk(4, "%p\n", av7110
);
940 if (av7110
->bmp_state
!= BMP_LOADED
&& FW_VERSION(av7110
->arm_app
) < 0x261e)
942 if (av7110
->bmp_state
== BMP_LOADING
)
943 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
944 av7110
->bmp_state
= BMP_NONE
;
945 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, ReleaseBmp
, 0);
948 static u32
RGB2YUV(u16 R
, u16 G
, u16 B
)
953 y
= R
* 77 + G
* 150 + B
* 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
954 u
= 2048 + B
* 8 -(y
>> 5); /* Cr 0..4095 */
955 v
= 2048 + R
* 8 -(y
>> 5); /* Cb 0..4095 */
961 return Cr
| (Cb
<< 16) | (Y
<< 8);
964 static int OSDSetColor(struct av7110
*av7110
, u8 color
, u8 r
, u8 g
, u8 b
, u8 blend
)
971 yuv
= blend
? RGB2YUV(r
,g
,b
) : 0;
973 ch
= ((yuv
>> 16) & 0xffff);
974 ret
= SetColor_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
977 ret
= SetBlend_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
978 color
, ((blend
>> 4) & 0x0f));
982 static int OSDSetPalette(struct av7110
*av7110
, u32 __user
* colors
, u8 first
, u8 last
)
985 int length
= last
- first
+ 1;
987 if (length
* 4 > DATA_BUFF3_SIZE
)
990 for (i
= 0; i
< length
; i
++) {
991 u32 color
, blend
, yuv
;
993 if (get_user(color
, colors
+ i
))
995 blend
= (color
& 0xF0000000) >> 4;
996 yuv
= blend
? RGB2YUV(color
& 0xFF, (color
>> 8) & 0xFF,
997 (color
>> 16) & 0xFF) | blend
: 0;
998 yuv
= ((yuv
& 0xFFFF0000) >> 16) | ((yuv
& 0x0000FFFF) << 16);
999 wdebi(av7110
, DEBINOSWAP
, DATA_BUFF3_BASE
+ i
* 4, yuv
, 4);
1001 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Palette
, 4,
1003 bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
1007 static int OSDSetBlock(struct av7110
*av7110
, int x0
, int y0
,
1008 int x1
, int y1
, int inc
, u8 __user
* data
)
1010 uint w
, h
, bpp
, bpl
, size
, lpb
, bnum
, brest
;
1018 if (w
<= 0 || w
> 720 || h
<= 0 || h
> 576)
1020 bpp
= av7110
->osdbpp
[av7110
->osdwin
] + 1;
1021 bpl
= ((w
* bpp
+ 7) & ~7) / 8;
1023 lpb
= (32 * 1024) / bpl
;
1024 bnum
= size
/ (lpb
* bpl
);
1025 brest
= size
- bnum
* lpb
* bpl
;
1027 if (av7110
->bmp_state
== BMP_LOADING
) {
1028 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1029 BUG_ON (FW_VERSION(av7110
->arm_app
) >= 0x261e);
1030 rc
= WaitUntilBmpLoaded(av7110
);
1033 /* just continue. This should work for all fw versions
1034 * if bnum==1 && !brest && LoadBitmap was successful
1039 for (i
= 0; i
< bnum
; i
++) {
1040 rc
= LoadBitmap(av7110
, w
, lpb
, inc
, data
);
1043 rc
= BlitBitmap(av7110
, x0
, y0
+ i
* lpb
);
1049 rc
= LoadBitmap(av7110
, w
, brest
/ bpl
, inc
, data
);
1051 rc
= BlitBitmap(av7110
, x0
, y0
+ bnum
* lpb
);
1053 release_rc
= ReleaseBitmap(av7110
);
1057 dprintk(1,"returns %d\n",rc
);
1061 int av7110_osd_cmd(struct av7110
*av7110
, osd_cmd_t
*dc
)
1065 if (mutex_lock_interruptible(&av7110
->osd_mutex
))
1066 return -ERESTARTSYS
;
1070 ret
= DestroyOSDWindow(av7110
, av7110
->osdwin
);
1073 av7110
->osdbpp
[av7110
->osdwin
] = (dc
->color
- 1) & 7;
1074 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
,
1075 bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]],
1076 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1080 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1083 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1087 ret
= MoveWindowRel(av7110
, av7110
->osdwin
, 0, 0);
1090 ret
= HideWindow(av7110
, av7110
->osdwin
);
1093 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, 0);
1096 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, dc
->color
);
1099 ret
= OSDSetColor(av7110
, dc
->color
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
);
1101 case OSD_SetPalette
:
1102 if (FW_VERSION(av7110
->arm_app
) >= 0x2618)
1103 ret
= OSDSetPalette(av7110
, dc
->data
, dc
->color
, dc
->x0
);
1105 int i
, len
= dc
->x0
-dc
->color
+1;
1106 u8 __user
*colors
= (u8 __user
*)dc
->data
;
1107 u8 r
, g
= 0, b
= 0, blend
= 0;
1109 for (i
= 0; i
<len
; i
++) {
1110 if (get_user(r
, colors
+ i
* 4) ||
1111 get_user(g
, colors
+ i
* 4 + 1) ||
1112 get_user(b
, colors
+ i
* 4 + 2) ||
1113 get_user(blend
, colors
+ i
* 4 + 3)) {
1117 ret
= OSDSetColor(av7110
, dc
->color
+ i
, r
, g
, b
, blend
);
1124 ret
= DrawLine(av7110
, av7110
->osdwin
,
1125 dc
->x0
, dc
->y0
, 0, 0, dc
->color
);
1131 ret
= OSDSetBlock(av7110
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
, dc
->color
, dc
->data
);
1134 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1135 dc
->x1
-dc
->x0
+1, dc
->y1
, dc
->color
);
1138 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1139 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1, dc
->color
);
1142 ret
= DrawLine(av7110
, av7110
->osdwin
,
1143 dc
->x0
, dc
->y0
, dc
->x1
- dc
->x0
, dc
->y1
- dc
->y0
, dc
->color
);
1149 if (strncpy_from_user(textbuf
, dc
->data
, 240) < 0) {
1156 ret
= SetFont(av7110
, av7110
->osdwin
, dc
->x1
,
1157 (u16
) (dc
->color
& 0xffff), (u16
) (dc
->color
>> 16));
1159 ret
= FlushText(av7110
);
1161 ret
= WriteText(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
, textbuf
);
1165 if (dc
->x0
< 1 || dc
->x0
> 7)
1168 av7110
->osdwin
= dc
->x0
;
1172 case OSD_MoveWindow
:
1173 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1175 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1178 if (dc
->color
< OSD_BITMAP1
|| dc
->color
> OSD_CURSOR
) {
1182 if (dc
->color
>= OSD_BITMAP1
&& dc
->color
<= OSD_BITMAP8HR
)
1183 av7110
->osdbpp
[av7110
->osdwin
] = (1 << (dc
->color
& 3)) - 1;
1185 av7110
->osdbpp
[av7110
->osdwin
] = 0;
1186 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
, (osd_raw_window_t
)dc
->color
,
1187 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1191 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1193 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1201 mutex_unlock(&av7110
->osd_mutex
);
1202 if (ret
==-ERESTARTSYS
)
1203 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc
->cmd
);
1205 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc
->cmd
,ret
);
1210 int av7110_osd_capability(struct av7110
*av7110
, osd_cap_t
*cap
)
1213 case OSD_CAP_MEMSIZE
:
1214 if (FW_4M_SDRAM(av7110
->arm_app
))
1223 #endif /* CONFIG_DVB_AV7110_OSD */