aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/spca561.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-08-03 06:52:53 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-08-06 05:57:25 -0400
commitcebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2a (patch)
tree606952be0566fa22515d142978d51d1a14be95e7 /drivers/media/video/gspca/spca561.c
parent594f5b8b3cce6d3137ebf260b7386520b2534385 (diff)
V4L/DVB (8604): gspca: Fix of "scheduling while atomic" crash.
The crash is due to USB exchanges done at interrupt level. These exchanges, tied to autogain, are now done by the application. Also, there is a fix about autogain start. Concerned subdrivers: etoms, pac7311, sonixj and spca561. Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r--drivers/media/video/gspca/spca561.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index a26174508cb9..1073ac3d2ec6 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -644,6 +644,18 @@ static void setcontrast(struct gspca_dev *gspca_dev)
644 } 644 }
645} 645}
646 646
647static void setautogain(struct gspca_dev *gspca_dev)
648{
649 struct sd *sd = (struct sd *) gspca_dev;
650
651 if (sd->chip_revision == Rev072A) {
652 if (sd->autogain)
653 sd->ag_cnt = AG_CNT_START;
654 else
655 sd->ag_cnt = -1;
656 }
657}
658
647static void sd_start(struct gspca_dev *gspca_dev) 659static void sd_start(struct gspca_dev *gspca_dev)
648{ 660{
649 struct sd *sd = (struct sd *) gspca_dev; 661 struct sd *sd = (struct sd *) gspca_dev;
@@ -671,6 +683,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
671 reg_w_val(dev, 0x8500, mode); /* mode */ 683 reg_w_val(dev, 0x8500, mode); /* mode */
672 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ 684 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
673 reg_w_val(dev, 0x8112, 0x10 | 0x20); 685 reg_w_val(dev, 0x8112, 0x10 | 0x20);
686 setautogain(gspca_dev);
674 break; 687 break;
675 default: 688 default:
676/* case Rev012A: */ 689/* case Rev012A: */
@@ -720,18 +733,24 @@ static void sd_close(struct gspca_dev *gspca_dev)
720 reg_w_val(gspca_dev->dev, 0x8114, 0); 733 reg_w_val(gspca_dev->dev, 0x8114, 0);
721} 734}
722 735
723static void setautogain(struct gspca_dev *gspca_dev) 736static void do_autogain(struct gspca_dev *gspca_dev)
724{ 737{
725 struct sd *sd = (struct sd *) gspca_dev; 738 struct sd *sd = (struct sd *) gspca_dev;
726 int expotimes = 0; 739 int expotimes;
727 int pixelclk = 0; 740 int pixelclk;
728 int gainG = 0; 741 int gainG;
729 __u8 R, Gr, Gb, B; 742 __u8 R, Gr, Gb, B;
730 int y; 743 int y;
731 __u8 luma_mean = 110; 744 __u8 luma_mean = 110;
732 __u8 luma_delta = 20; 745 __u8 luma_delta = 20;
733 __u8 spring = 4; 746 __u8 spring = 4;
734 747
748 if (sd->ag_cnt < 0)
749 return;
750 if (--sd->ag_cnt >= 0)
751 return;
752 sd->ag_cnt = AG_CNT_START;
753
735 switch (sd->chip_revision) { 754 switch (sd->chip_revision) {
736 case Rev072A: 755 case Rev072A:
737 reg_r(gspca_dev, 0x8621, 1); 756 reg_r(gspca_dev, 0x8621, 1);
@@ -795,18 +814,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
795 __u8 *data, /* isoc packet */ 814 __u8 *data, /* isoc packet */
796 int len) /* iso packet length */ 815 int len) /* iso packet length */
797{ 816{
798 struct sd *sd = (struct sd *) gspca_dev;
799
800 switch (data[0]) { 817 switch (data[0]) {
801 case 0: /* start of frame */ 818 case 0: /* start of frame */
802 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, 819 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
803 data, 0); 820 data, 0);
804 if (sd->ag_cnt >= 0) {
805 if (--sd->ag_cnt < 0) {
806 sd->ag_cnt = AG_CNT_START;
807 setautogain(gspca_dev);
808 }
809 }
810 data += SPCA561_OFFSET_DATA; 821 data += SPCA561_OFFSET_DATA;
811 len -= SPCA561_OFFSET_DATA; 822 len -= SPCA561_OFFSET_DATA;
812 if (data[1] & 0x10) { 823 if (data[1] & 0x10) {
@@ -944,10 +955,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
944 struct sd *sd = (struct sd *) gspca_dev; 955 struct sd *sd = (struct sd *) gspca_dev;
945 956
946 sd->autogain = val; 957 sd->autogain = val;
947 if (val) 958 if (gspca_dev->streaming)
948 sd->ag_cnt = AG_CNT_START; 959 setautogain(gspca_dev);
949 else
950 sd->ag_cnt = -1;
951 return 0; 960 return 0;
952} 961}
953 962
@@ -971,6 +980,7 @@ static const struct sd_desc sd_desc = {
971 .stop0 = sd_stop0, 980 .stop0 = sd_stop0,
972 .close = sd_close, 981 .close = sd_close,
973 .pkt_scan = sd_pkt_scan, 982 .pkt_scan = sd_pkt_scan,
983 .dq_callback = do_autogain,
974}; 984};
975 985
976/* -- module initialisation -- */ 986/* -- module initialisation -- */