2 * av7110_hw.c: av7110 low level hardware access and firmware interface
4 * Copyright (C) 1999-2002 Ralph Metzler
5 * & Marcus Metzler for convergence integrated media GmbH
7 * originally based on code by:
8 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
25 * the project's page is at http://www.linuxtv.org/dvb/
28 /* for debugging ARM communication: */
32 #include <linux/types.h>
33 #include <linux/kernel.h>
34 #include <linux/string.h>
35 #include <linux/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 static int waitdebi(struct av7110
*av7110
, int adr
, int state
)
111 dprintk(4, "%p\n", av7110
);
113 for (k
= 0; k
< 100; k
++) {
114 if (irdebi(av7110
, DEBINOSWAP
, adr
, 0, 2) == state
)
121 static int load_dram(struct av7110
*av7110
, u32
*data
, int len
)
125 u32 base
, bootblock
= AV7110_BOOT_BLOCK
;
127 dprintk(4, "%p\n", av7110
);
129 blocks
= len
/ AV7110_BOOT_MAX_SIZE
;
130 rest
= len
% AV7110_BOOT_MAX_SIZE
;
131 base
= DRAM_START_CODE
;
133 for (i
= 0; i
< blocks
; i
++) {
134 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
135 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at block %d\n", i
);
138 dprintk(4, "writing DRAM block %d\n", i
);
139 mwdebi(av7110
, DEBISWAB
, bootblock
,
140 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, AV7110_BOOT_MAX_SIZE
);
142 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
143 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, AV7110_BOOT_MAX_SIZE
, 2);
144 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
145 base
+= AV7110_BOOT_MAX_SIZE
;
149 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
150 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout at last block\n");
154 mwdebi(av7110
, DEBISWAB
, bootblock
,
155 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
, rest
);
157 mwdebi(av7110
, DEBISWAB
, bootblock
,
158 ((u8
*)data
) + i
* AV7110_BOOT_MAX_SIZE
- 4, rest
+ 4);
160 iwdebi(av7110
, DEBISWAB
, AV7110_BOOT_BASE
, swab32(base
), 4);
161 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, rest
, 2);
162 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
164 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_EMPTY
) < 0) {
165 printk(KERN_ERR
"dvb-ttpci: load_dram(): timeout after last block\n");
168 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_SIZE
, 0, 2);
169 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
170 if (waitdebi(av7110
, AV7110_BOOT_STATE
, BOOTSTATE_AV7110_BOOT_COMPLETE
) < 0) {
171 printk(KERN_ERR
"dvb-ttpci: load_dram(): final handshake timeout\n");
178 /* we cannot write av7110 DRAM directly, so load a bootloader into
179 * the DPRAM which implements a simple boot protocol */
180 int av7110_bootarm(struct av7110
*av7110
)
182 const struct firmware
*fw
;
183 const char *fw_name
= "av7110/bootcode.bin";
184 struct saa7146_dev
*dev
= av7110
->dev
;
188 dprintk(4, "%p\n", av7110
);
190 av7110
->arm_ready
= 0;
192 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
194 /* Disable DEBI and GPIO irq */
195 SAA7146_IER_DISABLE(av7110
->dev
, MASK_03
| MASK_19
);
196 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
199 saa7146_write(av7110
->dev
, MC1
, 0x08800880);
200 saa7146_write(av7110
->dev
, DD1_STREAM_B
, 0x00000000);
201 saa7146_write(av7110
->dev
, MC2
, (MASK_09
| MASK_25
| MASK_10
| MASK_26
));
204 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
205 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
, 0x76543210, 4);
207 if ((ret
=irdebi(av7110
, DEBINOSWAP
, DPRAM_BASE
, 0, 4)) != 0x10325476) {
208 printk(KERN_ERR
"dvb-ttpci: debi test in av7110_bootarm() failed: "
209 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
213 for (i
= 0; i
< 8192; i
+= 4)
214 iwdebi(av7110
, DEBISWAP
, DPRAM_BASE
+ i
, 0x00, 4);
215 dprintk(2, "debi test OK\n");
218 dprintk(1, "load boot code\n");
219 saa7146_setgpio(dev
, ARM_IRQ_LINE
, SAA7146_GPIO_IRQLO
);
220 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
221 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
223 ret
= request_firmware(&fw
, fw_name
, &dev
->pci
->dev
);
225 printk(KERN_ERR
"dvb-ttpci: Failed to load firmware \"%s\"\n",
230 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, fw
->data
, fw
->size
);
231 release_firmware(fw
);
232 iwdebi(av7110
, DEBINOSWAP
, AV7110_BOOT_STATE
, BOOTSTATE_BUFFER_FULL
, 2);
234 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
235 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
236 "saa7146_wait_for_debi_done() timed out\n");
239 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
242 dprintk(1, "load dram code\n");
243 if (load_dram(av7110
, (u32
*)av7110
->bin_root
, av7110
->size_root
) < 0) {
244 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
245 "load_dram() failed\n");
249 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTLO
);
252 dprintk(1, "load dpram code\n");
253 mwdebi(av7110
, DEBISWAB
, DPRAM_BASE
, av7110
->bin_dpram
, av7110
->size_dpram
);
255 if (saa7146_wait_for_debi_done(av7110
->dev
, 1)) {
256 printk(KERN_ERR
"dvb-ttpci: av7110_bootarm(): "
257 "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
260 saa7146_setgpio(dev
, RESET_LINE
, SAA7146_GPIO_OUTHI
);
261 msleep(30); /* the firmware needs some time to initialize */
263 //ARM_ClearIrq(av7110);
264 ARM_ResetMailBox(av7110
);
265 SAA7146_ISR_CLEAR(av7110
->dev
, MASK_19
| MASK_03
);
266 SAA7146_IER_ENABLE(av7110
->dev
, MASK_03
);
268 av7110
->arm_errors
= 0;
269 av7110
->arm_ready
= 1;
272 MODULE_FIRMWARE("av7110/bootcode.bin");
274 /****************************************************************************
275 * DEBI command polling
276 ****************************************************************************/
278 int av7110_wait_msgstate(struct av7110
*av7110
, u16 flags
)
284 if (FW_VERSION(av7110
->arm_app
) <= 0x261c) {
285 /* not supported by old firmware */
293 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
294 if (mutex_lock_interruptible(&av7110
->dcomlock
))
296 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
297 mutex_unlock(&av7110
->dcomlock
);
298 if ((stat
& flags
) == 0)
301 printk(KERN_ERR
"%s: timeout waiting for MSGSTATE %04x\n",
302 __func__
, stat
& flags
);
310 static int __av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
315 u16 flags
[2] = {0, 0};
319 // dprintk(4, "%p\n", av7110);
321 if (!av7110
->arm_ready
) {
322 dprintk(1, "arm not ready.\n");
328 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
329 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
332 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__
);
333 av7110
->arm_errors
++;
339 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
340 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0xffff, 2);
345 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
346 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
349 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__
);
356 switch ((buf
[0] >> 8) & 0xff) {
357 case COMTYPE_PIDFILTER
:
358 case COMTYPE_ENCODER
:
359 case COMTYPE_REC_PLAY
:
360 case COMTYPE_MPEGDECODER
:
371 if (FW_VERSION(av7110
->arm_app
) >= 0x261d) {
382 /* non-immediate COMMAND type */
385 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
386 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
387 if (stat
& flags
[0]) {
388 printk(KERN_ERR
"%s: %s QUEUE overflow\n",
392 if ((stat
& flags
[1]) == 0)
395 printk(KERN_ERR
"%s: timeout waiting on busy %s QUEUE\n",
397 av7110
->arm_errors
++;
404 for (i
= 2; i
< length
; i
++)
405 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2 * i
, (u32
) buf
[i
], 2);
408 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, (u32
) buf
[1], 2);
410 wdebi(av7110
, DEBINOSWAP
, COMMAND
+ 2, 0, 2);
412 wdebi(av7110
, DEBINOSWAP
, COMMAND
, (u32
) buf
[0], 2);
414 if (FW_VERSION(av7110
->arm_app
) <= 0x261f)
415 wdebi(av7110
, DEBINOSWAP
, COM_IF_LOCK
, 0x0000, 2);
420 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
421 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
424 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
425 __func__
, (buf
[0] >> 8) & 0xff);
431 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
432 if (stat
& GPMQOver
) {
433 printk(KERN_ERR
"dvb-ttpci: %s(): GPMQOver\n", __func__
);
436 else if (stat
& OSDQOver
) {
437 printk(KERN_ERR
"dvb-ttpci: %s(): OSDQOver\n", __func__
);
445 static int av7110_send_fw_cmd(struct av7110
*av7110
, u16
* buf
, int length
)
449 // dprintk(4, "%p\n", av7110);
451 if (!av7110
->arm_ready
) {
452 dprintk(1, "arm not ready.\n");
455 if (mutex_lock_interruptible(&av7110
->dcomlock
))
458 ret
= __av7110_send_fw_cmd(av7110
, buf
, length
);
459 mutex_unlock(&av7110
->dcomlock
);
460 if (ret
&& ret
!=-ERESTARTSYS
)
461 printk(KERN_ERR
"dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
466 int av7110_fw_cmd(struct av7110
*av7110
, int type
, int com
, int num
, ...)
472 // dprintk(4, "%p\n", av7110);
474 buf
[0] = ((type
<< 8) | com
);
479 for (i
= 0; i
< num
; i
++)
480 buf
[i
+ 2] = va_arg(args
, u32
);
484 ret
= av7110_send_fw_cmd(av7110
, buf
, num
+ 2);
485 if (ret
&& ret
!= -ERESTARTSYS
)
486 printk(KERN_ERR
"dvb-ttpci: av7110_fw_cmd error %d\n", ret
);
491 int av7110_fw_request(struct av7110
*av7110
, u16
*request_buf
,
492 int request_buf_len
, u16
*reply_buf
, int reply_buf_len
)
501 dprintk(4, "%p\n", av7110
);
503 if (!av7110
->arm_ready
) {
504 dprintk(1, "arm not ready.\n");
508 if (mutex_lock_interruptible(&av7110
->dcomlock
))
511 if ((err
= __av7110_send_fw_cmd(av7110
, request_buf
, request_buf_len
)) < 0) {
512 mutex_unlock(&av7110
->dcomlock
);
513 printk(KERN_ERR
"dvb-ttpci: av7110_fw_request error %d\n", err
);
519 err
= time_after(jiffies
, start
+ ARM_WAIT_FREE
);
520 if (rdebi(av7110
, DEBINOSWAP
, COMMAND
, 0, 2) == 0)
523 printk(KERN_ERR
"%s: timeout waiting for COMMAND to complete\n", __func__
);
524 mutex_unlock(&av7110
->dcomlock
);
535 err
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
536 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
539 printk(KERN_ERR
"%s: timeout waiting for HANDSHAKE_REG\n", __func__
);
540 mutex_unlock(&av7110
->dcomlock
);
548 stat
= rdebi(av7110
, DEBINOSWAP
, MSGSTATE
, 0, 2);
549 if (stat
& GPMQOver
) {
550 printk(KERN_ERR
"%s: GPMQOver\n", __func__
);
551 mutex_unlock(&av7110
->dcomlock
);
554 else if (stat
& OSDQOver
) {
555 printk(KERN_ERR
"%s: OSDQOver\n", __func__
);
556 mutex_unlock(&av7110
->dcomlock
);
561 for (i
= 0; i
< reply_buf_len
; i
++)
562 reply_buf
[i
] = rdebi(av7110
, DEBINOSWAP
, COM_BUFF
+ 2 * i
, 0, 2);
564 mutex_unlock(&av7110
->dcomlock
);
568 static int av7110_fw_query(struct av7110
*av7110
, u16 tag
, u16
* buf
, s16 length
)
571 ret
= av7110_fw_request(av7110
, &tag
, 0, buf
, length
);
573 printk(KERN_ERR
"dvb-ttpci: av7110_fw_query error %d\n", ret
);
578 /****************************************************************************
580 ****************************************************************************/
582 /* get version of the firmware ROM, RTSL, video ucode and ARM application */
583 int av7110_firmversion(struct av7110
*av7110
)
586 u16 tag
= ((COMTYPE_REQUEST
<< 8) + ReqVersion
);
588 dprintk(4, "%p\n", av7110
);
590 if (av7110_fw_query(av7110
, tag
, buf
, 16)) {
591 printk("dvb-ttpci: failed to boot firmware @ card %d\n",
592 av7110
->dvb_adapter
.num
);
596 av7110
->arm_fw
= (buf
[0] << 16) + buf
[1];
597 av7110
->arm_rtsl
= (buf
[2] << 16) + buf
[3];
598 av7110
->arm_vid
= (buf
[4] << 16) + buf
[5];
599 av7110
->arm_app
= (buf
[6] << 16) + buf
[7];
600 av7110
->avtype
= (buf
[8] << 16) + buf
[9];
602 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
603 av7110
->dvb_adapter
.num
, av7110
->arm_fw
,
604 av7110
->arm_rtsl
, av7110
->arm_vid
, av7110
->arm_app
);
606 /* print firmware capabilities */
607 if (FW_CI_LL_SUPPORT(av7110
->arm_app
))
608 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
609 av7110
->dvb_adapter
.num
);
611 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
612 av7110
->dvb_adapter
.num
);
618 int av7110_diseqc_send(struct av7110
*av7110
, int len
, u8
*msg
, unsigned long burst
)
621 u16 buf
[18] = { ((COMTYPE_AUDIODAC
<< 8) + SendDiSEqC
),
622 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
624 dprintk(4, "%p\n", av7110
);
633 buf
[3] = burst
? 0x01 : 0x00;
637 for (i
= 0; i
< len
; i
++)
640 ret
= av7110_send_fw_cmd(av7110
, buf
, 18);
641 if (ret
&& ret
!=-ERESTARTSYS
)
642 printk(KERN_ERR
"dvb-ttpci: av7110_diseqc_send error %d\n", ret
);
647 #ifdef CONFIG_DVB_AV7110_OSD
649 static inline int SetColorBlend(struct av7110
*av7110
, u8 windownr
)
651 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetCBlend
, 1, windownr
);
654 static inline int SetBlend_(struct av7110
*av7110
, u8 windownr
,
655 enum av7110_osd_palette_type colordepth
, u16 index
, u8 blending
)
657 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetBlend
, 4,
658 windownr
, colordepth
, index
, blending
);
661 static inline int SetColor_(struct av7110
*av7110
, u8 windownr
,
662 enum av7110_osd_palette_type colordepth
, u16 index
, u16 colorhi
, u16 colorlo
)
664 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, SetColor
, 5,
665 windownr
, colordepth
, index
, colorhi
, colorlo
);
668 static inline int SetFont(struct av7110
*av7110
, u8 windownr
, u8 fontsize
,
669 u16 colorfg
, u16 colorbg
)
671 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Font
, 4,
672 windownr
, fontsize
, colorfg
, colorbg
);
675 static int FlushText(struct av7110
*av7110
)
680 if (mutex_lock_interruptible(&av7110
->dcomlock
))
684 err
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
685 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
688 printk(KERN_ERR
"dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
690 mutex_unlock(&av7110
->dcomlock
);
695 mutex_unlock(&av7110
->dcomlock
);
699 static int WriteText(struct av7110
*av7110
, u8 win
, u16 x
, u16 y
, char *buf
)
703 int length
= strlen(buf
) + 1;
704 u16 cbuf
[5] = { (COMTYPE_OSD
<< 8) + DText
, 3, win
, x
, y
};
706 if (mutex_lock_interruptible(&av7110
->dcomlock
))
711 ret
= time_after(jiffies
, start
+ ARM_WAIT_OSD
);
712 if (rdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
, 0, 2) == 0)
715 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
717 mutex_unlock(&av7110
->dcomlock
);
725 ret
= time_after(jiffies
, start
+ ARM_WAIT_SHAKE
);
726 if (rdebi(av7110
, DEBINOSWAP
, HANDSHAKE_REG
, 0, 2) == 0)
729 printk(KERN_ERR
"dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
731 mutex_unlock(&av7110
->dcomlock
);
737 for (i
= 0; i
< length
/ 2; i
++)
738 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2,
739 swab16(*(u16
*)(buf
+ 2 * i
)), 2);
741 wdebi(av7110
, DEBINOSWAP
, BUFF1_BASE
+ i
* 2, 0, 2);
742 ret
= __av7110_send_fw_cmd(av7110
, cbuf
, 5);
743 mutex_unlock(&av7110
->dcomlock
);
744 if (ret
&& ret
!=-ERESTARTSYS
)
745 printk(KERN_ERR
"dvb-ttpci: WriteText error %d\n", ret
);
749 static inline int DrawLine(struct av7110
*av7110
, u8 windownr
,
750 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
752 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DLine
, 6,
753 windownr
, x
, y
, dx
, dy
, color
);
756 static inline int DrawBlock(struct av7110
*av7110
, u8 windownr
,
757 u16 x
, u16 y
, u16 dx
, u16 dy
, u16 color
)
759 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, DBox
, 6,
760 windownr
, x
, y
, dx
, dy
, color
);
763 static inline int HideWindow(struct av7110
*av7110
, u8 windownr
)
765 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WHide
, 1, windownr
);
768 static inline int MoveWindowRel(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
770 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveD
, 3, windownr
, x
, y
);
773 static inline int MoveWindowAbs(struct av7110
*av7110
, u8 windownr
, u16 x
, u16 y
)
775 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WMoveA
, 3, windownr
, x
, y
);
778 static inline int DestroyOSDWindow(struct av7110
*av7110
, u8 windownr
)
780 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WDestroy
, 1, windownr
);
783 static inline int CreateOSDWindow(struct av7110
*av7110
, u8 windownr
,
784 osd_raw_window_t disptype
,
785 u16 width
, u16 height
)
787 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, WCreate
, 4,
788 windownr
, disptype
, width
, height
);
792 static enum av7110_osd_palette_type bpp2pal
[8] = {
793 Pal1Bit
, Pal2Bit
, 0, Pal4Bit
, 0, 0, 0, Pal8Bit
795 static osd_raw_window_t bpp2bit
[8] = {
796 OSD_BITMAP1
, OSD_BITMAP2
, 0, OSD_BITMAP4
, 0, 0, 0, OSD_BITMAP8
799 static inline int WaitUntilBmpLoaded(struct av7110
*av7110
)
801 int ret
= wait_event_timeout(av7110
->bmpq
,
802 av7110
->bmp_state
!= BMP_LOADING
, 10*HZ
);
804 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
805 ret
, av7110
->bmp_state
);
806 av7110
->bmp_state
= BMP_NONE
;
812 static inline int LoadBitmap(struct av7110
*av7110
,
813 u16 dx
, u16 dy
, int inc
, u8 __user
* data
)
822 dprintk(4, "%p\n", av7110
);
824 format
= bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]];
826 av7110
->bmp_state
= BMP_LOADING
;
827 if (format
== OSD_BITMAP8
) {
829 } else if (format
== OSD_BITMAP4
) {
831 } else if (format
== OSD_BITMAP2
) {
833 } else if (format
== OSD_BITMAP1
) {
836 av7110
->bmp_state
= BMP_NONE
;
839 av7110
->bmplen
= ((dx
* dy
* bpp
+ 7) & ~7) / 8;
841 if (av7110
->bmplen
> 32768) {
842 av7110
->bmp_state
= BMP_NONE
;
845 for (i
= 0; i
< dy
; i
++) {
846 if (copy_from_user(av7110
->bmpbuf
+ 1024 + i
* dx
, data
+ i
* inc
, dx
)) {
847 av7110
->bmp_state
= BMP_NONE
;
851 if (format
!= OSD_BITMAP8
) {
852 for (i
= 0; i
< dx
* dy
/ delta
; i
++) {
853 c
= ((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ delta
- 1];
854 for (d
= delta
- 2; d
>= 0; d
--) {
855 c
|= (((u8
*)av7110
->bmpbuf
)[1024 + i
* delta
+ d
]
856 << ((delta
- d
- 1) * bpp
));
857 ((u8
*)av7110
->bmpbuf
)[1024 + i
] = c
;
861 av7110
->bmplen
+= 1024;
862 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110
->bmplen
);
863 ret
= av7110_fw_cmd(av7110
, COMTYPE_OSD
, LoadBmp
, 3, format
, dx
, dy
);
865 ret
= WaitUntilBmpLoaded(av7110
);
869 static int BlitBitmap(struct av7110
*av7110
, u16 x
, u16 y
)
871 dprintk(4, "%p\n", av7110
);
873 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, BlitBmp
, 4, av7110
->osdwin
, x
, y
, 0);
876 static inline int ReleaseBitmap(struct av7110
*av7110
)
878 dprintk(4, "%p\n", av7110
);
880 if (av7110
->bmp_state
!= BMP_LOADED
&& FW_VERSION(av7110
->arm_app
) < 0x261e)
882 if (av7110
->bmp_state
== BMP_LOADING
)
883 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
884 av7110
->bmp_state
= BMP_NONE
;
885 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, ReleaseBmp
, 0);
888 static u32
RGB2YUV(u16 R
, u16 G
, u16 B
)
893 y
= R
* 77 + G
* 150 + B
* 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
894 u
= 2048 + B
* 8 -(y
>> 5); /* Cr 0..4095 */
895 v
= 2048 + R
* 8 -(y
>> 5); /* Cb 0..4095 */
901 return Cr
| (Cb
<< 16) | (Y
<< 8);
904 static int OSDSetColor(struct av7110
*av7110
, u8 color
, u8 r
, u8 g
, u8 b
, u8 blend
)
911 yuv
= blend
? RGB2YUV(r
,g
,b
) : 0;
913 ch
= ((yuv
>> 16) & 0xffff);
914 ret
= SetColor_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
917 ret
= SetBlend_(av7110
, av7110
->osdwin
, bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
918 color
, ((blend
>> 4) & 0x0f));
922 static int OSDSetPalette(struct av7110
*av7110
, u32 __user
* colors
, u8 first
, u8 last
)
925 int length
= last
- first
+ 1;
927 if (length
* 4 > DATA_BUFF3_SIZE
)
930 for (i
= 0; i
< length
; i
++) {
931 u32 color
, blend
, yuv
;
933 if (get_user(color
, colors
+ i
))
935 blend
= (color
& 0xF0000000) >> 4;
936 yuv
= blend
? RGB2YUV(color
& 0xFF, (color
>> 8) & 0xFF,
937 (color
>> 16) & 0xFF) | blend
: 0;
938 yuv
= ((yuv
& 0xFFFF0000) >> 16) | ((yuv
& 0x0000FFFF) << 16);
939 wdebi(av7110
, DEBINOSWAP
, DATA_BUFF3_BASE
+ i
* 4, yuv
, 4);
941 return av7110_fw_cmd(av7110
, COMTYPE_OSD
, Set_Palette
, 4,
943 bpp2pal
[av7110
->osdbpp
[av7110
->osdwin
]],
947 static int OSDSetBlock(struct av7110
*av7110
, int x0
, int y0
,
948 int x1
, int y1
, int inc
, u8 __user
* data
)
950 uint w
, h
, bpp
, bpl
, size
, lpb
, bnum
, brest
;
958 if (w
<= 0 || w
> 720 || h
<= 0 || h
> 576)
960 bpp
= av7110
->osdbpp
[av7110
->osdwin
] + 1;
961 bpl
= ((w
* bpp
+ 7) & ~7) / 8;
963 lpb
= (32 * 1024) / bpl
;
964 bnum
= size
/ (lpb
* bpl
);
965 brest
= size
- bnum
* lpb
* bpl
;
967 if (av7110
->bmp_state
== BMP_LOADING
) {
968 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
969 BUG_ON (FW_VERSION(av7110
->arm_app
) >= 0x261e);
970 rc
= WaitUntilBmpLoaded(av7110
);
973 /* just continue. This should work for all fw versions
974 * if bnum==1 && !brest && LoadBitmap was successful
979 for (i
= 0; i
< bnum
; i
++) {
980 rc
= LoadBitmap(av7110
, w
, lpb
, inc
, data
);
983 rc
= BlitBitmap(av7110
, x0
, y0
+ i
* lpb
);
989 rc
= LoadBitmap(av7110
, w
, brest
/ bpl
, inc
, data
);
991 rc
= BlitBitmap(av7110
, x0
, y0
+ bnum
* lpb
);
993 release_rc
= ReleaseBitmap(av7110
);
997 dprintk(1,"returns %d\n",rc
);
1001 int av7110_osd_cmd(struct av7110
*av7110
, osd_cmd_t
*dc
)
1005 if (mutex_lock_interruptible(&av7110
->osd_mutex
))
1006 return -ERESTARTSYS
;
1010 ret
= DestroyOSDWindow(av7110
, av7110
->osdwin
);
1013 av7110
->osdbpp
[av7110
->osdwin
] = (dc
->color
- 1) & 7;
1014 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
,
1015 bpp2bit
[av7110
->osdbpp
[av7110
->osdwin
]],
1016 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1020 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1023 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1027 ret
= MoveWindowRel(av7110
, av7110
->osdwin
, 0, 0);
1030 ret
= HideWindow(av7110
, av7110
->osdwin
);
1033 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, 0);
1036 ret
= DrawBlock(av7110
, av7110
->osdwin
, 0, 0, 720, 576, dc
->color
);
1039 ret
= OSDSetColor(av7110
, dc
->color
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
);
1041 case OSD_SetPalette
:
1042 if (FW_VERSION(av7110
->arm_app
) >= 0x2618)
1043 ret
= OSDSetPalette(av7110
, dc
->data
, dc
->color
, dc
->x0
);
1045 int i
, len
= dc
->x0
-dc
->color
+1;
1046 u8 __user
*colors
= (u8 __user
*)dc
->data
;
1047 u8 r
, g
= 0, b
= 0, blend
= 0;
1049 for (i
= 0; i
<len
; i
++) {
1050 if (get_user(r
, colors
+ i
* 4) ||
1051 get_user(g
, colors
+ i
* 4 + 1) ||
1052 get_user(b
, colors
+ i
* 4 + 2) ||
1053 get_user(blend
, colors
+ i
* 4 + 3)) {
1057 ret
= OSDSetColor(av7110
, dc
->color
+ i
, r
, g
, b
, blend
);
1064 ret
= DrawLine(av7110
, av7110
->osdwin
,
1065 dc
->x0
, dc
->y0
, 0, 0, dc
->color
);
1071 ret
= OSDSetBlock(av7110
, dc
->x0
, dc
->y0
, dc
->x1
, dc
->y1
, dc
->color
, dc
->data
);
1074 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1075 dc
->x1
-dc
->x0
+1, dc
->y1
, dc
->color
);
1078 ret
= DrawBlock(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
,
1079 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1, dc
->color
);
1082 ret
= DrawLine(av7110
, av7110
->osdwin
,
1083 dc
->x0
, dc
->y0
, dc
->x1
- dc
->x0
, dc
->y1
- dc
->y0
, dc
->color
);
1089 if (strncpy_from_user(textbuf
, dc
->data
, 240) < 0) {
1096 ret
= SetFont(av7110
, av7110
->osdwin
, dc
->x1
,
1097 (u16
) (dc
->color
& 0xffff), (u16
) (dc
->color
>> 16));
1099 ret
= FlushText(av7110
);
1101 ret
= WriteText(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
, textbuf
);
1105 if (dc
->x0
< 1 || dc
->x0
> 7)
1108 av7110
->osdwin
= dc
->x0
;
1112 case OSD_MoveWindow
:
1113 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1115 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1118 if (dc
->color
< OSD_BITMAP1
|| dc
->color
> OSD_CURSOR
) {
1122 if (dc
->color
>= OSD_BITMAP1
&& dc
->color
<= OSD_BITMAP8HR
)
1123 av7110
->osdbpp
[av7110
->osdwin
] = (1 << (dc
->color
& 3)) - 1;
1125 av7110
->osdbpp
[av7110
->osdwin
] = 0;
1126 ret
= CreateOSDWindow(av7110
, av7110
->osdwin
, (osd_raw_window_t
)dc
->color
,
1127 dc
->x1
- dc
->x0
+ 1, dc
->y1
- dc
->y0
+ 1);
1131 ret
= MoveWindowAbs(av7110
, av7110
->osdwin
, dc
->x0
, dc
->y0
);
1133 ret
= SetColorBlend(av7110
, av7110
->osdwin
);
1141 mutex_unlock(&av7110
->osd_mutex
);
1142 if (ret
==-ERESTARTSYS
)
1143 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc
->cmd
);
1145 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc
->cmd
,ret
);
1150 int av7110_osd_capability(struct av7110
*av7110
, osd_cap_t
*cap
)
1153 case OSD_CAP_MEMSIZE
:
1154 if (FW_4M_SDRAM(av7110
->arm_app
))
1163 #endif /* CONFIG_DVB_AV7110_OSD */