aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/ttpci
diff options
context:
space:
mode:
authorWolfgang Rohdewald <wolfgang@rohdewald.de>2005-07-07 20:57:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-07 21:23:57 -0400
commitc9090ebb247999354f80d45d45b3d5a804a94f7f (patch)
treeb87cccfa2a0f037d1b59a5aa5986d449965819c2 /drivers/media/dvb/ttpci
parentdd2bbb179326d23577ff8201c4f20e0db3e87f7b (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.h3
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c309
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
143static int load_dram(struct av7110 *av7110, u32 *data, int len) 143static 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
819static inline int LoadBitmap(struct av7110 *av7110, u16 format, 821static 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
836static 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
879static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans) 893static 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
901static inline int ReleaseBitmap(struct av7110 *av7110) 900static 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
927static void OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend) 928static 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
941static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) 946static 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
1009int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) 1025int 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
1154out:
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