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"
43 /****************************************************************************
45 ****************************************************************************/
47 /* This DEBI code is based on the Stradis driver
48 by Nathan Laredo <laredo@gnu.org> */
50 int av7110_debiwrite(struct av7110
*av7110
, u32 config
,
51 int addr
, u32 val
, int count
)
53 struct saa7146_dev
*dev
= av7110
->dev
;
55 if (count
<= 0 || count
> 32764) {
56 printk("%s: invalid count %d\n", __func__
, count
);
59 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
60 printk("%s: wait_for_debi_done failed\n", __func__
);
63 saa7146_write(dev
, DEBI_CONFIG
, config
);
64 if (count
<= 4) /* immediate transfer */
65 saa7146_write(dev
, DEBI_AD
, val
);
66 else /* block transfer */
67 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
68 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | (addr
& 0xffff));
69 saa7146_write(dev
, MC2
, (2 << 16) | 2);
73 u32
av7110_debiread(struct av7110
*av7110
, u32 config
, int addr
, int count
)
75 struct saa7146_dev
*dev
= av7110
->dev
;
78 if (count
> 32764 || count
<= 0) {
79 printk("%s: invalid count %d\n", __func__
, count
);
82 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
83 printk("%s: wait_for_debi_done #1 failed\n", __func__
);
86 saa7146_write(dev
, DEBI_AD
, av7110
->debi_bus
);
87 saa7146_write(dev
, DEBI_COMMAND
, (count
<< 17) | 0x10000 | (addr
& 0xffff));
89 saa7146_write(dev
, DEBI_CONFIG
, config
);
90 saa7146_write(dev
, MC2
, (2 << 16) | 2);
93 if (saa7146_wait_for_debi_done(av7110
->dev
, 0) < 0) {
94 printk("%s: wait_for_debi_done #2 failed\n", __func__
);
98 result
= saa7146_read(dev
, DEBI_AD
);
99 result
&= (0xffffffffUL
>> ((4 - count
) * 8));
105 /* av7110 ARM core boot stuff */
107 void av7110_reset_arm(struct av7110
*av7110
)
109 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
111 /* Disable DEBI and GPIO irq */
112 SAA7146_IER_DISABLE(av7110
->dev
, MASK_19
| MASK_03
);
113 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
115 saa7146_setgpio(av7110
->dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
116 msleep(30); /* the firmware needs some time to initialize */
118 ARM_ResetMailBox(av7110
);
120 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
121 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
123 av7110
->arm_ready
= 1;
124 dprintk(1, "reset ARM\n");
128 static int waitdebi(struct av7110
*av7110
, int adr
, int state
)
132 dprintk(4, "%p\n", av7110
);
134 for (k
= 0; k
< 100; k
++) {
135 if (irdebi(av7110
, DEBINOSWAP
, adr
, 0, 2) == state
)
142 static int load_dram(struct av7110
*av7110
, u32
*data
, int len
)
146 u32 base
, bootblock
= AV7110_BOOT_BLOCK
;
148 dprintk(4, "%p\n", av7110
);
150 blocks
= len
/ AV7110_BOOT_MAX_SIZE
;
151 rest
= len
% AV7110_BOOT_MAX_SIZE
;
152 base
= DRAM_START_CODE
;
154 for (i
= 0; i
< blocks
; i
++) {
155 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
156 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at block %d\n", i
);
159 dprintk(4, "writing DRAM block %d\n", i
);
160 mwdebi(av7110
, DEBISWAB
, bootblock
,
161 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, AV7110_BOOT_MAX_SIZE
);
163 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
164 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, AV7110_BOOT_MAX_SIZE
, 2);
165 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
166 base
+= AV7110_BOOT_MAX_SIZE
;
170 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
171 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at last block\n");
175 mwdebi(av7110
, DEBISWAB
, bootblock
,
176 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, rest
);
178 mwdebi(av7110
, DEBISWAB
, bootblock
,
179 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
- 4, rest
+ 4);
181 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
182 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, rest
, 2);
183 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
185 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
186 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout after last block\n");
189 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, 0, 2);
190 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
191 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_AV7110_BOOT_COMPLETE
) < 0) {
192 printk(KERN_ERR
"dvb-ttpci: load_dram(): final handshake timeout\n");
199 /* we cannot write av7110 DRAM directly, so load a bootloader into
200 * the DPRAM which implements a simple boot protocol */
201 int av7110_bootarm(struct av7110
*av7110
)
203 const struct firmware
*fw
;
204 const char *fw_name
= "av7110/bootcode.bin";
205 struct saa7146_dev
*dev
= av7110
->dev
;
209 dprintk(4, "%p\n", av7110
);
211 av7110
->arm_ready
= 0;
213 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
215 /* Disable DEBI and GPIO irq */
216 SAA7146_IER_DISABLE(av7110
->dev
, MASK_03
| MASK_19
);
217 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
220 saa7146_write(av7110
->dev
, MC1
, 0x08800880);
221 saa7146_write(av7110
->dev
, DD1_STREAM_B
, 0x00000000);
222 saa7146_write(av7110
->dev
, MC2
, (MASK_09
| MASK_25
| MASK_10
| MASK_26
));
225 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
226 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
227 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
229 if ((ret
=irdebi(av7110
, DEBINOSWAP
, DPRAM_BASE
, 0, 4)) != 0x10325476) {
230 printk(KERN_ERR
"dvb-ttpci: debi test in av7110_bootarm() failed: "
231 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
235 for (i
= 0; i
< 8192; i
+= 4)
236 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
+ i
, 0x00, 4);
237 dprintk(2, "debi test OK\n");
240 dprintk(1, "load boot code\n");
241 saa7146_setgpio(dev
, ARM_IRQ_LINE
, SAA7146_GPIO_IRQLO
);
242 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
243 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
245 ret
= request_firmware(&fw
, fw_name
, &dev
->pci
->dev
);
247 printk(KERN_ERR
"dvb-ttpci: Failed to load firmware \"%s\"\n",
252 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, fw
->data
, fw
->size
);
253 release_firmware(fw
);
254 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
256 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
257 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
258 "saa7146_wait_for_debi_done() timed out\n");
261 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
264 dprintk(1, "load dram code\n");
265 if (load_dram(av7110
, (u32
*)av7110
->bin_root
, av7110
->size_root
) < 0) {
266 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
267 "load_dram() failed\n");
271 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
274 dprintk(1, "load dpram code\n");
275 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, av7110
->bin_dpram
, av7110
->size_dpram
);
277 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
278 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
279 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
282 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
283 msleep(30); /* the firmware needs some time to initialize */
285 //ARM_ClearIrq(av7110);
286 ARM_ResetMailBox(av7110
);
287 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
288 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
290 av7110
->arm_errors
= 0;
291 av7110
->arm_ready
= 1;
294 MODULE_FIRMWARE("av7110/bootcode.bin");
296 /****************************************************************************
297 * DEBI command polling
298 ****************************************************************************/
300 int av7110_wait_msgstate(struct av7110
*av7110
, u16 flags
)
306 if (FW_VERSION(av7110
->arm_app
) <= 0x261c) {
307 /* not supported by old firmware */
315 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
316 if (mutex_lock_interruptible(&av7110
->dcomlock
))
318 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
319 mutex_unlock(&av7110
->dcomlock
);
320 if ((stat
& flags
) == 0)
323 printk(KERN_ERR
"%s: timeout waiting for MSGSTATE %04x\n",
324 __func__
, stat
& flags
);
332 static int __av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
337 u16 flags
[2] = {0, 0};
341 // dprintk(4, "%p\n", av7110);
343 if (!av7110
->arm_ready
) {
344 dprintk(1, "arm not ready.\n");
350 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
351 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
354 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__
);
355 av7110
->arm_errors
++;
361 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
362 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0xffff, 2);
367 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
368 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
371 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__
);
378 switch ((buf
[0] >> 8) & 0xff) {
379 case COMTYPE_PIDFILTER
:
380 case COMTYPE_ENCODER
:
381 case COMTYPE_REC_PLAY
:
382 case COMTYPE_MPEGDECODER
:
393 if (FW_VERSION(av7110
->arm_app
) >= 0x261d) {
404 /* non-immediate COMMAND type */
407 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
408 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
409 if (stat
& flags
[0]) {
410 printk(KERN_ERR
"%s: %s QUEUE overflow\n",
414 if ((stat
& flags
[1]) == 0)
417 printk(KERN_ERR
"%s: timeout waiting on busy %s QUEUE\n",
419 av7110
->arm_errors
++;
426 for (i
= 2; i
< length
; i
++)
427 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2 * i
, (u32
) buf
[i
], 2);
430 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, (u32
) buf
[1], 2);
432 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, 0, 2);
434 wdebi(av7110
, DEBINOSWAP
, COMMAND
, (u32
) buf
[0], 2);
436 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
437 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0x0000, 2);
442 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
443 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
446 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
447 __func__
, (buf
[0] >> 8) & 0xff);
453 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
454 if (stat
& GPMQOver
) {
455 printk(KERN_ERR
"dvb-ttpci: %s(): GPMQOver\n", __func__
);
458 else if (stat
& OSDQOver
) {
459 printk(KERN_ERR
"dvb-ttpci: %s(): OSDQOver\n", __func__
);
467 static int av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
471 // dprintk(4, "%p\n", av7110);
473 if (!av7110
->arm_ready
) {
474 dprintk(1, "arm not ready.\n");
477 if (mutex_lock_interruptible(&av7110
->dcomlock
))
480 ret
= __av7110_send_fw_cmd(av7110
, buf
, length
);
481 mutex_unlock(&av7110
->dcomlock
);
482 if (ret
&& ret
!=-ERESTARTSYS
)
483 printk(KERN_ERR
"dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
488 int av7110_fw_cmd(struct av7110
*av7110
, int type
, int com
, int num
, ...)
494 // dprintk(4, "%p\n", av7110);
496 buf
[0] = ((type
<< 8) | com
);
501 for (i
= 0; i
< num
; i
++)
502 buf
[i
+ 2] = va_arg(args
, u32
);
506 ret
= av7110_send_fw_cmd(av7110
, buf
, num
+ 2);
507 if (ret
&& ret
!= -ERESTARTSYS
)
508 printk(KERN_ERR
"dvb-ttpci: av7110_fw_cmd error %d\n", ret
);
513 int av7110_send_ci_cmd(struct av7110
*av7110
, u8 subcom
, u8
*buf
, u8 len
)
516 u16 cmd
[18] = { ((COMTYPE_COMMON_IF
<< 8) + subcom
),
517 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
519 dprintk(4, "%p\n", av7110
);
521 for(i
= 0; i
< len
&& i
< 32; i
++)
524 cmd
[(i
/ 2) + 2] = (u16
)(buf
[i
]) << 8;
526 cmd
[(i
/ 2) + 2] |= buf
[i
];
529 ret
= av7110_send_fw_cmd(av7110
, cmd
, 18);
530 if (ret
&& ret
!= -ERESTARTSYS
)
531 printk(KERN_ERR
"dvb-ttpci: av7110_send_ci_cmd error %d\n", ret
);
536 int av7110_fw_request(struct av7110
*av7110
, u16
*request_buf
,
537 int request_buf_len
, u16
*reply_buf
, int reply_buf_len
)
546 dprintk(4, "%p\n", av7110
);
548 if (!av7110
->arm_ready
) {
549 dprintk(1, "arm not ready.\n");
553 if (mutex_lock_interruptible(&av7110
->dcomlock
))
556 if ((err
= __av7110_send_fw_cmd(av7110
, request_buf
, request_buf_len
)) < 0) {
557 mutex_unlock(&av7110
->dcomlock
);
558 printk(KERN_ERR
"dvb-ttpci: av7110_fw_request error %d\n", err
);
564 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
565 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
568 printk(KERN_ERR
"%s: timeout waiting for COMMAND to complete\n", __func__
);
569 mutex_unlock(&av7110
->dcomlock
);
580 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
581 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
584 printk(KERN_ERR
"%s: timeout waiting for HANDSHAKE_REG\n", __func__
);
585 mutex_unlock(&av7110
->dcomlock
);
593 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
594 if (stat
& GPMQOver
) {
595 printk(KERN_ERR
"%s: GPMQOver\n", __func__
);
596 mutex_unlock(&av7110
->dcomlock
);
599 else if (stat
& OSDQOver
) {
600 printk(KERN_ERR
"%s: OSDQOver\n", __func__
);
601 mutex_unlock(&av7110
->dcomlock
);
606 for (i
= 0; i
< reply_buf_len
; i
++)
607 reply_buf
[i
] = rdebi(av7110
, DEBINOSWAP
, COM_BUFF
+ 2 * i
, 0, 2);
609 mutex_unlock(&av7110
->dcomlock
);
613 static int av7110_fw_query(struct av7110
*av7110
, u16 tag
, u16
* buf
, s16 length
)
616 ret
= av7110_fw_request(av7110
, &tag
, 0, buf
, length
);
618 printk(KERN_ERR
"dvb-ttpci: av7110_fw_query error %d\n", ret
);
623 /****************************************************************************
625 ****************************************************************************/
627 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
628 int av7110_firmversion(struct av7110
*av7110
)
631 u16 tag
= ((COMTYPE_REQUEST
<< 8) + ReqVersion
);
633 dprintk(4, "%p\n", av7110
);
635 if (av7110_fw_query(av7110
, tag
, buf
, 16)) {
636 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
637 av7110
->dvb_adapter
.num
);
641 av7110
->arm_fw
= (buf
[0] << 16) + buf
[1];
642 av7110
->arm_rtsl
= (buf
[2] << 16) + buf
[3];
643 av7110
->arm_vid
= (buf
[4] << 16) + buf
[5];
644 av7110
->arm_app
= (buf
[6] << 16) + buf
[7];
645 av7110
->avtype
= (buf
[8] << 16) + buf
[9];
647 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
648 av7110
->dvb_adapter
.num
, av7110
->arm_fw
,
649 av7110
->arm_rtsl
, av7110
->arm_vid
, av7110
->arm_app
);
651 /* print firmware capabilities */
652 if (FW_CI_LL_SUPPORT(av7110
->arm_app
))
653 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
654 av7110
->dvb_adapter
.num
);
656 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
657 av7110
->dvb_adapter
.num
);
663 int av7110_diseqc_send(struct av7110
*av7110
, int len
, u8
*msg
, unsigned long burst
)
666 u16 buf
[18] = { ((COMTYPE_AUDIODAC
<< 8) + SendDiSEqC
),
667 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
669 dprintk(4, "%p\n", av7110
);
678 buf
[3] = burst
? 0x01 : 0x00;
682 for (i
= 0; i
< len
; i
++)
685 ret
= av7110_send_fw_cmd(av7110
, buf
, 18);
686 if (ret
&& ret
!=-ERESTARTSYS
)
687 printk(KERN_ERR
"dvb-ttpci: av7110_diseqc_send error %d\n", ret
);
692 #ifdef CONFIG_DVB_AV7110_OSD
694 static inline int SetColorBlend(struct av7110
*av7110
, u8 windownr
)
696 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetCBlend
, 1, windownr
);
699 static inline int SetBlend_(struct av7110
*av7110
, u8 windownr
,
700 enum av7110_osd_palette_type colordepth
, u16 index
, u8 blending
)
702 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetBlend
, 4,
703 windownr
, colordepth
, index
, blending
);
706 static inline int SetColor_(struct av7110
*av7110
, u8 windownr
,
707 enum av7110_osd_palette_type colordepth
, u16 index
, u16 colorhi
, u16 colorlo
)
709 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetColor
, 5,
710 windownr
, colordepth
, index
, colorhi
, colorlo
);
713 static inline int SetFont(struct av7110
*av7110
, u8 windownr
, u8 fontsize
,
714 u16 colorfg
, u16 colorbg
)
716 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Font
, 4,
717 windownr
, fontsize
, colorfg
, colorbg
);
720 static int FlushText(struct av7110
*av7110
)
725 if (mutex_lock_interruptible(&av7110
->dcomlock
))
729 err
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
730 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
733 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
735 mutex_unlock(&av7110
->dcomlock
);
740 mutex_unlock(&av7110
->dcomlock
);
744 static int WriteText(struct av7110
*av7110
, u8 win
, u16 x
, u16 y
, char *buf
)
748 int length
= strlen(buf
) + 1;
749 u16 cbuf
[5] = { (COMTYPE_OSD
<< 8) + DText
, 3, win
, x
, y
};
751 if (mutex_lock_interruptible(&av7110
->dcomlock
))
756 ret
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
757 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
760 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
762 mutex_unlock(&av7110
->dcomlock
);
770 ret
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
771 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
774 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
776 mutex_unlock(&av7110
->dcomlock
);
782 for (i
= 0; i
< length
/ 2; i
++)
783 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2,
784 swab16(*(u16
*)(buf
+ 2 * i
)), 2);
786 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2, 0, 2);
787 ret
= __av7110_send_fw_cmd(av7110
, cbuf
, 5);
788 mutex_unlock(&av7110
->dcomlock
);
789 if (ret
&& ret
!=-ERESTARTSYS
)
790 printk(KERN_ERR
"dvb-ttpci: WriteText error %d\n", ret
);
794 static inline int DrawLine(struct av7110
*av7110
, u8 windownr
,
795 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
797 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DLine
, 6,
798 windownr
, x
, y
, dx
, dy
, color
);
801 static inline int DrawBlock(struct av7110
*av7110
, u8 windownr
,
802 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
804 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DBox
, 6,
805 windownr
, x
, y
, dx
, dy
, color
);
808 static inline int HideWindow(struct av7110
*av7110
, u8 windownr
)
810 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WHide
, 1, windownr
);
813 static inline int MoveWindowRel(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
815 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveD
, 3, windownr
, x
, y
);
818 static inline int MoveWindowAbs(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
820 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveA
, 3, windownr
, x
, y
);
823 static inline int DestroyOSDWindow(struct av7110
*av7110
, u8 windownr
)
825 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WDestroy
, 1, windownr
);
828 static inline int CreateOSDWindow(struct av7110
*av7110
, u8 windownr
,
829 osd_raw_window_t disptype
,
830 u16 width
, u16 height
)
832 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WCreate
, 4,
833 windownr
, disptype
, width
, height
);
837 static enum av7110_osd_palette_type bpp2pal
[8] = {
838 Pal1Bit
, Pal2Bit
, 0, Pal4Bit
, 0, 0, 0, Pal8Bit
840 static osd_raw_window_t bpp2bit
[8] = {
841 OSD_BITMAP1
, OSD_BITMAP2
, 0, OSD_BITMAP4
, 0, 0, 0, OSD_BITMAP8
844 static inline int WaitUntilBmpLoaded(struct av7110
*av7110
)
846 int ret
= wait_event_timeout(av7110
->bmpq
,
847 av7110
->bmp_state
!= BMP_LOADING
, 10*HZ
);
849 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
850 ret
, av7110
->bmp_state
);
851 av7110
->bmp_state
= BMP_NONE
;
857 static inline int LoadBitmap(struct av7110
*av7110
,
858 u16 dx
, u16 dy
, int inc
, u8 __user
* data
)
867 dprintk(4, "%p\n", av7110
);
869 format
= bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]];
871 av7110
->bmp_state
= BMP_LOADING
;
872 if (format
== OSD_BITMAP8
) {
874 } else if (format
== OSD_BITMAP4
) {
876 } else if (format
== OSD_BITMAP2
) {
878 } else if (format
== OSD_BITMAP1
) {
881 av7110
->bmp_state
= BMP_NONE
;
884 av7110
->bmplen
= ((dx
* dy
* bpp
+ 7) & ~7) / 8;
886 if (av7110
->bmplen
> 32768) {
887 av7110
->bmp_state
= BMP_NONE
;
890 for (i
= 0; i
< dy
; i
++) {
891 if (copy_from_user(av7110
->bmpbuf
+ 1024 + i
* dx
, data
+ i
* inc
, dx
)) {
892 av7110
->bmp_state
= BMP_NONE
;
896 if (format
!= OSD_BITMAP8
) {
897 for (i
= 0; i
< dx
* dy
/ delta
; i
++) {
898 c
= ((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ delta
- 1];
899 for (d
= delta
- 2; d
>= 0; d
--) {
900 c
|= (((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ d
]
901 << ((delta
- d
- 1) * bpp
));
902 ((u8
*)av7110
->bmpbuf
)[1024 + i
] = c
;
906 av7110
->bmplen
+= 1024;
907 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110
->bmplen
);
908 ret
= av7110_fw_cmd(av7110
, COMTYPE_OSD
, LoadBmp
, 3, format
, dx
, dy
);
910 ret
= WaitUntilBmpLoaded(av7110
);
914 static int BlitBitmap(struct av7110
*av7110
, u16 x
, u16 y
)
916 dprintk(4, "%p\n", av7110
);
918 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, BlitBmp
, 4, av7110
->osdwin
, x
, y
, 0);
921 static inline int ReleaseBitmap(struct av7110
*av7110
)
923 dprintk(4, "%p\n", av7110
);
925 if (av7110
->bmp_state
!= BMP_LOADED
&& FW_VERSION(av7110
->arm_app
) < 0x261e)
927 if (av7110
->bmp_state
== BMP_LOADING
)
928 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
929 av7110
->bmp_state
= BMP_NONE
;
930 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, ReleaseBmp
, 0);
933 static u32
RGB2YUV(u16 R
, u16 G
, u16 B
)
938 y
= R
* 77 + G
* 150 + B
* 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
939 u
= 2048 + B
* 8 -(y
>> 5); /* Cr 0..4095 */
940 v
= 2048 + R
* 8 -(y
>> 5); /* Cb 0..4095 */
946 return Cr
| (Cb
<< 16) | (Y
<< 8);
949 static int OSDSetColor(struct av7110
*av7110
, u8 color
, u8 r
, u8 g
, u8 b
, u8 blend
)
956 yuv
= blend
? RGB2YUV(r
,g
,b
) : 0;
958 ch
= ((yuv
>> 16) & 0xffff);
959 ret
= SetColor_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
962 ret
= SetBlend_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
963 color
, ((blend
>> 4) & 0x0f));
967 static int OSDSetPalette(struct av7110
*av7110
, u32 __user
* colors
, u8 first
, u8 last
)
970 int length
= last
- first
+ 1;
972 if (length
* 4 > DATA_BUFF3_SIZE
)
975 for (i
= 0; i
< length
; i
++) {
976 u32 color
, blend
, yuv
;
978 if (get_user(color
, colors
+ i
))
980 blend
= (color
& 0xF0000000) >> 4;
981 yuv
= blend
? RGB2YUV(color
& 0xFF, (color
>> 8) & 0xFF,
982 (color
>> 16) & 0xFF) | blend
: 0;
983 yuv
= ((yuv
& 0xFFFF0000) >> 16) | ((yuv
& 0x0000FFFF) << 16);
984 wdebi(av7110
, DEBINOSWAP
, DATA_BUFF3_BASE
+ i
* 4, yuv
, 4);
986 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Palette
, 4,
988 bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
992 static int OSDSetBlock(struct av7110
*av7110
, int x0
, int y0
,
993 int x1
, int y1
, int inc
, u8 __user
* data
)
995 uint w
, h
, bpp
, bpl
, size
, lpb
, bnum
, brest
;
1003 if (w
<= 0 || w
> 720 || h
<= 0 || h
> 576)
1005 bpp
= av7110
->osdbpp
[av7110
->osdwin
] + 1;
1006 bpl
= ((w
* bpp
+ 7) & ~7) / 8;
1008 lpb
= (32 * 1024) / bpl
;
1009 bnum
= size
/ (lpb
* bpl
);
1010 brest
= size
- bnum
* lpb
* bpl
;
1012 if (av7110
->bmp_state
== BMP_LOADING
) {
1013 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
1014 BUG_ON (FW_VERSION(av7110
->arm_app
) >= 0x261e);
1015 rc
= WaitUntilBmpLoaded(av7110
);
1018 /* just continue. This should work for all fw versions
1019 * if bnum==1 && !brest && LoadBitmap was successful
1024 for (i
= 0; i
< bnum
; i
++) {
1025 rc
= LoadBitmap(av7110
, w
, lpb
, inc
, data
);
1028 rc
= BlitBitmap(av7110
, x0
, y0
+ i
* lpb
);
1034 rc
= LoadBitmap(av7110
, w
, brest
/ bpl
, inc
, data
);
1036 rc
= BlitBitmap(av7110
, x0
, y0
+ bnum
* lpb
);
1038 release_rc
= ReleaseBitmap(av7110
);
1042 dprintk(1,"returns %d\n",rc
);
1046 int av7110_osd_cmd(struct av7110
*av7110
, osd_cmd_t
*dc
)
1050 if (mutex_lock_interruptible(&av7110
->osd_mutex
))
1051 return -ERESTARTSYS
;
1055 ret
= DestroyOSDWindow(av7110
, av7110
->osdwin
);
1058 av7110
->osdbpp
[av7110
->osdwin
] = (dc
->color
- 1) & 7;
1059 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
,
1060 bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]],
1061 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1065 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1068 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1072 ret
= MoveWindowRel(av7110
, av7110
->osdwin
, 0, 0);
1075 ret
= HideWindow(av7110
, av7110
->osdwin
);
1078 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, 0);
1081 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, dc
->color
);
1084 ret
= OSDSetColor(av7110
, dc
->color
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
);
1086 case OSD_SetPalette
:
1087 if (FW_VERSION(av7110
->arm_app
) >= 0x2618)
1088 ret
= OSDSetPalette(av7110
, dc
->data
, dc
->color
, dc
->x0
);
1090 int i
, len
= dc
->x0
-dc
->color
+1;
1091 u8 __user
*colors
= (u8 __user
*)dc
->data
;
1092 u8 r
, g
= 0, b
= 0, blend
= 0;
1094 for (i
= 0; i
<len
; i
++) {
1095 if (get_user(r
, colors
+ i
* 4) ||
1096 get_user(g
, colors
+ i
* 4 + 1) ||
1097 get_user(b
, colors
+ i
* 4 + 2) ||
1098 get_user(blend
, colors
+ i
* 4 + 3)) {
1102 ret
= OSDSetColor(av7110
, dc
->color
+ i
, r
, g
, b
, blend
);
1109 ret
= DrawLine(av7110
, av7110
->osdwin
,
1110 dc
->x0
, dc
->y0
, 0, 0, dc
->color
);
1116 ret
= OSDSetBlock(av7110
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
, dc
->color
, dc
->data
);
1119 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1120 dc
->x1
-dc
->x0
+1, dc
->y1
, dc
->color
);
1123 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1124 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1, dc
->color
);
1127 ret
= DrawLine(av7110
, av7110
->osdwin
,
1128 dc
->x0
, dc
->y0
, dc
->x1
- dc
->x0
, dc
->y1
- dc
->y0
, dc
->color
);
1134 if (strncpy_from_user(textbuf
, dc
->data
, 240) < 0) {
1141 ret
= SetFont(av7110
, av7110
->osdwin
, dc
->x1
,
1142 (u16
) (dc
->color
& 0xffff), (u16
) (dc
->color
>> 16));
1144 ret
= FlushText(av7110
);
1146 ret
= WriteText(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
, textbuf
);
1150 if (dc
->x0
< 1 || dc
->x0
> 7)
1153 av7110
->osdwin
= dc
->x0
;
1157 case OSD_MoveWindow
:
1158 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1160 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1163 if (dc
->color
< OSD_BITMAP1
|| dc
->color
> OSD_CURSOR
) {
1167 if (dc
->color
>= OSD_BITMAP1
&& dc
->color
<= OSD_BITMAP8HR
)
1168 av7110
->osdbpp
[av7110
->osdwin
] = (1 << (dc
->color
& 3)) - 1;
1170 av7110
->osdbpp
[av7110
->osdwin
] = 0;
1171 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
, (osd_raw_window_t
)dc
->color
,
1172 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1176 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1178 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1186 mutex_unlock(&av7110
->osd_mutex
);
1187 if (ret
==-ERESTARTSYS
)
1188 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc
->cmd
);
1190 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc
->cmd
,ret
);
1195 int av7110_osd_capability(struct av7110
*av7110
, osd_cap_t
*cap
)
1198 case OSD_CAP_MEMSIZE
:
1199 if (FW_4M_SDRAM(av7110
->arm_app
))
1208 #endif /* CONFIG_DVB_AV7110_OSD */