1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * av7110_hw.c: av7110 low level hardware access and firmware interface
5 * Copyright (C) 1999-2002 Ralph Metzler
6 * & Marcus Metzler for convergence integrated media GmbH
8 * originally based on code by:
9 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
11 * the project's page is at https://linuxtv.org
14 /* for debugging ARM communication: */
17 #include <linux/types.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
20 #include <linux/delay.h>
24 #include "av7110_hw.h"
29 * Max transfer size done by av7110_fw_cmd()
31 * The maximum size passed to this function is 6 bytes. The buffer also
32 * uses two additional ones for type and size. So, 8 bytes is enough.
34 #define MAX_XFER_SIZE 8
36 /****************************************************************************
38 ****************************************************************************/
40 /* This DEBI code is based on the Stradis driver
41 by Nathan Laredo <laredo@gnu.org> */
43 int av7110_debiwrite(struct av7110
*av7110
, u32 config
,
44 int addr
, u32 val
, unsigned int count
)
46 struct saa7146_dev
*dev
= av7110
->dev
;
49 printk("%s: invalid count %d\n", __func__
, count
);
52 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
53 printk("%s: wait_for_debi_done failed\n", __func__
);
56 saa7146_write(dev
, DEBI_CONFIG
, config
);
57 if (count
<= 4) /* immediate transfer */
58 saa7146_write(dev
, DEBI_AD
, val
);
59 else /* block transfer */
60 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
61 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | (addr
& 0xffff));
62 saa7146_write(dev
, MC2
, (2 << 16) | 2);
66 u32
av7110_debiread(struct av7110
*av7110
, u32 config
, int addr
, unsigned int count
)
68 struct saa7146_dev
*dev
= av7110
->dev
;
72 printk("%s: invalid count %d\n", __func__
, count
);
75 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
76 printk("%s: wait_for_debi_done #1 failed\n", __func__
);
79 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
80 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | 0x10000 | (addr
& 0xffff));
82 saa7146_write(dev
, DEBI_CONFIG
, config
);
83 saa7146_write(dev
, MC2
, (2 << 16) | 2);
86 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
87 printk("%s: wait_for_debi_done #2 failed\n", __func__
);
91 result
= saa7146_read(dev
, DEBI_AD
);
92 result
&= (0xffffffffUL
>> ((4 - count
) * 8));
98 /* av7110 ARM core boot stuff */
100 void av7110_reset_arm(struct av7110
*av7110
)
102 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
104 /* Disable DEBI and GPIO irq */
105 SAA7146_IER_DISABLE(av7110
->dev
, MASK_19
| MASK_03
);
106 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
108 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
109 msleep(30); /* the firmware needs some time to initialize */
111 ARM_ResetMailBox(av7110
);
113 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
114 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
116 av7110
->arm_ready
= 1;
117 dprintk(1, "reset ARM\n");
121 static int waitdebi(struct av7110
*av7110
, int adr
, int state
)
125 dprintk(4, "%p\n", av7110
);
127 for (k
= 0; k
< 100; k
++) {
128 if (irdebi(av7110
, DEBINOSWAP
, adr
, 0, 2) == state
)
135 static int load_dram(struct av7110
*av7110
, u32
*data
, int len
)
139 u32 base
, bootblock
= AV7110_BOOT_BLOCK
;
141 dprintk(4, "%p\n", av7110
);
143 blocks
= len
/ AV7110_BOOT_MAX_SIZE
;
144 rest
= len
% AV7110_BOOT_MAX_SIZE
;
145 base
= DRAM_START_CODE
;
147 for (i
= 0; i
< blocks
; i
++) {
148 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
149 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at block %d\n", i
);
152 dprintk(4, "writing DRAM block %d\n", i
);
153 mwdebi(av7110
, DEBISWAB
, bootblock
,
154 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, AV7110_BOOT_MAX_SIZE
);
156 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
157 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, AV7110_BOOT_MAX_SIZE
, 2);
158 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
159 base
+= AV7110_BOOT_MAX_SIZE
;
163 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
164 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at last block\n");
168 mwdebi(av7110
, DEBISWAB
, bootblock
,
169 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, rest
);
171 mwdebi(av7110
, DEBISWAB
, bootblock
,
172 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
- 4, rest
+ 4);
174 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
175 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, rest
, 2);
176 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
178 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
179 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout after last block\n");
182 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, 0, 2);
183 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
184 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_AV7110_BOOT_COMPLETE
) < 0) {
185 printk(KERN_ERR
"dvb-ttpci: load_dram(): final handshake timeout\n");
192 /* we cannot write av7110 DRAM directly, so load a bootloader into
193 * the DPRAM which implements a simple boot protocol */
194 int av7110_bootarm(struct av7110
*av7110
)
196 const struct firmware
*fw
;
197 const char *fw_name
= "av7110/bootcode.bin";
198 struct saa7146_dev
*dev
= av7110
->dev
;
202 dprintk(4, "%p\n", av7110
);
204 av7110
->arm_ready
= 0;
206 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
208 /* Disable DEBI and GPIO irq */
209 SAA7146_IER_DISABLE(av7110
->dev
, MASK_03
| MASK_19
);
210 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
213 saa7146_write(av7110
->dev
, MC1
, 0x08800880);
214 saa7146_write(av7110
->dev
, DD1_STREAM_B
, 0x00000000);
215 saa7146_write(av7110
->dev
, MC2
, (MASK_09
| MASK_25
| MASK_10
| MASK_26
));
218 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
219 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
220 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
222 if ((ret
=irdebi(av7110
, DEBINOSWAP
, DPRAM_BASE
, 0, 4)) != 0x10325476) {
223 printk(KERN_ERR
"dvb-ttpci: debi test in av7110_bootarm() failed: %08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
227 for (i
= 0; i
< 8192; i
+= 4)
228 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
+ i
, 0x00, 4);
229 dprintk(2, "debi test OK\n");
232 dprintk(1, "load boot code\n");
233 saa7146_setgpio(dev
, ARM_IRQ_LINE
, SAA7146_GPIO_IRQLO
);
234 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
235 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
237 ret
= request_firmware(&fw
, fw_name
, &dev
->pci
->dev
);
239 printk(KERN_ERR
"dvb-ttpci: Failed to load firmware \"%s\"\n",
244 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, fw
->data
, fw
->size
);
245 release_firmware(fw
);
246 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
248 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
249 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out\n");
252 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
255 dprintk(1, "load dram code\n");
256 if (load_dram(av7110
, (u32
*)av7110
->bin_root
, av7110
->size_root
) < 0) {
257 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): load_dram() failed\n");
261 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
264 dprintk(1, "load dpram code\n");
265 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, av7110
->bin_dpram
, av7110
->size_dpram
);
267 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
268 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out after loading DRAM\n");
271 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
272 msleep(30); /* the firmware needs some time to initialize */
274 //ARM_ClearIrq(av7110);
275 ARM_ResetMailBox(av7110
);
276 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
277 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
279 av7110
->arm_errors
= 0;
280 av7110
->arm_ready
= 1;
283 MODULE_FIRMWARE("av7110/bootcode.bin");
285 /****************************************************************************
286 * DEBI command polling
287 ****************************************************************************/
289 int av7110_wait_msgstate(struct av7110
*av7110
, u16 flags
)
295 if (FW_VERSION(av7110
->arm_app
) <= 0x261c) {
296 /* not supported by old firmware */
304 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
305 if (mutex_lock_interruptible(&av7110
->dcomlock
))
307 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
308 mutex_unlock(&av7110
->dcomlock
);
309 if ((stat
& flags
) == 0)
312 printk(KERN_ERR
"%s: timeout waiting for MSGSTATE %04x\n",
313 __func__
, stat
& flags
);
321 static int __av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
326 u16 flags
[2] = {0, 0};
330 // dprintk(4, "%p\n", av7110);
332 if (!av7110
->arm_ready
) {
333 dprintk(1, "arm not ready.\n");
339 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
340 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
343 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__
);
344 av7110
->arm_errors
++;
350 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
351 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0xffff, 2);
356 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
357 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
360 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__
);
367 switch ((buf
[0] >> 8) & 0xff) {
368 case COMTYPE_PIDFILTER
:
369 case COMTYPE_ENCODER
:
370 case COMTYPE_REC_PLAY
:
371 case COMTYPE_MPEGDECODER
:
382 if (FW_VERSION(av7110
->arm_app
) >= 0x261d) {
393 /* non-immediate COMMAND type */
396 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
397 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
398 if (stat
& flags
[0]) {
399 printk(KERN_ERR
"%s: %s QUEUE overflow\n",
403 if ((stat
& flags
[1]) == 0)
406 printk(KERN_ERR
"%s: timeout waiting on busy %s QUEUE\n",
408 av7110
->arm_errors
++;
415 for (i
= 2; i
< length
; i
++)
416 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2 * i
, (u32
) buf
[i
], 2);
419 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, (u32
) buf
[1], 2);
421 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, 0, 2);
423 wdebi(av7110
, DEBINOSWAP
, COMMAND
, (u32
) buf
[0], 2);
425 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
426 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0x0000, 2);
431 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
432 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
435 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
436 __func__
, (buf
[0] >> 8) & 0xff);
442 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
443 if (stat
& GPMQOver
) {
444 printk(KERN_ERR
"dvb-ttpci: %s(): GPMQOver\n", __func__
);
447 else if (stat
& OSDQOver
) {
448 printk(KERN_ERR
"dvb-ttpci: %s(): OSDQOver\n", __func__
);
456 static int av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
460 // dprintk(4, "%p\n", av7110);
462 if (!av7110
->arm_ready
) {
463 dprintk(1, "arm not ready.\n");
466 if (mutex_lock_interruptible(&av7110
->dcomlock
))
469 ret
= __av7110_send_fw_cmd(av7110
, buf
, length
);
470 mutex_unlock(&av7110
->dcomlock
);
471 if (ret
&& ret
!=-ERESTARTSYS
)
472 printk(KERN_ERR
"dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
477 int av7110_fw_cmd(struct av7110
*av7110
, int type
, int com
, int num
, ...)
480 u16 buf
[MAX_XFER_SIZE
];
483 // dprintk(4, "%p\n", av7110);
485 if (2 + num
> ARRAY_SIZE(buf
)) {
487 "%s: %s len=%d is too big!\n",
488 KBUILD_MODNAME
, __func__
, num
);
492 buf
[0] = ((type
<< 8) | com
);
497 for (i
= 0; i
< num
; i
++)
498 buf
[i
+ 2] = va_arg(args
, u32
);
502 ret
= av7110_send_fw_cmd(av7110
, buf
, num
+ 2);
503 if (ret
&& ret
!= -ERESTARTSYS
)
504 printk(KERN_ERR
"dvb-ttpci: av7110_fw_cmd error %d\n", ret
);
509 int av7110_send_ci_cmd(struct av7110
*av7110
, u8 subcom
, u8
*buf
, u8 len
)
512 u16 cmd
[18] = { ((COMTYPE_COMMON_IF
<< 8) + subcom
),
513 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
515 dprintk(4, "%p\n", av7110
);
517 for(i
= 0; i
< len
&& i
< 32; i
++)
520 cmd
[(i
/ 2) + 2] = (u16
)(buf
[i
]) << 8;
522 cmd
[(i
/ 2) + 2] |= buf
[i
];
525 ret
= av7110_send_fw_cmd(av7110
, cmd
, 18);
526 if (ret
&& ret
!= -ERESTARTSYS
)
527 printk(KERN_ERR
"dvb-ttpci: av7110_send_ci_cmd error %d\n", ret
);
532 int av7110_fw_request(struct av7110
*av7110
, u16
*request_buf
,
533 int request_buf_len
, u16
*reply_buf
, int reply_buf_len
)
542 dprintk(4, "%p\n", av7110
);
544 if (!av7110
->arm_ready
) {
545 dprintk(1, "arm not ready.\n");
549 if (mutex_lock_interruptible(&av7110
->dcomlock
))
552 if ((err
= __av7110_send_fw_cmd(av7110
, request_buf
, request_buf_len
)) < 0) {
553 mutex_unlock(&av7110
->dcomlock
);
554 printk(KERN_ERR
"dvb-ttpci: av7110_fw_request error %d\n", err
);
560 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
561 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
564 printk(KERN_ERR
"%s: timeout waiting for COMMAND to complete\n", __func__
);
565 mutex_unlock(&av7110
->dcomlock
);
576 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
577 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
580 printk(KERN_ERR
"%s: timeout waiting for HANDSHAKE_REG\n", __func__
);
581 mutex_unlock(&av7110
->dcomlock
);
589 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
590 if (stat
& GPMQOver
) {
591 printk(KERN_ERR
"%s: GPMQOver\n", __func__
);
592 mutex_unlock(&av7110
->dcomlock
);
595 else if (stat
& OSDQOver
) {
596 printk(KERN_ERR
"%s: OSDQOver\n", __func__
);
597 mutex_unlock(&av7110
->dcomlock
);
602 for (i
= 0; i
< reply_buf_len
; i
++)
603 reply_buf
[i
] = rdebi(av7110
, DEBINOSWAP
, COM_BUFF
+ 2 * i
, 0, 2);
605 mutex_unlock(&av7110
->dcomlock
);
609 static int av7110_fw_query(struct av7110
*av7110
, u16 tag
, u16
* buf
, s16 length
)
612 ret
= av7110_fw_request(av7110
, &tag
, 0, buf
, length
);
614 printk(KERN_ERR
"dvb-ttpci: av7110_fw_query error %d\n", ret
);
619 /****************************************************************************
621 ****************************************************************************/
623 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
624 int av7110_firmversion(struct av7110
*av7110
)
627 u16 tag
= ((COMTYPE_REQUEST
<< 8) + ReqVersion
);
629 dprintk(4, "%p\n", av7110
);
631 if (av7110_fw_query(av7110
, tag
, buf
, 16)) {
632 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
633 av7110
->dvb_adapter
.num
);
637 av7110
->arm_fw
= (buf
[0] << 16) + buf
[1];
638 av7110
->arm_rtsl
= (buf
[2] << 16) + buf
[3];
639 av7110
->arm_vid
= (buf
[4] << 16) + buf
[5];
640 av7110
->arm_app
= (buf
[6] << 16) + buf
[7];
641 av7110
->avtype
= (buf
[8] << 16) + buf
[9];
643 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
644 av7110
->dvb_adapter
.num
, av7110
->arm_fw
,
645 av7110
->arm_rtsl
, av7110
->arm_vid
, av7110
->arm_app
);
647 /* print firmware capabilities */
648 if (FW_CI_LL_SUPPORT(av7110
->arm_app
))
649 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
650 av7110
->dvb_adapter
.num
);
652 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
653 av7110
->dvb_adapter
.num
);
659 int av7110_diseqc_send(struct av7110
*av7110
, int len
, u8
*msg
, unsigned long burst
)
662 u16 buf
[18] = { ((COMTYPE_AUDIODAC
<< 8) + SendDiSEqC
),
663 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
665 dprintk(4, "%p\n", av7110
);
674 buf
[3] = burst
? 0x01 : 0x00;
678 for (i
= 0; i
< len
; i
++)
681 ret
= av7110_send_fw_cmd(av7110
, buf
, 18);
682 if (ret
&& ret
!=-ERESTARTSYS
)
683 printk(KERN_ERR
"dvb-ttpci: av7110_diseqc_send error %d\n", ret
);
688 #ifdef CONFIG_DVB_AV7110_OSD
690 static inline int SetColorBlend(struct av7110
*av7110
, u8 windownr
)
692 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetCBlend
, 1, windownr
);
695 static inline int SetBlend_(struct av7110
*av7110
, u8 windownr
,
696 enum av7110_osd_palette_type colordepth
, u16 index
, u8 blending
)
698 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetBlend
, 4,
699 windownr
, colordepth
, index
, blending
);
702 static inline int SetColor_(struct av7110
*av7110
, u8 windownr
,
703 enum av7110_osd_palette_type colordepth
, u16 index
, u16 colorhi
, u16 colorlo
)
705 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetColor
, 5,
706 windownr
, colordepth
, index
, colorhi
, colorlo
);
709 static inline int SetFont(struct av7110
*av7110
, u8 windownr
, u8 fontsize
,
710 u16 colorfg
, u16 colorbg
)
712 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Font
, 4,
713 windownr
, fontsize
, colorfg
, colorbg
);
716 static int FlushText(struct av7110
*av7110
)
721 if (mutex_lock_interruptible(&av7110
->dcomlock
))
725 err
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
726 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
729 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
731 mutex_unlock(&av7110
->dcomlock
);
736 mutex_unlock(&av7110
->dcomlock
);
740 static int WriteText(struct av7110
*av7110
, u8 win
, u16 x
, u16 y
, char *buf
)
744 int length
= strlen(buf
) + 1;
745 u16 cbuf
[5] = { (COMTYPE_OSD
<< 8) + DText
, 3, win
, x
, y
};
747 if (mutex_lock_interruptible(&av7110
->dcomlock
))
752 ret
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
753 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
756 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
758 mutex_unlock(&av7110
->dcomlock
);
766 ret
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
767 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
770 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
772 mutex_unlock(&av7110
->dcomlock
);
778 for (i
= 0; i
< length
/ 2; i
++)
779 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2,
780 swab16(*(u16
*)(buf
+ 2 * i
)), 2);
782 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2, 0, 2);
783 ret
= __av7110_send_fw_cmd(av7110
, cbuf
, 5);
784 mutex_unlock(&av7110
->dcomlock
);
785 if (ret
&& ret
!=-ERESTARTSYS
)
786 printk(KERN_ERR
"dvb-ttpci: WriteText error %d\n", ret
);
790 static inline int DrawLine(struct av7110
*av7110
, u8 windownr
,
791 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
793 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DLine
, 6,
794 windownr
, x
, y
, dx
, dy
, color
);
797 static inline int DrawBlock(struct av7110
*av7110
, u8 windownr
,
798 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
800 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DBox
, 6,
801 windownr
, x
, y
, dx
, dy
, color
);
804 static inline int HideWindow(struct av7110
*av7110
, u8 windownr
)
806 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WHide
, 1, windownr
);
809 static inline int MoveWindowRel(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
811 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveD
, 3, windownr
, x
, y
);
814 static inline int MoveWindowAbs(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
816 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveA
, 3, windownr
, x
, y
);
819 static inline int DestroyOSDWindow(struct av7110
*av7110
, u8 windownr
)
821 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WDestroy
, 1, windownr
);
824 static inline int CreateOSDWindow(struct av7110
*av7110
, u8 windownr
,
825 osd_raw_window_t disptype
,
826 u16 width
, u16 height
)
828 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WCreate
, 4,
829 windownr
, disptype
, width
, height
);
833 static enum av7110_osd_palette_type bpp2pal
[8] = {
834 Pal1Bit
, Pal2Bit
, 0, Pal4Bit
, 0, 0, 0, Pal8Bit
836 static osd_raw_window_t bpp2bit
[8] = {
837 OSD_BITMAP1
, OSD_BITMAP2
, 0, OSD_BITMAP4
, 0, 0, 0, OSD_BITMAP8
840 static inline int WaitUntilBmpLoaded(struct av7110
*av7110
)
842 int ret
= wait_event_timeout(av7110
->bmpq
,
843 av7110
->bmp_state
!= BMP_LOADING
, 10*HZ
);
845 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
846 ret
, av7110
->bmp_state
);
847 av7110
->bmp_state
= BMP_NONE
;
853 static inline int LoadBitmap(struct av7110
*av7110
,
854 u16 dx
, u16 dy
, int inc
, u8 __user
* data
)
863 dprintk(4, "%p\n", av7110
);
865 format
= bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]];
867 av7110
->bmp_state
= BMP_LOADING
;
868 if (format
== OSD_BITMAP8
) {
870 } else if (format
== OSD_BITMAP4
) {
872 } else if (format
== OSD_BITMAP2
) {
874 } else if (format
== OSD_BITMAP1
) {
877 av7110
->bmp_state
= BMP_NONE
;
880 av7110
->bmplen
= ((dx
* dy
* bpp
+ 7) & ~7) / 8;
882 if (av7110
->bmplen
> 32768) {
883 av7110
->bmp_state
= BMP_NONE
;
886 for (i
= 0; i
< dy
; i
++) {
887 if (copy_from_user(av7110
->bmpbuf
+ 1024 + i
* dx
, data
+ i
* inc
, dx
)) {
888 av7110
->bmp_state
= BMP_NONE
;
892 if (format
!= OSD_BITMAP8
) {
893 for (i
= 0; i
< dx
* dy
/ delta
; i
++) {
894 c
= ((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ delta
- 1];
895 for (d
= delta
- 2; d
>= 0; d
--) {
896 c
|= (((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ d
]
897 << ((delta
- d
- 1) * bpp
));
898 ((u8
*)av7110
->bmpbuf
)[1024 + i
] = c
;
902 av7110
->bmplen
+= 1024;
903 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110
->bmplen
);
904 ret
= av7110_fw_cmd(av7110
, COMTYPE_OSD
, LoadBmp
, 3, format
, dx
, dy
);
906 ret
= WaitUntilBmpLoaded(av7110
);
910 static int BlitBitmap(struct av7110
*av7110
, u16 x
, u16 y
)
912 dprintk(4, "%p\n", av7110
);
914 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, BlitBmp
, 4, av7110
->osdwin
, x
, y
, 0);
917 static inline int ReleaseBitmap(struct av7110
*av7110
)
919 dprintk(4, "%p\n", av7110
);
921 if (av7110
->bmp_state
!= BMP_LOADED
&& FW_VERSION(av7110
->arm_app
) < 0x261e)
923 if (av7110
->bmp_state
== BMP_LOADING
)
924 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
925 av7110
->bmp_state
= BMP_NONE
;
926 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, ReleaseBmp
, 0);
929 static u32
RGB2YUV(u16 R
, u16 G
, u16 B
)
934 y
= R
* 77 + G
* 150 + B
* 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
935 u
= 2048 + B
* 8 -(y
>> 5); /* Cr 0..4095 */
936 v
= 2048 + R
* 8 -(y
>> 5); /* Cb 0..4095 */
942 return Cr
| (Cb
<< 16) | (Y
<< 8);
945 static int OSDSetColor(struct av7110
*av7110
, u8 color
, u8 r
, u8 g
, u8 b
, u8 blend
)
952 yuv
= blend
? RGB2YUV(r
,g
,b
) : 0;
954 ch
= ((yuv
>> 16) & 0xffff);
955 ret
= SetColor_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
958 ret
= SetBlend_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
959 color
, ((blend
>> 4) & 0x0f));
963 static int OSDSetPalette(struct av7110
*av7110
, u32 __user
* colors
, u8 first
, u8 last
)
966 int length
= last
- first
+ 1;
968 if (length
* 4 > DATA_BUFF3_SIZE
)
971 for (i
= 0; i
< length
; i
++) {
972 u32 color
, blend
, yuv
;
974 if (get_user(color
, colors
+ i
))
976 blend
= (color
& 0xF0000000) >> 4;
977 yuv
= blend
? RGB2YUV(color
& 0xFF, (color
>> 8) & 0xFF,
978 (color
>> 16) & 0xFF) | blend
: 0;
979 yuv
= ((yuv
& 0xFFFF0000) >> 16) | ((yuv
& 0x0000FFFF) << 16);
980 wdebi(av7110
, DEBINOSWAP
, DATA_BUFF3_BASE
+ i
* 4, yuv
, 4);
982 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Palette
, 4,
984 bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
988 static int OSDSetBlock(struct av7110
*av7110
, int x0
, int y0
,
989 int x1
, int y1
, int inc
, u8 __user
* data
)
991 uint w
, h
, bpp
, bpl
, size
, lpb
, bnum
, brest
;
999 if (w
<= 0 || w
> 720 || h
<= 0 || h
> 576)
1001 bpp
= av7110
->osdbpp
[av7110
->osdwin
] + 1;
1002 bpl
= ((w
* bpp
+ 7) & ~7) / 8;
1004 lpb
= (32 * 1024) / bpl
;
1005 bnum
= size
/ (lpb
* bpl
);
1006 brest
= size
- bnum
* lpb
* bpl
;
1008 if (av7110
->bmp_state
== BMP_LOADING
) {
1009 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1010 BUG_ON (FW_VERSION(av7110
->arm_app
) >= 0x261e);
1011 rc
= WaitUntilBmpLoaded(av7110
);
1014 /* just continue. This should work for all fw versions
1015 * if bnum==1 && !brest && LoadBitmap was successful
1020 for (i
= 0; i
< bnum
; i
++) {
1021 rc
= LoadBitmap(av7110
, w
, lpb
, inc
, data
);
1024 rc
= BlitBitmap(av7110
, x0
, y0
+ i
* lpb
);
1030 rc
= LoadBitmap(av7110
, w
, brest
/ bpl
, inc
, data
);
1032 rc
= BlitBitmap(av7110
, x0
, y0
+ bnum
* lpb
);
1034 release_rc
= ReleaseBitmap(av7110
);
1038 dprintk(1,"returns %d\n",rc
);
1042 int av7110_osd_cmd(struct av7110
*av7110
, osd_cmd_t
*dc
)
1046 if (mutex_lock_interruptible(&av7110
->osd_mutex
))
1047 return -ERESTARTSYS
;
1051 ret
= DestroyOSDWindow(av7110
, av7110
->osdwin
);
1054 av7110
->osdbpp
[av7110
->osdwin
] = (dc
->color
- 1) & 7;
1055 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
,
1056 bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]],
1057 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1061 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1064 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1068 ret
= MoveWindowRel(av7110
, av7110
->osdwin
, 0, 0);
1071 ret
= HideWindow(av7110
, av7110
->osdwin
);
1074 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, 0);
1077 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, dc
->color
);
1080 ret
= OSDSetColor(av7110
, dc
->color
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
);
1082 case OSD_SetPalette
:
1083 if (FW_VERSION(av7110
->arm_app
) >= 0x2618)
1084 ret
= OSDSetPalette(av7110
, dc
->data
, dc
->color
, dc
->x0
);
1086 int i
, len
= dc
->x0
-dc
->color
+1;
1087 u8 __user
*colors
= (u8 __user
*)dc
->data
;
1088 u8 r
, g
= 0, b
= 0, blend
= 0;
1090 for (i
= 0; i
<len
; i
++) {
1091 if (get_user(r
, colors
+ i
* 4) ||
1092 get_user(g
, colors
+ i
* 4 + 1) ||
1093 get_user(b
, colors
+ i
* 4 + 2) ||
1094 get_user(blend
, colors
+ i
* 4 + 3)) {
1098 ret
= OSDSetColor(av7110
, dc
->color
+ i
, r
, g
, b
, blend
);
1105 ret
= DrawLine(av7110
, av7110
->osdwin
,
1106 dc
->x0
, dc
->y0
, 0, 0, dc
->color
);
1112 ret
= OSDSetBlock(av7110
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
, dc
->color
, dc
->data
);
1115 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1116 dc
->x1
-dc
->x0
+1, dc
->y1
, dc
->color
);
1119 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1120 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1, dc
->color
);
1123 ret
= DrawLine(av7110
, av7110
->osdwin
,
1124 dc
->x0
, dc
->y0
, dc
->x1
- dc
->x0
, dc
->y1
- dc
->y0
, dc
->color
);
1130 if (strncpy_from_user(textbuf
, dc
->data
, 240) < 0) {
1137 ret
= SetFont(av7110
, av7110
->osdwin
, dc
->x1
,
1138 (u16
) (dc
->color
& 0xffff), (u16
) (dc
->color
>> 16));
1140 ret
= FlushText(av7110
);
1142 ret
= WriteText(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
, textbuf
);
1146 if (dc
->x0
< 1 || dc
->x0
> 7)
1149 av7110
->osdwin
= dc
->x0
;
1153 case OSD_MoveWindow
:
1154 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1156 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1159 if (dc
->color
< OSD_BITMAP1
|| dc
->color
> OSD_CURSOR
) {
1163 if (dc
->color
>= OSD_BITMAP1
&& dc
->color
<= OSD_BITMAP8HR
)
1164 av7110
->osdbpp
[av7110
->osdwin
] = (1 << (dc
->color
& 3)) - 1;
1166 av7110
->osdbpp
[av7110
->osdwin
] = 0;
1167 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
, (osd_raw_window_t
)dc
->color
,
1168 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1172 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1174 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1182 mutex_unlock(&av7110
->osd_mutex
);
1183 if (ret
==-ERESTARTSYS
)
1184 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc
->cmd
);
1186 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc
->cmd
,ret
);
1191 int av7110_osd_capability(struct av7110
*av7110
, osd_cap_t
*cap
)
1194 case OSD_CAP_MEMSIZE
:
1195 if (FW_4M_SDRAM(av7110
->arm_app
))
1204 #endif /* CONFIG_DVB_AV7110_OSD */