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.
19 * To obtain the license, point your browser to
20 * http://www.gnu.org/copyleft/gpl.html
22 * the project's page is at https://linuxtv.org
25 /* for debugging ARM communication: */
29 #include <linux/types.h>
30 #include <linux/kernel.h>
31 #include <linux/string.h>
32 #include <linux/delay.h>
36 #include "av7110_hw.h"
41 * Max transfer size done by av7110_fw_cmd()
43 * The maximum size passed to this function is 6 bytes. The buffer also
44 * uses two additional ones for type and size. So, 8 bytes is enough.
46 #define MAX_XFER_SIZE 8
48 /****************************************************************************
50 ****************************************************************************/
52 /* This DEBI code is based on the Stradis driver
53 by Nathan Laredo <laredo@gnu.org> */
55 int av7110_debiwrite(struct av7110
*av7110
, u32 config
,
56 int addr
, u32 val
, unsigned int count
)
58 struct saa7146_dev
*dev
= av7110
->dev
;
61 printk("%s: invalid count %d\n", __func__
, count
);
64 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
65 printk("%s: wait_for_debi_done failed\n", __func__
);
68 saa7146_write(dev
, DEBI_CONFIG
, config
);
69 if (count
<= 4) /* immediate transfer */
70 saa7146_write(dev
, DEBI_AD
, val
);
71 else /* block transfer */
72 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
73 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | (addr
& 0xffff));
74 saa7146_write(dev
, MC2
, (2 << 16) | 2);
78 u32
av7110_debiread(struct av7110
*av7110
, u32 config
, int addr
, unsigned int count
)
80 struct saa7146_dev
*dev
= av7110
->dev
;
84 printk("%s: invalid count %d\n", __func__
, count
);
87 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
88 printk("%s: wait_for_debi_done #1 failed\n", __func__
);
91 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
92 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | 0x10000 | (addr
& 0xffff));
94 saa7146_write(dev
, DEBI_CONFIG
, config
);
95 saa7146_write(dev
, MC2
, (2 << 16) | 2);
98 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
99 printk("%s: wait_for_debi_done #2 failed\n", __func__
);
103 result
= saa7146_read(dev
, DEBI_AD
);
104 result
&= (0xffffffffUL
>> ((4 - count
) * 8));
110 /* av7110 ARM core boot stuff */
112 void av7110_reset_arm(struct av7110
*av7110
)
114 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
116 /* Disable DEBI and GPIO irq */
117 SAA7146_IER_DISABLE(av7110
->dev
, MASK_19
| MASK_03
);
118 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
120 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
121 msleep(30); /* the firmware needs some time to initialize */
123 ARM_ResetMailBox(av7110
);
125 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
126 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
128 av7110
->arm_ready
= 1;
129 dprintk(1, "reset ARM\n");
133 static int waitdebi(struct av7110
*av7110
, int adr
, int state
)
137 dprintk(4, "%p\n", av7110
);
139 for (k
= 0; k
< 100; k
++) {
140 if (irdebi(av7110
, DEBINOSWAP
, adr
, 0, 2) == state
)
147 static int load_dram(struct av7110
*av7110
, u32
*data
, int len
)
151 u32 base
, bootblock
= AV7110_BOOT_BLOCK
;
153 dprintk(4, "%p\n", av7110
);
155 blocks
= len
/ AV7110_BOOT_MAX_SIZE
;
156 rest
= len
% AV7110_BOOT_MAX_SIZE
;
157 base
= DRAM_START_CODE
;
159 for (i
= 0; i
< blocks
; i
++) {
160 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
161 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at block %d\n", i
);
164 dprintk(4, "writing DRAM block %d\n", i
);
165 mwdebi(av7110
, DEBISWAB
, bootblock
,
166 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, AV7110_BOOT_MAX_SIZE
);
168 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
169 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, AV7110_BOOT_MAX_SIZE
, 2);
170 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
171 base
+= AV7110_BOOT_MAX_SIZE
;
175 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
176 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at last block\n");
180 mwdebi(av7110
, DEBISWAB
, bootblock
,
181 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, rest
);
183 mwdebi(av7110
, DEBISWAB
, bootblock
,
184 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
- 4, rest
+ 4);
186 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
187 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, rest
, 2);
188 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
190 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
191 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout after last block\n");
194 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, 0, 2);
195 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
196 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_AV7110_BOOT_COMPLETE
) < 0) {
197 printk(KERN_ERR
"dvb-ttpci: load_dram(): final handshake timeout\n");
204 /* we cannot write av7110 DRAM directly, so load a bootloader into
205 * the DPRAM which implements a simple boot protocol */
206 int av7110_bootarm(struct av7110
*av7110
)
208 const struct firmware
*fw
;
209 const char *fw_name
= "av7110/bootcode.bin";
210 struct saa7146_dev
*dev
= av7110
->dev
;
214 dprintk(4, "%p\n", av7110
);
216 av7110
->arm_ready
= 0;
218 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
220 /* Disable DEBI and GPIO irq */
221 SAA7146_IER_DISABLE(av7110
->dev
, MASK_03
| MASK_19
);
222 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
225 saa7146_write(av7110
->dev
, MC1
, 0x08800880);
226 saa7146_write(av7110
->dev
, DD1_STREAM_B
, 0x00000000);
227 saa7146_write(av7110
->dev
, MC2
, (MASK_09
| MASK_25
| MASK_10
| MASK_26
));
230 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
231 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
232 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
234 if ((ret
=irdebi(av7110
, DEBINOSWAP
, DPRAM_BASE
, 0, 4)) != 0x10325476) {
235 printk(KERN_ERR
"dvb-ttpci: debi test in av7110_bootarm() failed: %08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
239 for (i
= 0; i
< 8192; i
+= 4)
240 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
+ i
, 0x00, 4);
241 dprintk(2, "debi test OK\n");
244 dprintk(1, "load boot code\n");
245 saa7146_setgpio(dev
, ARM_IRQ_LINE
, SAA7146_GPIO_IRQLO
);
246 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
247 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
249 ret
= request_firmware(&fw
, fw_name
, &dev
->pci
->dev
);
251 printk(KERN_ERR
"dvb-ttpci: Failed to load firmware \"%s\"\n",
256 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, fw
->data
, fw
->size
);
257 release_firmware(fw
);
258 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
260 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
261 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out\n");
264 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
267 dprintk(1, "load dram code\n");
268 if (load_dram(av7110
, (u32
*)av7110
->bin_root
, av7110
->size_root
) < 0) {
269 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): load_dram() failed\n");
273 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
276 dprintk(1, "load dpram code\n");
277 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, av7110
->bin_dpram
, av7110
->size_dpram
);
279 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
280 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out after loading DRAM\n");
283 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
284 msleep(30); /* the firmware needs some time to initialize */
286 //ARM_ClearIrq(av7110);
287 ARM_ResetMailBox(av7110
);
288 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
289 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
291 av7110
->arm_errors
= 0;
292 av7110
->arm_ready
= 1;
295 MODULE_FIRMWARE("av7110/bootcode.bin");
297 /****************************************************************************
298 * DEBI command polling
299 ****************************************************************************/
301 int av7110_wait_msgstate(struct av7110
*av7110
, u16 flags
)
307 if (FW_VERSION(av7110
->arm_app
) <= 0x261c) {
308 /* not supported by old firmware */
316 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
317 if (mutex_lock_interruptible(&av7110
->dcomlock
))
319 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
320 mutex_unlock(&av7110
->dcomlock
);
321 if ((stat
& flags
) == 0)
324 printk(KERN_ERR
"%s: timeout waiting for MSGSTATE %04x\n",
325 __func__
, stat
& flags
);
333 static int __av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
338 u16 flags
[2] = {0, 0};
342 // dprintk(4, "%p\n", av7110);
344 if (!av7110
->arm_ready
) {
345 dprintk(1, "arm not ready.\n");
351 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
352 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
355 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__
);
356 av7110
->arm_errors
++;
362 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
363 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0xffff, 2);
368 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
369 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
372 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__
);
379 switch ((buf
[0] >> 8) & 0xff) {
380 case COMTYPE_PIDFILTER
:
381 case COMTYPE_ENCODER
:
382 case COMTYPE_REC_PLAY
:
383 case COMTYPE_MPEGDECODER
:
394 if (FW_VERSION(av7110
->arm_app
) >= 0x261d) {
405 /* non-immediate COMMAND type */
408 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
409 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
410 if (stat
& flags
[0]) {
411 printk(KERN_ERR
"%s: %s QUEUE overflow\n",
415 if ((stat
& flags
[1]) == 0)
418 printk(KERN_ERR
"%s: timeout waiting on busy %s QUEUE\n",
420 av7110
->arm_errors
++;
427 for (i
= 2; i
< length
; i
++)
428 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2 * i
, (u32
) buf
[i
], 2);
431 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, (u32
) buf
[1], 2);
433 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, 0, 2);
435 wdebi(av7110
, DEBINOSWAP
, COMMAND
, (u32
) buf
[0], 2);
437 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
438 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0x0000, 2);
443 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
444 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
447 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
448 __func__
, (buf
[0] >> 8) & 0xff);
454 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
455 if (stat
& GPMQOver
) {
456 printk(KERN_ERR
"dvb-ttpci: %s(): GPMQOver\n", __func__
);
459 else if (stat
& OSDQOver
) {
460 printk(KERN_ERR
"dvb-ttpci: %s(): OSDQOver\n", __func__
);
468 static int av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
472 // dprintk(4, "%p\n", av7110);
474 if (!av7110
->arm_ready
) {
475 dprintk(1, "arm not ready.\n");
478 if (mutex_lock_interruptible(&av7110
->dcomlock
))
481 ret
= __av7110_send_fw_cmd(av7110
, buf
, length
);
482 mutex_unlock(&av7110
->dcomlock
);
483 if (ret
&& ret
!=-ERESTARTSYS
)
484 printk(KERN_ERR
"dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
489 int av7110_fw_cmd(struct av7110
*av7110
, int type
, int com
, int num
, ...)
492 u16 buf
[MAX_XFER_SIZE
];
495 // dprintk(4, "%p\n", av7110);
497 if (2 + num
> ARRAY_SIZE(buf
)) {
499 "%s: %s len=%d is too big!\n",
500 KBUILD_MODNAME
, __func__
, num
);
504 buf
[0] = ((type
<< 8) | com
);
509 for (i
= 0; i
< num
; i
++)
510 buf
[i
+ 2] = va_arg(args
, u32
);
514 ret
= av7110_send_fw_cmd(av7110
, buf
, num
+ 2);
515 if (ret
&& ret
!= -ERESTARTSYS
)
516 printk(KERN_ERR
"dvb-ttpci: av7110_fw_cmd error %d\n", ret
);
521 int av7110_send_ci_cmd(struct av7110
*av7110
, u8 subcom
, u8
*buf
, u8 len
)
524 u16 cmd
[18] = { ((COMTYPE_COMMON_IF
<< 8) + subcom
),
525 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
527 dprintk(4, "%p\n", av7110
);
529 for(i
= 0; i
< len
&& i
< 32; i
++)
532 cmd
[(i
/ 2) + 2] = (u16
)(buf
[i
]) << 8;
534 cmd
[(i
/ 2) + 2] |= buf
[i
];
537 ret
= av7110_send_fw_cmd(av7110
, cmd
, 18);
538 if (ret
&& ret
!= -ERESTARTSYS
)
539 printk(KERN_ERR
"dvb-ttpci: av7110_send_ci_cmd error %d\n", ret
);
544 int av7110_fw_request(struct av7110
*av7110
, u16
*request_buf
,
545 int request_buf_len
, u16
*reply_buf
, int reply_buf_len
)
554 dprintk(4, "%p\n", av7110
);
556 if (!av7110
->arm_ready
) {
557 dprintk(1, "arm not ready.\n");
561 if (mutex_lock_interruptible(&av7110
->dcomlock
))
564 if ((err
= __av7110_send_fw_cmd(av7110
, request_buf
, request_buf_len
)) < 0) {
565 mutex_unlock(&av7110
->dcomlock
);
566 printk(KERN_ERR
"dvb-ttpci: av7110_fw_request error %d\n", err
);
572 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
573 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
576 printk(KERN_ERR
"%s: timeout waiting for COMMAND to complete\n", __func__
);
577 mutex_unlock(&av7110
->dcomlock
);
588 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
589 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
592 printk(KERN_ERR
"%s: timeout waiting for HANDSHAKE_REG\n", __func__
);
593 mutex_unlock(&av7110
->dcomlock
);
601 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
602 if (stat
& GPMQOver
) {
603 printk(KERN_ERR
"%s: GPMQOver\n", __func__
);
604 mutex_unlock(&av7110
->dcomlock
);
607 else if (stat
& OSDQOver
) {
608 printk(KERN_ERR
"%s: OSDQOver\n", __func__
);
609 mutex_unlock(&av7110
->dcomlock
);
614 for (i
= 0; i
< reply_buf_len
; i
++)
615 reply_buf
[i
] = rdebi(av7110
, DEBINOSWAP
, COM_BUFF
+ 2 * i
, 0, 2);
617 mutex_unlock(&av7110
->dcomlock
);
621 static int av7110_fw_query(struct av7110
*av7110
, u16 tag
, u16
* buf
, s16 length
)
624 ret
= av7110_fw_request(av7110
, &tag
, 0, buf
, length
);
626 printk(KERN_ERR
"dvb-ttpci: av7110_fw_query error %d\n", ret
);
631 /****************************************************************************
633 ****************************************************************************/
635 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
636 int av7110_firmversion(struct av7110
*av7110
)
639 u16 tag
= ((COMTYPE_REQUEST
<< 8) + ReqVersion
);
641 dprintk(4, "%p\n", av7110
);
643 if (av7110_fw_query(av7110
, tag
, buf
, 16)) {
644 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
645 av7110
->dvb_adapter
.num
);
649 av7110
->arm_fw
= (buf
[0] << 16) + buf
[1];
650 av7110
->arm_rtsl
= (buf
[2] << 16) + buf
[3];
651 av7110
->arm_vid
= (buf
[4] << 16) + buf
[5];
652 av7110
->arm_app
= (buf
[6] << 16) + buf
[7];
653 av7110
->avtype
= (buf
[8] << 16) + buf
[9];
655 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
656 av7110
->dvb_adapter
.num
, av7110
->arm_fw
,
657 av7110
->arm_rtsl
, av7110
->arm_vid
, av7110
->arm_app
);
659 /* print firmware capabilities */
660 if (FW_CI_LL_SUPPORT(av7110
->arm_app
))
661 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
662 av7110
->dvb_adapter
.num
);
664 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
665 av7110
->dvb_adapter
.num
);
671 int av7110_diseqc_send(struct av7110
*av7110
, int len
, u8
*msg
, unsigned long burst
)
674 u16 buf
[18] = { ((COMTYPE_AUDIODAC
<< 8) + SendDiSEqC
),
675 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
677 dprintk(4, "%p\n", av7110
);
686 buf
[3] = burst
? 0x01 : 0x00;
690 for (i
= 0; i
< len
; i
++)
693 ret
= av7110_send_fw_cmd(av7110
, buf
, 18);
694 if (ret
&& ret
!=-ERESTARTSYS
)
695 printk(KERN_ERR
"dvb-ttpci: av7110_diseqc_send error %d\n", ret
);
700 #ifdef CONFIG_DVB_AV7110_OSD
702 static inline int SetColorBlend(struct av7110
*av7110
, u8 windownr
)
704 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetCBlend
, 1, windownr
);
707 static inline int SetBlend_(struct av7110
*av7110
, u8 windownr
,
708 enum av7110_osd_palette_type colordepth
, u16 index
, u8 blending
)
710 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetBlend
, 4,
711 windownr
, colordepth
, index
, blending
);
714 static inline int SetColor_(struct av7110
*av7110
, u8 windownr
,
715 enum av7110_osd_palette_type colordepth
, u16 index
, u16 colorhi
, u16 colorlo
)
717 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetColor
, 5,
718 windownr
, colordepth
, index
, colorhi
, colorlo
);
721 static inline int SetFont(struct av7110
*av7110
, u8 windownr
, u8 fontsize
,
722 u16 colorfg
, u16 colorbg
)
724 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Font
, 4,
725 windownr
, fontsize
, colorfg
, colorbg
);
728 static int FlushText(struct av7110
*av7110
)
733 if (mutex_lock_interruptible(&av7110
->dcomlock
))
737 err
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
738 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
741 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
743 mutex_unlock(&av7110
->dcomlock
);
748 mutex_unlock(&av7110
->dcomlock
);
752 static int WriteText(struct av7110
*av7110
, u8 win
, u16 x
, u16 y
, char *buf
)
756 int length
= strlen(buf
) + 1;
757 u16 cbuf
[5] = { (COMTYPE_OSD
<< 8) + DText
, 3, win
, x
, y
};
759 if (mutex_lock_interruptible(&av7110
->dcomlock
))
764 ret
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
765 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
768 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
770 mutex_unlock(&av7110
->dcomlock
);
778 ret
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
779 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
782 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
784 mutex_unlock(&av7110
->dcomlock
);
790 for (i
= 0; i
< length
/ 2; i
++)
791 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2,
792 swab16(*(u16
*)(buf
+ 2 * i
)), 2);
794 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2, 0, 2);
795 ret
= __av7110_send_fw_cmd(av7110
, cbuf
, 5);
796 mutex_unlock(&av7110
->dcomlock
);
797 if (ret
&& ret
!=-ERESTARTSYS
)
798 printk(KERN_ERR
"dvb-ttpci: WriteText error %d\n", ret
);
802 static inline int DrawLine(struct av7110
*av7110
, u8 windownr
,
803 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
805 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DLine
, 6,
806 windownr
, x
, y
, dx
, dy
, color
);
809 static inline int DrawBlock(struct av7110
*av7110
, u8 windownr
,
810 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
812 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DBox
, 6,
813 windownr
, x
, y
, dx
, dy
, color
);
816 static inline int HideWindow(struct av7110
*av7110
, u8 windownr
)
818 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WHide
, 1, windownr
);
821 static inline int MoveWindowRel(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
823 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveD
, 3, windownr
, x
, y
);
826 static inline int MoveWindowAbs(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
828 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveA
, 3, windownr
, x
, y
);
831 static inline int DestroyOSDWindow(struct av7110
*av7110
, u8 windownr
)
833 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WDestroy
, 1, windownr
);
836 static inline int CreateOSDWindow(struct av7110
*av7110
, u8 windownr
,
837 osd_raw_window_t disptype
,
838 u16 width
, u16 height
)
840 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WCreate
, 4,
841 windownr
, disptype
, width
, height
);
845 static enum av7110_osd_palette_type bpp2pal
[8] = {
846 Pal1Bit
, Pal2Bit
, 0, Pal4Bit
, 0, 0, 0, Pal8Bit
848 static osd_raw_window_t bpp2bit
[8] = {
849 OSD_BITMAP1
, OSD_BITMAP2
, 0, OSD_BITMAP4
, 0, 0, 0, OSD_BITMAP8
852 static inline int WaitUntilBmpLoaded(struct av7110
*av7110
)
854 int ret
= wait_event_timeout(av7110
->bmpq
,
855 av7110
->bmp_state
!= BMP_LOADING
, 10*HZ
);
857 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
858 ret
, av7110
->bmp_state
);
859 av7110
->bmp_state
= BMP_NONE
;
865 static inline int LoadBitmap(struct av7110
*av7110
,
866 u16 dx
, u16 dy
, int inc
, u8 __user
* data
)
875 dprintk(4, "%p\n", av7110
);
877 format
= bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]];
879 av7110
->bmp_state
= BMP_LOADING
;
880 if (format
== OSD_BITMAP8
) {
882 } else if (format
== OSD_BITMAP4
) {
884 } else if (format
== OSD_BITMAP2
) {
886 } else if (format
== OSD_BITMAP1
) {
889 av7110
->bmp_state
= BMP_NONE
;
892 av7110
->bmplen
= ((dx
* dy
* bpp
+ 7) & ~7) / 8;
894 if (av7110
->bmplen
> 32768) {
895 av7110
->bmp_state
= BMP_NONE
;
898 for (i
= 0; i
< dy
; i
++) {
899 if (copy_from_user(av7110
->bmpbuf
+ 1024 + i
* dx
, data
+ i
* inc
, dx
)) {
900 av7110
->bmp_state
= BMP_NONE
;
904 if (format
!= OSD_BITMAP8
) {
905 for (i
= 0; i
< dx
* dy
/ delta
; i
++) {
906 c
= ((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ delta
- 1];
907 for (d
= delta
- 2; d
>= 0; d
--) {
908 c
|= (((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ d
]
909 << ((delta
- d
- 1) * bpp
));
910 ((u8
*)av7110
->bmpbuf
)[1024 + i
] = c
;
914 av7110
->bmplen
+= 1024;
915 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110
->bmplen
);
916 ret
= av7110_fw_cmd(av7110
, COMTYPE_OSD
, LoadBmp
, 3, format
, dx
, dy
);
918 ret
= WaitUntilBmpLoaded(av7110
);
922 static int BlitBitmap(struct av7110
*av7110
, u16 x
, u16 y
)
924 dprintk(4, "%p\n", av7110
);
926 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, BlitBmp
, 4, av7110
->osdwin
, x
, y
, 0);
929 static inline int ReleaseBitmap(struct av7110
*av7110
)
931 dprintk(4, "%p\n", av7110
);
933 if (av7110
->bmp_state
!= BMP_LOADED
&& FW_VERSION(av7110
->arm_app
) < 0x261e)
935 if (av7110
->bmp_state
== BMP_LOADING
)
936 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
937 av7110
->bmp_state
= BMP_NONE
;
938 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, ReleaseBmp
, 0);
941 static u32
RGB2YUV(u16 R
, u16 G
, u16 B
)
946 y
= R
* 77 + G
* 150 + B
* 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
947 u
= 2048 + B
* 8 -(y
>> 5); /* Cr 0..4095 */
948 v
= 2048 + R
* 8 -(y
>> 5); /* Cb 0..4095 */
954 return Cr
| (Cb
<< 16) | (Y
<< 8);
957 static int OSDSetColor(struct av7110
*av7110
, u8 color
, u8 r
, u8 g
, u8 b
, u8 blend
)
964 yuv
= blend
? RGB2YUV(r
,g
,b
) : 0;
966 ch
= ((yuv
>> 16) & 0xffff);
967 ret
= SetColor_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
970 ret
= SetBlend_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
971 color
, ((blend
>> 4) & 0x0f));
975 static int OSDSetPalette(struct av7110
*av7110
, u32 __user
* colors
, u8 first
, u8 last
)
978 int length
= last
- first
+ 1;
980 if (length
* 4 > DATA_BUFF3_SIZE
)
983 for (i
= 0; i
< length
; i
++) {
984 u32 color
, blend
, yuv
;
986 if (get_user(color
, colors
+ i
))
988 blend
= (color
& 0xF0000000) >> 4;
989 yuv
= blend
? RGB2YUV(color
& 0xFF, (color
>> 8) & 0xFF,
990 (color
>> 16) & 0xFF) | blend
: 0;
991 yuv
= ((yuv
& 0xFFFF0000) >> 16) | ((yuv
& 0x0000FFFF) << 16);
992 wdebi(av7110
, DEBINOSWAP
, DATA_BUFF3_BASE
+ i
* 4, yuv
, 4);
994 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Palette
, 4,
996 bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
1000 static int OSDSetBlock(struct av7110
*av7110
, int x0
, int y0
,
1001 int x1
, int y1
, int inc
, u8 __user
* data
)
1003 uint w
, h
, bpp
, bpl
, size
, lpb
, bnum
, brest
;
1011 if (w
<= 0 || w
> 720 || h
<= 0 || h
> 576)
1013 bpp
= av7110
->osdbpp
[av7110
->osdwin
] + 1;
1014 bpl
= ((w
* bpp
+ 7) & ~7) / 8;
1016 lpb
= (32 * 1024) / bpl
;
1017 bnum
= size
/ (lpb
* bpl
);
1018 brest
= size
- bnum
* lpb
* bpl
;
1020 if (av7110
->bmp_state
== BMP_LOADING
) {
1021 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1022 BUG_ON (FW_VERSION(av7110
->arm_app
) >= 0x261e);
1023 rc
= WaitUntilBmpLoaded(av7110
);
1026 /* just continue. This should work for all fw versions
1027 * if bnum==1 && !brest && LoadBitmap was successful
1032 for (i
= 0; i
< bnum
; i
++) {
1033 rc
= LoadBitmap(av7110
, w
, lpb
, inc
, data
);
1036 rc
= BlitBitmap(av7110
, x0
, y0
+ i
* lpb
);
1042 rc
= LoadBitmap(av7110
, w
, brest
/ bpl
, inc
, data
);
1044 rc
= BlitBitmap(av7110
, x0
, y0
+ bnum
* lpb
);
1046 release_rc
= ReleaseBitmap(av7110
);
1050 dprintk(1,"returns %d\n",rc
);
1054 int av7110_osd_cmd(struct av7110
*av7110
, osd_cmd_t
*dc
)
1058 if (mutex_lock_interruptible(&av7110
->osd_mutex
))
1059 return -ERESTARTSYS
;
1063 ret
= DestroyOSDWindow(av7110
, av7110
->osdwin
);
1066 av7110
->osdbpp
[av7110
->osdwin
] = (dc
->color
- 1) & 7;
1067 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
,
1068 bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]],
1069 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1073 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1076 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1080 ret
= MoveWindowRel(av7110
, av7110
->osdwin
, 0, 0);
1083 ret
= HideWindow(av7110
, av7110
->osdwin
);
1086 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, 0);
1089 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, dc
->color
);
1092 ret
= OSDSetColor(av7110
, dc
->color
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
);
1094 case OSD_SetPalette
:
1095 if (FW_VERSION(av7110
->arm_app
) >= 0x2618)
1096 ret
= OSDSetPalette(av7110
, dc
->data
, dc
->color
, dc
->x0
);
1098 int i
, len
= dc
->x0
-dc
->color
+1;
1099 u8 __user
*colors
= (u8 __user
*)dc
->data
;
1100 u8 r
, g
= 0, b
= 0, blend
= 0;
1102 for (i
= 0; i
<len
; i
++) {
1103 if (get_user(r
, colors
+ i
* 4) ||
1104 get_user(g
, colors
+ i
* 4 + 1) ||
1105 get_user(b
, colors
+ i
* 4 + 2) ||
1106 get_user(blend
, colors
+ i
* 4 + 3)) {
1110 ret
= OSDSetColor(av7110
, dc
->color
+ i
, r
, g
, b
, blend
);
1117 ret
= DrawLine(av7110
, av7110
->osdwin
,
1118 dc
->x0
, dc
->y0
, 0, 0, dc
->color
);
1124 ret
= OSDSetBlock(av7110
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
, dc
->color
, dc
->data
);
1127 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1128 dc
->x1
-dc
->x0
+1, dc
->y1
, dc
->color
);
1131 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1132 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1, dc
->color
);
1135 ret
= DrawLine(av7110
, av7110
->osdwin
,
1136 dc
->x0
, dc
->y0
, dc
->x1
- dc
->x0
, dc
->y1
- dc
->y0
, dc
->color
);
1142 if (strncpy_from_user(textbuf
, dc
->data
, 240) < 0) {
1149 ret
= SetFont(av7110
, av7110
->osdwin
, dc
->x1
,
1150 (u16
) (dc
->color
& 0xffff), (u16
) (dc
->color
>> 16));
1152 ret
= FlushText(av7110
);
1154 ret
= WriteText(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
, textbuf
);
1158 if (dc
->x0
< 1 || dc
->x0
> 7)
1161 av7110
->osdwin
= dc
->x0
;
1165 case OSD_MoveWindow
:
1166 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1168 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1171 if (dc
->color
< OSD_BITMAP1
|| dc
->color
> OSD_CURSOR
) {
1175 if (dc
->color
>= OSD_BITMAP1
&& dc
->color
<= OSD_BITMAP8HR
)
1176 av7110
->osdbpp
[av7110
->osdwin
] = (1 << (dc
->color
& 3)) - 1;
1178 av7110
->osdbpp
[av7110
->osdwin
] = 0;
1179 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
, (osd_raw_window_t
)dc
->color
,
1180 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1184 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1186 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1194 mutex_unlock(&av7110
->osd_mutex
);
1195 if (ret
==-ERESTARTSYS
)
1196 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc
->cmd
);
1198 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc
->cmd
,ret
);
1203 int av7110_osd_capability(struct av7110
*av7110
, osd_cap_t
*cap
)
1206 case OSD_CAP_MEMSIZE
:
1207 if (FW_4M_SDRAM(av7110
->arm_app
))
1216 #endif /* CONFIG_DVB_AV7110_OSD */