diff options
author | Wolfgang Rohdewald <wolfgang@rohdewald.de> | 2005-07-07 20:57:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-07 21:23:57 -0400 |
commit | c9090ebb247999354f80d45d45b3d5a804a94f7f (patch) | |
tree | b87cccfa2a0f037d1b59a5aa5986d449965819c2 /drivers/media/dvb/ttpci | |
parent | dd2bbb179326d23577ff8201c4f20e0db3e87f7b (diff) |
[PATCH] dvb: ttpci: fix error handling for firmware communication
o make sure ERESTARTSYS will be propagated
o ReleaseBitmap: starting with Firmware 261e, also release when
BMP_LOADING
o removes unused #define BMP_LOADINGS
o in many cases changed the return value from -1 to something more
meaningful like ETIMEDOUT, EINVAL
o changed syslog message timeout waiting for COMMAND such that it
indicates what command did not complete
o reduce # of arguments for LoadBitmap and BlitBitmap
o av7110_osd_cmd: remove the out: label
Signed-off-by: Wolfgang Rohdewald <wolfgang@rohdewald.de>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media/dvb/ttpci')
-rw-r--r-- | drivers/media/dvb/ttpci/av7110.h | 3 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/av7110_hw.c | 309 |
2 files changed, 163 insertions, 149 deletions
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 4f69b4d01479..e54222d9b3f9 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h | |||
@@ -119,8 +119,7 @@ struct av7110 { | |||
119 | volatile int bmp_state; | 119 | volatile int bmp_state; |
120 | #define BMP_NONE 0 | 120 | #define BMP_NONE 0 |
121 | #define BMP_LOADING 1 | 121 | #define BMP_LOADING 1 |
122 | #define BMP_LOADINGS 2 | 122 | #define BMP_LOADED 2 |
123 | #define BMP_LOADED 3 | ||
124 | wait_queue_head_t bmpq; | 123 | wait_queue_head_t bmpq; |
125 | 124 | ||
126 | 125 | ||
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 7fa4a0ebe133..7d2bdd791c9e 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c | |||
@@ -137,7 +137,7 @@ static int waitdebi(struct av7110 *av7110, int adr, int state) | |||
137 | return 0; | 137 | return 0; |
138 | udelay(5); | 138 | udelay(5); |
139 | } | 139 | } |
140 | return -1; | 140 | return -ETIMEDOUT; |
141 | } | 141 | } |
142 | 142 | ||
143 | static int load_dram(struct av7110 *av7110, u32 *data, int len) | 143 | static int load_dram(struct av7110 *av7110, u32 *data, int len) |
@@ -155,7 +155,7 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) | |||
155 | for (i = 0; i < blocks; i++) { | 155 | for (i = 0; i < blocks; i++) { |
156 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { | 156 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { |
157 | printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i); | 157 | printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i); |
158 | return -1; | 158 | return -ETIMEDOUT; |
159 | } | 159 | } |
160 | dprintk(4, "writing DRAM block %d\n", i); | 160 | dprintk(4, "writing DRAM block %d\n", i); |
161 | mwdebi(av7110, DEBISWAB, bootblock, | 161 | mwdebi(av7110, DEBISWAB, bootblock, |
@@ -170,7 +170,7 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) | |||
170 | if (rest > 0) { | 170 | if (rest > 0) { |
171 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { | 171 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { |
172 | printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n"); | 172 | printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n"); |
173 | return -1; | 173 | return -ETIMEDOUT; |
174 | } | 174 | } |
175 | if (rest > 4) | 175 | if (rest > 4) |
176 | mwdebi(av7110, DEBISWAB, bootblock, | 176 | mwdebi(av7110, DEBISWAB, bootblock, |
@@ -185,13 +185,13 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) | |||
185 | } | 185 | } |
186 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { | 186 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { |
187 | printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n"); | 187 | printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n"); |
188 | return -1; | 188 | return -ETIMEDOUT; |
189 | } | 189 | } |
190 | iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2); | 190 | iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2); |
191 | iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); | 191 | iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); |
192 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) { | 192 | if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) { |
193 | printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n"); | 193 | printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n"); |
194 | return -1; | 194 | return -ETIMEDOUT; |
195 | } | 195 | } |
196 | return 0; | 196 | return 0; |
197 | } | 197 | } |
@@ -263,7 +263,7 @@ int av7110_bootarm(struct av7110 *av7110) | |||
263 | if (saa7146_wait_for_debi_done(av7110->dev, 1)) { | 263 | if (saa7146_wait_for_debi_done(av7110->dev, 1)) { |
264 | printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " | 264 | printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " |
265 | "saa7146_wait_for_debi_done() timed out\n"); | 265 | "saa7146_wait_for_debi_done() timed out\n"); |
266 | return -1; | 266 | return -ETIMEDOUT; |
267 | } | 267 | } |
268 | saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); | 268 | saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); |
269 | mdelay(1); | 269 | mdelay(1); |
@@ -284,7 +284,7 @@ int av7110_bootarm(struct av7110 *av7110) | |||
284 | if (saa7146_wait_for_debi_done(av7110->dev, 1)) { | 284 | if (saa7146_wait_for_debi_done(av7110->dev, 1)) { |
285 | printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " | 285 | printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " |
286 | "saa7146_wait_for_debi_done() timed out after loading DRAM\n"); | 286 | "saa7146_wait_for_debi_done() timed out after loading DRAM\n"); |
287 | return -1; | 287 | return -ETIMEDOUT; |
288 | } | 288 | } |
289 | saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); | 289 | saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); |
290 | msleep(30); /* the firmware needs some time to initialize */ | 290 | msleep(30); /* the firmware needs some time to initialize */ |
@@ -328,7 +328,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) | |||
328 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 328 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { |
329 | printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", | 329 | printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", |
330 | __FUNCTION__, stat & flags); | 330 | __FUNCTION__, stat & flags); |
331 | return -1; | 331 | return -ETIMEDOUT; |
332 | } | 332 | } |
333 | msleep(1); | 333 | msleep(1); |
334 | } | 334 | } |
@@ -412,7 +412,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
412 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 412 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { |
413 | printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", | 413 | printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", |
414 | __FUNCTION__, type); | 414 | __FUNCTION__, type); |
415 | return -1; | 415 | return -ETIMEDOUT; |
416 | } | 416 | } |
417 | msleep(1); | 417 | msleep(1); |
418 | } | 418 | } |
@@ -435,8 +435,10 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
435 | while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { | 435 | while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { |
436 | msleep(1); | 436 | msleep(1); |
437 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 437 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { |
438 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND to complete\n", | 438 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n", |
439 | __FUNCTION__); | 439 | __FUNCTION__, |
440 | (buf[0] >> 8) & 0xff | ||
441 | ); | ||
440 | return -ETIMEDOUT; | 442 | return -ETIMEDOUT; |
441 | } | 443 | } |
442 | } | 444 | } |
@@ -470,7 +472,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
470 | 472 | ||
471 | ret = __av7110_send_fw_cmd(av7110, buf, length); | 473 | ret = __av7110_send_fw_cmd(av7110, buf, length); |
472 | up(&av7110->dcomlock); | 474 | up(&av7110->dcomlock); |
473 | if (ret) | 475 | if (ret && ret!=-ERESTARTSYS) |
474 | printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n", | 476 | printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n", |
475 | __FUNCTION__, ret); | 477 | __FUNCTION__, ret); |
476 | return ret; | 478 | return ret; |
@@ -495,7 +497,7 @@ int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...) | |||
495 | } | 497 | } |
496 | 498 | ||
497 | ret = av7110_send_fw_cmd(av7110, buf, num + 2); | 499 | ret = av7110_send_fw_cmd(av7110, buf, num + 2); |
498 | if (ret) | 500 | if (ret && ret != -ERESTARTSYS) |
499 | printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret); | 501 | printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret); |
500 | return ret; | 502 | return ret; |
501 | } | 503 | } |
@@ -518,7 +520,7 @@ int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len) | |||
518 | } | 520 | } |
519 | 521 | ||
520 | ret = av7110_send_fw_cmd(av7110, cmd, 18); | 522 | ret = av7110_send_fw_cmd(av7110, cmd, 18); |
521 | if (ret) | 523 | if (ret && ret != -ERESTARTSYS) |
522 | printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret); | 524 | printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret); |
523 | return ret; | 525 | return ret; |
524 | } | 526 | } |
@@ -558,7 +560,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, | |||
558 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 560 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { |
559 | printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); | 561 | printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); |
560 | up(&av7110->dcomlock); | 562 | up(&av7110->dcomlock); |
561 | return -1; | 563 | return -ETIMEDOUT; |
562 | } | 564 | } |
563 | } | 565 | } |
564 | 566 | ||
@@ -569,7 +571,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, | |||
569 | if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { | 571 | if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { |
570 | printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); | 572 | printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); |
571 | up(&av7110->dcomlock); | 573 | up(&av7110->dcomlock); |
572 | return -1; | 574 | return -ETIMEDOUT; |
573 | } | 575 | } |
574 | } | 576 | } |
575 | #endif | 577 | #endif |
@@ -667,10 +669,10 @@ int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long bu | |||
667 | for (i = 0; i < len; i++) | 669 | for (i = 0; i < len; i++) |
668 | buf[i + 4] = msg[i]; | 670 | buf[i + 4] = msg[i]; |
669 | 671 | ||
670 | if ((ret = av7110_send_fw_cmd(av7110, buf, 18))) | 672 | ret = av7110_send_fw_cmd(av7110, buf, 18); |
673 | if (ret && ret!=-ERESTARTSYS) | ||
671 | printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret); | 674 | printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret); |
672 | 675 | return ret; | |
673 | return 0; | ||
674 | } | 676 | } |
675 | 677 | ||
676 | 678 | ||
@@ -715,7 +717,7 @@ static int FlushText(struct av7110 *av7110) | |||
715 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", | 717 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", |
716 | __FUNCTION__); | 718 | __FUNCTION__); |
717 | up(&av7110->dcomlock); | 719 | up(&av7110->dcomlock); |
718 | return -1; | 720 | return -ETIMEDOUT; |
719 | } | 721 | } |
720 | } | 722 | } |
721 | up(&av7110->dcomlock); | 723 | up(&av7110->dcomlock); |
@@ -739,7 +741,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) | |||
739 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", | 741 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", |
740 | __FUNCTION__); | 742 | __FUNCTION__); |
741 | up(&av7110->dcomlock); | 743 | up(&av7110->dcomlock); |
742 | return -1; | 744 | return -ETIMEDOUT; |
743 | } | 745 | } |
744 | } | 746 | } |
745 | #ifndef _NOHANDSHAKE | 747 | #ifndef _NOHANDSHAKE |
@@ -750,7 +752,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) | |||
750 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", | 752 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", |
751 | __FUNCTION__); | 753 | __FUNCTION__); |
752 | up(&av7110->dcomlock); | 754 | up(&av7110->dcomlock); |
753 | return -1; | 755 | return -ETIMEDOUT; |
754 | } | 756 | } |
755 | } | 757 | } |
756 | #endif | 758 | #endif |
@@ -761,7 +763,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) | |||
761 | wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2); | 763 | wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2); |
762 | ret = __av7110_send_fw_cmd(av7110, cbuf, 5); | 764 | ret = __av7110_send_fw_cmd(av7110, cbuf, 5); |
763 | up(&av7110->dcomlock); | 765 | up(&av7110->dcomlock); |
764 | if (ret) | 766 | if (ret && ret!=-ERESTARTSYS) |
765 | printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret); | 767 | printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret); |
766 | return ret; | 768 | return ret; |
767 | } | 769 | } |
@@ -816,9 +818,25 @@ static osd_raw_window_t bpp2bit[8] = { | |||
816 | OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8 | 818 | OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8 |
817 | }; | 819 | }; |
818 | 820 | ||
819 | static inline int LoadBitmap(struct av7110 *av7110, u16 format, | 821 | static inline int WaitUntilBmpLoaded(struct av7110 *av7110) |
822 | { | ||
823 | int ret = wait_event_interruptible_timeout(av7110->bmpq, | ||
824 | av7110->bmp_state != BMP_LOADING, 10*HZ); | ||
825 | if (ret == -ERESTARTSYS) | ||
826 | return ret; | ||
827 | if (ret == 0) { | ||
828 | printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n", | ||
829 | ret, av7110->bmp_state); | ||
830 | av7110->bmp_state = BMP_NONE; | ||
831 | return -ETIMEDOUT; | ||
832 | } | ||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static inline int LoadBitmap(struct av7110 *av7110, | ||
820 | u16 dx, u16 dy, int inc, u8 __user * data) | 837 | u16 dx, u16 dy, int inc, u8 __user * data) |
821 | { | 838 | { |
839 | u16 format; | ||
822 | int bpp; | 840 | int bpp; |
823 | int i; | 841 | int i; |
824 | int d, delta; | 842 | int d, delta; |
@@ -827,14 +845,7 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, | |||
827 | 845 | ||
828 | dprintk(4, "%p\n", av7110); | 846 | dprintk(4, "%p\n", av7110); |
829 | 847 | ||
830 | ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ); | 848 | format = bpp2bit[av7110->osdbpp[av7110->osdwin]]; |
831 | if (ret == -ERESTARTSYS || ret == 0) { | ||
832 | printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n", | ||
833 | ret, av7110->bmp_state); | ||
834 | av7110->bmp_state = BMP_NONE; | ||
835 | return -1; | ||
836 | } | ||
837 | BUG_ON (av7110->bmp_state == BMP_LOADING); | ||
838 | 849 | ||
839 | av7110->bmp_state = BMP_LOADING; | 850 | av7110->bmp_state = BMP_LOADING; |
840 | if (format == OSD_BITMAP8) { | 851 | if (format == OSD_BITMAP8) { |
@@ -847,18 +858,18 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, | |||
847 | bpp=1; delta = 8; | 858 | bpp=1; delta = 8; |
848 | } else { | 859 | } else { |
849 | av7110->bmp_state = BMP_NONE; | 860 | av7110->bmp_state = BMP_NONE; |
850 | return -1; | 861 | return -EINVAL; |
851 | } | 862 | } |
852 | av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8; | 863 | av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8; |
853 | av7110->bmpp = 0; | 864 | av7110->bmpp = 0; |
854 | if (av7110->bmplen > 32768) { | 865 | if (av7110->bmplen > 32768) { |
855 | av7110->bmp_state = BMP_NONE; | 866 | av7110->bmp_state = BMP_NONE; |
856 | return -1; | 867 | return -EINVAL; |
857 | } | 868 | } |
858 | for (i = 0; i < dy; i++) { | 869 | for (i = 0; i < dy; i++) { |
859 | if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) { | 870 | if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) { |
860 | av7110->bmp_state = BMP_NONE; | 871 | av7110->bmp_state = BMP_NONE; |
861 | return -1; | 872 | return -EINVAL; |
862 | } | 873 | } |
863 | } | 874 | } |
864 | if (format != OSD_BITMAP8) { | 875 | if (format != OSD_BITMAP8) { |
@@ -873,37 +884,27 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, | |||
873 | } | 884 | } |
874 | av7110->bmplen += 1024; | 885 | av7110->bmplen += 1024; |
875 | dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen); | 886 | dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen); |
876 | return av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy); | 887 | ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy); |
888 | if (!ret) | ||
889 | ret = WaitUntilBmpLoaded(av7110); | ||
890 | return ret; | ||
877 | } | 891 | } |
878 | 892 | ||
879 | static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans) | 893 | static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y) |
880 | { | 894 | { |
881 | int ret; | ||
882 | |||
883 | dprintk(4, "%p\n", av7110); | 895 | dprintk(4, "%p\n", av7110); |
884 | 896 | ||
885 | BUG_ON (av7110->bmp_state == BMP_NONE); | 897 | return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0); |
886 | |||
887 | ret = wait_event_interruptible_timeout(av7110->bmpq, | ||
888 | av7110->bmp_state != BMP_LOADING, 10*HZ); | ||
889 | if (ret == -ERESTARTSYS || ret == 0) { | ||
890 | printk("dvb-ttpci: warning: timeout waiting in BlitBitmap: %d, %d\n", | ||
891 | ret, av7110->bmp_state); | ||
892 | av7110->bmp_state = BMP_NONE; | ||
893 | return (ret == 0) ? -ETIMEDOUT : ret; | ||
894 | } | ||
895 | |||
896 | BUG_ON (av7110->bmp_state != BMP_LOADED); | ||
897 | |||
898 | return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, win, x, y, trans); | ||
899 | } | 898 | } |
900 | 899 | ||
901 | static inline int ReleaseBitmap(struct av7110 *av7110) | 900 | static inline int ReleaseBitmap(struct av7110 *av7110) |
902 | { | 901 | { |
903 | dprintk(4, "%p\n", av7110); | 902 | dprintk(4, "%p\n", av7110); |
904 | 903 | ||
905 | if (av7110->bmp_state != BMP_LOADED) | 904 | if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e) |
906 | return -1; | 905 | return -1; |
906 | if (av7110->bmp_state == BMP_LOADING) | ||
907 | dprintk(1,"ReleaseBitmap called while BMP_LOADING\n"); | ||
907 | av7110->bmp_state = BMP_NONE; | 908 | av7110->bmp_state = BMP_NONE; |
908 | return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0); | 909 | return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0); |
909 | } | 910 | } |
@@ -924,18 +925,22 @@ static u32 RGB2YUV(u16 R, u16 G, u16 B) | |||
924 | return Cr | (Cb << 16) | (Y << 8); | 925 | return Cr | (Cb << 16) | (Y << 8); |
925 | } | 926 | } |
926 | 927 | ||
927 | static void OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend) | 928 | static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend) |
928 | { | 929 | { |
930 | int ret; | ||
931 | |||
929 | u16 ch, cl; | 932 | u16 ch, cl; |
930 | u32 yuv; | 933 | u32 yuv; |
931 | 934 | ||
932 | yuv = blend ? RGB2YUV(r,g,b) : 0; | 935 | yuv = blend ? RGB2YUV(r,g,b) : 0; |
933 | cl = (yuv & 0xffff); | 936 | cl = (yuv & 0xffff); |
934 | ch = ((yuv >> 16) & 0xffff); | 937 | ch = ((yuv >> 16) & 0xffff); |
935 | SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], | 938 | ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], |
936 | color, ch, cl); | 939 | color, ch, cl); |
937 | SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], | 940 | if (!ret) |
938 | color, ((blend >> 4) & 0x0f)); | 941 | ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], |
942 | color, ((blend >> 4) & 0x0f)); | ||
943 | return ret; | ||
939 | } | 944 | } |
940 | 945 | ||
941 | static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) | 946 | static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) |
@@ -968,14 +973,14 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, | |||
968 | { | 973 | { |
969 | uint w, h, bpp, bpl, size, lpb, bnum, brest; | 974 | uint w, h, bpp, bpl, size, lpb, bnum, brest; |
970 | int i; | 975 | int i; |
971 | int rc; | 976 | int rc,release_rc; |
972 | 977 | ||
973 | w = x1 - x0 + 1; | 978 | w = x1 - x0 + 1; |
974 | h = y1 - y0 + 1; | 979 | h = y1 - y0 + 1; |
975 | if (inc <= 0) | 980 | if (inc <= 0) |
976 | inc = w; | 981 | inc = w; |
977 | if (w <= 0 || w > 720 || h <= 0 || h > 576) | 982 | if (w <= 0 || w > 720 || h <= 0 || h > 576) |
978 | return -1; | 983 | return -EINVAL; |
979 | bpp = av7110->osdbpp[av7110->osdwin] + 1; | 984 | bpp = av7110->osdbpp[av7110->osdwin] + 1; |
980 | bpl = ((w * bpp + 7) & ~7) / 8; | 985 | bpl = ((w * bpp + 7) & ~7) / 8; |
981 | size = h * bpl; | 986 | size = h * bpl; |
@@ -983,176 +988,186 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, | |||
983 | bnum = size / (lpb * bpl); | 988 | bnum = size / (lpb * bpl); |
984 | brest = size - bnum * lpb * bpl; | 989 | brest = size - bnum * lpb * bpl; |
985 | 990 | ||
986 | for (i = 0; i < bnum; i++) { | 991 | if (av7110->bmp_state == BMP_LOADING) { |
987 | rc = LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]], | 992 | /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */ |
988 | w, lpb, inc, data); | 993 | BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e); |
989 | if (rc) | 994 | rc = WaitUntilBmpLoaded(av7110); |
990 | return rc; | ||
991 | rc = BlitBitmap(av7110, av7110->osdwin, x0, y0 + i * lpb, 0); | ||
992 | if (rc) | 995 | if (rc) |
993 | return rc; | 996 | return rc; |
994 | data += lpb * inc; | 997 | /* just continue. This should work for all fw versions |
998 | * if bnum==1 && !brest && LoadBitmap was successful | ||
999 | */ | ||
995 | } | 1000 | } |
996 | if (brest) { | 1001 | |
997 | rc = LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]], | 1002 | rc = 0; |
998 | w, brest / bpl, inc, data); | 1003 | for (i = 0; i < bnum; i++) { |
1004 | rc = LoadBitmap(av7110, w, lpb, inc, data); | ||
999 | if (rc) | 1005 | if (rc) |
1000 | return rc; | 1006 | break; |
1001 | rc = BlitBitmap(av7110, av7110->osdwin, x0, y0 + bnum * lpb, 0); | 1007 | rc = BlitBitmap(av7110, x0, y0 + i * lpb); |
1002 | if (rc) | 1008 | if (rc) |
1003 | return rc; | 1009 | break; |
1010 | data += lpb * inc; | ||
1004 | } | 1011 | } |
1005 | ReleaseBitmap(av7110); | 1012 | if (!rc && brest) { |
1006 | return 0; | 1013 | rc = LoadBitmap(av7110, w, brest / bpl, inc, data); |
1014 | if (!rc) | ||
1015 | rc = BlitBitmap(av7110, x0, y0 + bnum * lpb); | ||
1016 | } | ||
1017 | release_rc = ReleaseBitmap(av7110); | ||
1018 | if (!rc) | ||
1019 | rc = release_rc; | ||
1020 | if (rc) | ||
1021 | dprintk(1,"returns %d\n",rc); | ||
1022 | return rc; | ||
1007 | } | 1023 | } |
1008 | 1024 | ||
1009 | int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) | 1025 | int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) |
1010 | { | 1026 | { |
1011 | int ret; | 1027 | int ret; |
1012 | 1028 | ||
1013 | ret = down_interruptible(&av7110->osd_sema); | 1029 | if (down_interruptible(&av7110->osd_sema)) |
1014 | if (ret) | ||
1015 | return -ERESTARTSYS; | 1030 | return -ERESTARTSYS; |
1016 | 1031 | ||
1017 | /* stupid, but OSD functions don't provide a return code anyway */ | ||
1018 | ret = 0; | ||
1019 | |||
1020 | switch (dc->cmd) { | 1032 | switch (dc->cmd) { |
1021 | case OSD_Close: | 1033 | case OSD_Close: |
1022 | DestroyOSDWindow(av7110, av7110->osdwin); | 1034 | ret = DestroyOSDWindow(av7110, av7110->osdwin); |
1023 | goto out; | 1035 | break; |
1024 | case OSD_Open: | 1036 | case OSD_Open: |
1025 | av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7; | 1037 | av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7; |
1026 | CreateOSDWindow(av7110, av7110->osdwin, | 1038 | ret = CreateOSDWindow(av7110, av7110->osdwin, |
1027 | bpp2bit[av7110->osdbpp[av7110->osdwin]], | 1039 | bpp2bit[av7110->osdbpp[av7110->osdwin]], |
1028 | dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); | 1040 | dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); |
1041 | if (ret) | ||
1042 | break; | ||
1029 | if (!dc->data) { | 1043 | if (!dc->data) { |
1030 | MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); | 1044 | ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); |
1031 | SetColorBlend(av7110, av7110->osdwin); | 1045 | if (ret) |
1046 | break; | ||
1047 | ret = SetColorBlend(av7110, av7110->osdwin); | ||
1032 | } | 1048 | } |
1033 | goto out; | 1049 | break; |
1034 | case OSD_Show: | 1050 | case OSD_Show: |
1035 | MoveWindowRel(av7110, av7110->osdwin, 0, 0); | 1051 | ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0); |
1036 | goto out; | 1052 | break; |
1037 | case OSD_Hide: | 1053 | case OSD_Hide: |
1038 | HideWindow(av7110, av7110->osdwin); | 1054 | ret = HideWindow(av7110, av7110->osdwin); |
1039 | goto out; | 1055 | break; |
1040 | case OSD_Clear: | 1056 | case OSD_Clear: |
1041 | DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0); | 1057 | ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0); |
1042 | goto out; | 1058 | break; |
1043 | case OSD_Fill: | 1059 | case OSD_Fill: |
1044 | DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color); | 1060 | ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color); |
1045 | goto out; | 1061 | break; |
1046 | case OSD_SetColor: | 1062 | case OSD_SetColor: |
1047 | OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1); | 1063 | ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1); |
1048 | goto out; | 1064 | break; |
1049 | case OSD_SetPalette: | 1065 | case OSD_SetPalette: |
1050 | { | 1066 | if (FW_VERSION(av7110->arm_app) >= 0x2618) |
1051 | if (FW_VERSION(av7110->arm_app) >= 0x2618) { | ||
1052 | ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0); | 1067 | ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0); |
1053 | goto out; | 1068 | else { |
1054 | } else { | ||
1055 | int i, len = dc->x0-dc->color+1; | 1069 | int i, len = dc->x0-dc->color+1; |
1056 | u8 __user *colors = (u8 __user *)dc->data; | 1070 | u8 __user *colors = (u8 __user *)dc->data; |
1057 | u8 r, g, b, blend; | 1071 | u8 r, g, b, blend; |
1058 | 1072 | ret = 0; | |
1059 | for (i = 0; i<len; i++) { | 1073 | for (i = 0; i<len; i++) { |
1060 | if (get_user(r, colors + i * 4) || | 1074 | if (get_user(r, colors + i * 4) || |
1061 | get_user(g, colors + i * 4 + 1) || | 1075 | get_user(g, colors + i * 4 + 1) || |
1062 | get_user(b, colors + i * 4 + 2) || | 1076 | get_user(b, colors + i * 4 + 2) || |
1063 | get_user(blend, colors + i * 4 + 3)) { | 1077 | get_user(blend, colors + i * 4 + 3)) { |
1064 | ret = -EFAULT; | 1078 | ret = -EFAULT; |
1065 | goto out; | 1079 | break; |
1066 | } | 1080 | } |
1067 | OSDSetColor(av7110, dc->color + i, r, g, b, blend); | 1081 | ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend); |
1082 | if (ret) | ||
1083 | break; | ||
1068 | } | 1084 | } |
1069 | } | 1085 | } |
1070 | ret = 0; | 1086 | break; |
1071 | goto out; | ||
1072 | } | ||
1073 | case OSD_SetTrans: | ||
1074 | goto out; | ||
1075 | case OSD_SetPixel: | 1087 | case OSD_SetPixel: |
1076 | DrawLine(av7110, av7110->osdwin, | 1088 | ret = DrawLine(av7110, av7110->osdwin, |
1077 | dc->x0, dc->y0, 0, 0, dc->color); | 1089 | dc->x0, dc->y0, 0, 0, dc->color); |
1078 | goto out; | 1090 | break; |
1079 | case OSD_GetPixel: | ||
1080 | goto out; | ||
1081 | case OSD_SetRow: | 1091 | case OSD_SetRow: |
1082 | dc->y1 = dc->y0; | 1092 | dc->y1 = dc->y0; |
1083 | /* fall through */ | 1093 | /* fall through */ |
1084 | case OSD_SetBlock: | 1094 | case OSD_SetBlock: |
1085 | ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data); | 1095 | ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data); |
1086 | goto out; | 1096 | break; |
1087 | case OSD_FillRow: | 1097 | case OSD_FillRow: |
1088 | DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, | 1098 | ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, |
1089 | dc->x1-dc->x0+1, dc->y1, dc->color); | 1099 | dc->x1-dc->x0+1, dc->y1, dc->color); |
1090 | goto out; | 1100 | break; |
1091 | case OSD_FillBlock: | 1101 | case OSD_FillBlock: |
1092 | DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, | 1102 | ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, |
1093 | dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color); | 1103 | dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color); |
1094 | goto out; | 1104 | break; |
1095 | case OSD_Line: | 1105 | case OSD_Line: |
1096 | DrawLine(av7110, av7110->osdwin, | 1106 | ret = DrawLine(av7110, av7110->osdwin, |
1097 | dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color); | 1107 | dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color); |
1098 | goto out; | 1108 | break; |
1099 | case OSD_Query: | ||
1100 | goto out; | ||
1101 | case OSD_Test: | ||
1102 | goto out; | ||
1103 | case OSD_Text: | 1109 | case OSD_Text: |
1104 | { | 1110 | { |
1105 | char textbuf[240]; | 1111 | char textbuf[240]; |
1106 | 1112 | ||
1107 | if (strncpy_from_user(textbuf, dc->data, 240) < 0) { | 1113 | if (strncpy_from_user(textbuf, dc->data, 240) < 0) { |
1108 | ret = -EFAULT; | 1114 | ret = -EFAULT; |
1109 | goto out; | 1115 | break; |
1110 | } | 1116 | } |
1111 | textbuf[239] = 0; | 1117 | textbuf[239] = 0; |
1112 | if (dc->x1 > 3) | 1118 | if (dc->x1 > 3) |
1113 | dc->x1 = 3; | 1119 | dc->x1 = 3; |
1114 | SetFont(av7110, av7110->osdwin, dc->x1, | 1120 | ret = SetFont(av7110, av7110->osdwin, dc->x1, |
1115 | (u16) (dc->color & 0xffff), (u16) (dc->color >> 16)); | 1121 | (u16) (dc->color & 0xffff), (u16) (dc->color >> 16)); |
1116 | FlushText(av7110); | 1122 | if (!ret) |
1117 | WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf); | 1123 | ret = FlushText(av7110); |
1118 | goto out; | 1124 | if (!ret) |
1125 | ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf); | ||
1126 | break; | ||
1119 | } | 1127 | } |
1120 | case OSD_SetWindow: | 1128 | case OSD_SetWindow: |
1121 | if (dc->x0 < 1 || dc->x0 > 7) { | 1129 | if (dc->x0 < 1 || dc->x0 > 7) |
1122 | ret = -EINVAL; | 1130 | ret = -EINVAL; |
1123 | goto out; | 1131 | else { |
1132 | av7110->osdwin = dc->x0; | ||
1133 | ret = 0; | ||
1124 | } | 1134 | } |
1125 | av7110->osdwin = dc->x0; | 1135 | break; |
1126 | goto out; | ||
1127 | case OSD_MoveWindow: | 1136 | case OSD_MoveWindow: |
1128 | MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); | 1137 | ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); |
1129 | SetColorBlend(av7110, av7110->osdwin); | 1138 | if (!ret) |
1130 | goto out; | 1139 | ret = SetColorBlend(av7110, av7110->osdwin); |
1140 | break; | ||
1131 | case OSD_OpenRaw: | 1141 | case OSD_OpenRaw: |
1132 | if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) { | 1142 | if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) { |
1133 | ret = -EINVAL; | 1143 | ret = -EINVAL; |
1134 | goto out; | 1144 | break; |
1135 | } | 1145 | } |
1136 | if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR) { | 1146 | if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR) |
1137 | av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1; | 1147 | av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1; |
1138 | } | 1148 | else |
1139 | else { | ||
1140 | av7110->osdbpp[av7110->osdwin] = 0; | 1149 | av7110->osdbpp[av7110->osdwin] = 0; |
1141 | } | 1150 | ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color, |
1142 | CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color, | ||
1143 | dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); | 1151 | dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); |
1152 | if (ret) | ||
1153 | break; | ||
1144 | if (!dc->data) { | 1154 | if (!dc->data) { |
1145 | MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); | 1155 | ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); |
1146 | SetColorBlend(av7110, av7110->osdwin); | 1156 | if (!ret) |
1157 | ret = SetColorBlend(av7110, av7110->osdwin); | ||
1147 | } | 1158 | } |
1148 | goto out; | 1159 | break; |
1149 | default: | 1160 | default: |
1150 | ret = -EINVAL; | 1161 | ret = -EINVAL; |
1151 | goto out; | 1162 | break; |
1152 | } | 1163 | } |
1153 | 1164 | ||
1154 | out: | ||
1155 | up(&av7110->osd_sema); | 1165 | up(&av7110->osd_sema); |
1166 | if (ret==-ERESTARTSYS) | ||
1167 | dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd); | ||
1168 | else if (ret) | ||
1169 | dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret); | ||
1170 | |||
1156 | return ret; | 1171 | return ret; |
1157 | } | 1172 | } |
1158 | 1173 | ||