diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2006-09-05 14:25:05 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:45:57 -0400 |
commit | ea543f1ee61bbfdf6cac4b79d66c7840d5b00037 (patch) | |
tree | 9afd4cc03826e32f6abd2145c77c7e9d8311a183 | |
parent | 679e28eef835cbd30de78c2f80bf488cba1b7e40 (diff) |
[ALSA] sparc dbri: SMP fixes
The dbri driver hangs when used in kernel compiled with SMP
support due to inproper locking. The patch fixes it.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r-- | sound/sparc/dbri.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 82d5e8072f2b..e4935fca12df 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -635,10 +635,16 @@ to send them to the DBRI. | |||
635 | static void dbri_cmdwait(struct snd_dbri *dbri) | 635 | static void dbri_cmdwait(struct snd_dbri *dbri) |
636 | { | 636 | { |
637 | int maxloops = MAXLOOPS; | 637 | int maxloops = MAXLOOPS; |
638 | unsigned long flags; | ||
638 | 639 | ||
639 | /* Delay if previous commands are still being processed */ | 640 | /* Delay if previous commands are still being processed */ |
640 | while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) | 641 | spin_lock_irqsave(&dbri->lock, flags); |
642 | while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) { | ||
643 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
641 | msleep_interruptible(1); | 644 | msleep_interruptible(1); |
645 | spin_lock_irqsave(&dbri->lock, flags); | ||
646 | } | ||
647 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
642 | 648 | ||
643 | if (maxloops == 0) { | 649 | if (maxloops == 0) { |
644 | printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); | 650 | printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); |
@@ -671,11 +677,12 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) | |||
671 | * the last WAIT cmd and force DBRI to reread the cmd. | 677 | * the last WAIT cmd and force DBRI to reread the cmd. |
672 | * The JUMP cmd points to the new cmd string. | 678 | * The JUMP cmd points to the new cmd string. |
673 | * It also releases the cmdlock spinlock. | 679 | * It also releases the cmdlock spinlock. |
680 | * | ||
681 | * Lock must not be held before calling this. | ||
674 | */ | 682 | */ |
675 | static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | 683 | static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) |
676 | { | 684 | { |
677 | s32 tmp, addr; | 685 | s32 tmp, addr; |
678 | unsigned long flags; | ||
679 | static int wait_id = 0; | 686 | static int wait_id = 0; |
680 | 687 | ||
681 | wait_id++; | 688 | wait_id++; |
@@ -706,12 +713,10 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | |||
706 | } | 713 | } |
707 | #endif | 714 | #endif |
708 | 715 | ||
709 | spin_lock_irqsave(&dbri->lock, flags); | ||
710 | /* Reread the last command */ | 716 | /* Reread the last command */ |
711 | tmp = sbus_readl(dbri->regs + REG0); | 717 | tmp = sbus_readl(dbri->regs + REG0); |
712 | tmp |= D_P; | 718 | tmp |= D_P; |
713 | sbus_writel(tmp, dbri->regs + REG0); | 719 | sbus_writel(tmp, dbri->regs + REG0); |
714 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
715 | 720 | ||
716 | dbri->cmdptr = cmd; | 721 | dbri->cmdptr = cmd; |
717 | spin_unlock(&dbri->cmdlock); | 722 | spin_unlock(&dbri->cmdlock); |
@@ -777,9 +782,9 @@ static void dbri_initialize(struct snd_dbri * dbri) | |||
777 | dma_addr = dbri->dma_dvma + dbri_dma_off(cmd, 0); | 782 | dma_addr = dbri->dma_dvma + dbri_dma_off(cmd, 0); |
778 | sbus_writel(dma_addr, dbri->regs + REG8); | 783 | sbus_writel(dma_addr, dbri->regs + REG8); |
779 | spin_unlock(&dbri->cmdlock); | 784 | spin_unlock(&dbri->cmdlock); |
780 | dbri_cmdwait(dbri); | ||
781 | 785 | ||
782 | spin_unlock_irqrestore(&dbri->lock, flags); | 786 | spin_unlock_irqrestore(&dbri->lock, flags); |
787 | dbri_cmdwait(dbri); | ||
783 | } | 788 | } |
784 | 789 | ||
785 | /* | 790 | /* |
@@ -840,6 +845,9 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) | |||
840 | dbri->pipes[pipe].first_desc = -1; | 845 | dbri->pipes[pipe].first_desc = -1; |
841 | } | 846 | } |
842 | 847 | ||
848 | /* | ||
849 | * Lock must be held before calling this. | ||
850 | */ | ||
843 | static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) | 851 | static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) |
844 | { | 852 | { |
845 | if (pipe < 0 || pipe > DBRI_MAX_PIPE) { | 853 | if (pipe < 0 || pipe > DBRI_MAX_PIPE) { |
@@ -866,6 +874,9 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) | |||
866 | reset_pipe(dbri, pipe); | 874 | reset_pipe(dbri, pipe); |
867 | } | 875 | } |
868 | 876 | ||
877 | /* | ||
878 | * Lock must be held before calling this. | ||
879 | */ | ||
869 | static void link_time_slot(struct snd_dbri * dbri, int pipe, | 880 | static void link_time_slot(struct snd_dbri * dbri, int pipe, |
870 | int prevpipe, int nextpipe, | 881 | int prevpipe, int nextpipe, |
871 | int length, int cycle) | 882 | int length, int cycle) |
@@ -920,6 +931,10 @@ static void link_time_slot(struct snd_dbri * dbri, int pipe, | |||
920 | dbri_cmdsend(dbri, cmd, 4); | 931 | dbri_cmdsend(dbri, cmd, 4); |
921 | } | 932 | } |
922 | 933 | ||
934 | #if 0 | ||
935 | /* | ||
936 | * Lock must be held before calling this. | ||
937 | */ | ||
923 | static void unlink_time_slot(struct snd_dbri * dbri, int pipe, | 938 | static void unlink_time_slot(struct snd_dbri * dbri, int pipe, |
924 | enum in_or_out direction, int prevpipe, | 939 | enum in_or_out direction, int prevpipe, |
925 | int nextpipe) | 940 | int nextpipe) |
@@ -952,6 +967,7 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, | |||
952 | 967 | ||
953 | dbri_cmdsend(dbri, cmd, 4); | 968 | dbri_cmdsend(dbri, cmd, 4); |
954 | } | 969 | } |
970 | #endif | ||
955 | 971 | ||
956 | /* xmit_fixed() / recv_fixed() | 972 | /* xmit_fixed() / recv_fixed() |
957 | * | 973 | * |
@@ -965,11 +981,14 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, | |||
965 | * the actual time slot is. The interrupt handler takes care of bit | 981 | * the actual time slot is. The interrupt handler takes care of bit |
966 | * ordering and alignment. An 8-bit time slot will always end up | 982 | * ordering and alignment. An 8-bit time slot will always end up |
967 | * in the low-order 8 bits, filled either MSB-first or LSB-first, | 983 | * in the low-order 8 bits, filled either MSB-first or LSB-first, |
968 | * depending on the settings passed to setup_pipe() | 984 | * depending on the settings passed to setup_pipe(). |
985 | * | ||
986 | * Lock must not be held before calling it. | ||
969 | */ | 987 | */ |
970 | static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) | 988 | static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) |
971 | { | 989 | { |
972 | s32 *cmd; | 990 | s32 *cmd; |
991 | unsigned long flags; | ||
973 | 992 | ||
974 | if (pipe < 16 || pipe > DBRI_MAX_PIPE) { | 993 | if (pipe < 16 || pipe > DBRI_MAX_PIPE) { |
975 | printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n"); | 994 | printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n"); |
@@ -1002,8 +1021,11 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) | |||
1002 | *(cmd++) = data; | 1021 | *(cmd++) = data; |
1003 | *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); | 1022 | *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); |
1004 | 1023 | ||
1024 | spin_lock_irqsave(&dbri->lock, flags); | ||
1005 | dbri_cmdsend(dbri, cmd, 3); | 1025 | dbri_cmdsend(dbri, cmd, 3); |
1026 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1006 | dbri_cmdwait(dbri); | 1027 | dbri_cmdwait(dbri); |
1028 | |||
1007 | } | 1029 | } |
1008 | 1030 | ||
1009 | static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) | 1031 | static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) |
@@ -1039,6 +1061,8 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) | |||
1039 | * be spread across multiple descriptors. | 1061 | * be spread across multiple descriptors. |
1040 | * | 1062 | * |
1041 | * All descriptors create a ring buffer. | 1063 | * All descriptors create a ring buffer. |
1064 | * | ||
1065 | * Lock must be held before calling this. | ||
1042 | */ | 1066 | */ |
1043 | static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period) | 1067 | static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period) |
1044 | { | 1068 | { |
@@ -1186,6 +1210,9 @@ multiplexed serial interface which the DBRI can operate in either master | |||
1186 | 1210 | ||
1187 | enum master_or_slave { CHImaster, CHIslave }; | 1211 | enum master_or_slave { CHImaster, CHIslave }; |
1188 | 1212 | ||
1213 | /* | ||
1214 | * Lock must not be held before calling it. | ||
1215 | */ | ||
1189 | static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave, | 1216 | static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave, |
1190 | int bits_per_frame) | 1217 | int bits_per_frame) |
1191 | { | 1218 | { |
@@ -1258,9 +1285,14 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla | |||
1258 | In the standard SPARC audio configuration, the CS4215 codec is attached | 1285 | In the standard SPARC audio configuration, the CS4215 codec is attached |
1259 | to the DBRI via the CHI interface and few of the DBRI's PIO pins. | 1286 | to the DBRI via the CHI interface and few of the DBRI's PIO pins. |
1260 | 1287 | ||
1288 | * Lock must not be held before calling it. | ||
1289 | |||
1261 | */ | 1290 | */ |
1262 | static void cs4215_setup_pipes(struct snd_dbri * dbri) | 1291 | static void cs4215_setup_pipes(struct snd_dbri * dbri) |
1263 | { | 1292 | { |
1293 | unsigned long flags; | ||
1294 | |||
1295 | spin_lock_irqsave(&dbri->lock, flags); | ||
1264 | /* | 1296 | /* |
1265 | * Data mode: | 1297 | * Data mode: |
1266 | * Pipe 4: Send timeslots 1-4 (audio data) | 1298 | * Pipe 4: Send timeslots 1-4 (audio data) |
@@ -1284,6 +1316,7 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri) | |||
1284 | setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); | 1316 | setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); |
1285 | setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | 1317 | setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); |
1286 | setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | 1318 | setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); |
1319 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1287 | 1320 | ||
1288 | dbri_cmdwait(dbri); | 1321 | dbri_cmdwait(dbri); |
1289 | } | 1322 | } |
@@ -1358,6 +1391,7 @@ static void cs4215_open(struct snd_dbri * dbri) | |||
1358 | { | 1391 | { |
1359 | int data_width; | 1392 | int data_width; |
1360 | u32 tmp; | 1393 | u32 tmp; |
1394 | unsigned long flags; | ||
1361 | 1395 | ||
1362 | dprintk(D_MM, "cs4215_open: %d channels, %d bits\n", | 1396 | dprintk(D_MM, "cs4215_open: %d channels, %d bits\n", |
1363 | dbri->mm.channels, dbri->mm.precision); | 1397 | dbri->mm.channels, dbri->mm.precision); |
@@ -1382,6 +1416,7 @@ static void cs4215_open(struct snd_dbri * dbri) | |||
1382 | * bits. The CS4215, it seems, observes TSIN (the delayed signal) | 1416 | * bits. The CS4215, it seems, observes TSIN (the delayed signal) |
1383 | * even if it's the CHI master. Don't ask me... | 1417 | * even if it's the CHI master. Don't ask me... |
1384 | */ | 1418 | */ |
1419 | spin_lock_irqsave(&dbri->lock, flags); | ||
1385 | tmp = sbus_readl(dbri->regs + REG0); | 1420 | tmp = sbus_readl(dbri->regs + REG0); |
1386 | tmp &= ~(D_C); /* Disable CHI */ | 1421 | tmp &= ~(D_C); /* Disable CHI */ |
1387 | sbus_writel(tmp, dbri->regs + REG0); | 1422 | sbus_writel(tmp, dbri->regs + REG0); |
@@ -1409,6 +1444,7 @@ static void cs4215_open(struct snd_dbri * dbri) | |||
1409 | tmp = sbus_readl(dbri->regs + REG0); | 1444 | tmp = sbus_readl(dbri->regs + REG0); |
1410 | tmp |= D_C; /* Enable CHI */ | 1445 | tmp |= D_C; /* Enable CHI */ |
1411 | sbus_writel(tmp, dbri->regs + REG0); | 1446 | sbus_writel(tmp, dbri->regs + REG0); |
1447 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1412 | 1448 | ||
1413 | cs4215_setdata(dbri, 0); | 1449 | cs4215_setdata(dbri, 0); |
1414 | } | 1450 | } |
@@ -1420,6 +1456,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri) | |||
1420 | { | 1456 | { |
1421 | int i, val; | 1457 | int i, val; |
1422 | u32 tmp; | 1458 | u32 tmp; |
1459 | unsigned long flags; | ||
1423 | 1460 | ||
1424 | /* FIXME - let the CPU do something useful during these delays */ | 1461 | /* FIXME - let the CPU do something useful during these delays */ |
1425 | 1462 | ||
@@ -1456,6 +1493,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri) | |||
1456 | * done in hardware by a TI 248 that delays the DBRI->4215 | 1493 | * done in hardware by a TI 248 that delays the DBRI->4215 |
1457 | * frame sync signal by eight clock cycles. Anybody know why? | 1494 | * frame sync signal by eight clock cycles. Anybody know why? |
1458 | */ | 1495 | */ |
1496 | spin_lock_irqsave(&dbri->lock, flags); | ||
1459 | tmp = sbus_readl(dbri->regs + REG0); | 1497 | tmp = sbus_readl(dbri->regs + REG0); |
1460 | tmp &= ~D_C; /* Disable CHI */ | 1498 | tmp &= ~D_C; /* Disable CHI */ |
1461 | sbus_writel(tmp, dbri->regs + REG0); | 1499 | sbus_writel(tmp, dbri->regs + REG0); |
@@ -1472,14 +1510,17 @@ static int cs4215_setctrl(struct snd_dbri * dbri) | |||
1472 | link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); | 1510 | link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); |
1473 | link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset); | 1511 | link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset); |
1474 | link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48); | 1512 | link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48); |
1513 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1475 | 1514 | ||
1476 | /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */ | 1515 | /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */ |
1477 | dbri->mm.ctrl[0] &= ~CS4215_CLB; | 1516 | dbri->mm.ctrl[0] &= ~CS4215_CLB; |
1478 | xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); | 1517 | xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); |
1479 | 1518 | ||
1519 | spin_lock_irqsave(&dbri->lock, flags); | ||
1480 | tmp = sbus_readl(dbri->regs + REG0); | 1520 | tmp = sbus_readl(dbri->regs + REG0); |
1481 | tmp |= D_C; /* Enable CHI */ | 1521 | tmp |= D_C; /* Enable CHI */ |
1482 | sbus_writel(tmp, dbri->regs + REG0); | 1522 | sbus_writel(tmp, dbri->regs + REG0); |
1523 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1483 | 1524 | ||
1484 | for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) { | 1525 | for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) { |
1485 | msleep_interruptible(1); | 1526 | msleep_interruptible(1); |
@@ -1688,6 +1729,7 @@ static void xmit_descs(struct snd_dbri *dbri) | |||
1688 | dbri->pipes[info->pipe].desc = first_td; | 1729 | dbri->pipes[info->pipe].desc = first_td; |
1689 | } | 1730 | } |
1690 | } | 1731 | } |
1732 | |||
1691 | spin_unlock_irqrestore(&dbri->lock, flags); | 1733 | spin_unlock_irqrestore(&dbri->lock, flags); |
1692 | } | 1734 | } |
1693 | 1735 | ||
@@ -2093,7 +2135,6 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) | |||
2093 | { | 2135 | { |
2094 | struct snd_dbri *dbri = snd_pcm_substream_chip(substream); | 2136 | struct snd_dbri *dbri = snd_pcm_substream_chip(substream); |
2095 | struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream); | 2137 | struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream); |
2096 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2097 | int ret; | 2138 | int ret; |
2098 | 2139 | ||
2099 | info->size = snd_pcm_lib_buffer_bytes(substream); | 2140 | info->size = snd_pcm_lib_buffer_bytes(substream); |
@@ -2232,7 +2273,6 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, | |||
2232 | { | 2273 | { |
2233 | struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); | 2274 | struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); |
2234 | struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value]; | 2275 | struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value]; |
2235 | unsigned long flags; | ||
2236 | int changed = 0; | 2276 | int changed = 0; |
2237 | 2277 | ||
2238 | if (info->left_gain != ucontrol->value.integer.value[0]) { | 2278 | if (info->left_gain != ucontrol->value.integer.value[0]) { |
@@ -2247,13 +2287,9 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, | |||
2247 | /* First mute outputs, and wait 1/8000 sec (125 us) | 2287 | /* First mute outputs, and wait 1/8000 sec (125 us) |
2248 | * to make sure this takes. This avoids clicking noises. | 2288 | * to make sure this takes. This avoids clicking noises. |
2249 | */ | 2289 | */ |
2250 | spin_lock_irqsave(&dbri->lock, flags); | ||
2251 | |||
2252 | cs4215_setdata(dbri, 1); | 2290 | cs4215_setdata(dbri, 1); |
2253 | udelay(125); | 2291 | udelay(125); |
2254 | cs4215_setdata(dbri, 0); | 2292 | cs4215_setdata(dbri, 0); |
2255 | |||
2256 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2257 | } | 2293 | } |
2258 | return changed; | 2294 | return changed; |
2259 | } | 2295 | } |
@@ -2300,7 +2336,6 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, | |||
2300 | struct snd_ctl_elem_value *ucontrol) | 2336 | struct snd_ctl_elem_value *ucontrol) |
2301 | { | 2337 | { |
2302 | struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); | 2338 | struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); |
2303 | unsigned long flags; | ||
2304 | int elem = kcontrol->private_value & 0xff; | 2339 | int elem = kcontrol->private_value & 0xff; |
2305 | int shift = (kcontrol->private_value >> 8) & 0xff; | 2340 | int shift = (kcontrol->private_value >> 8) & 0xff; |
2306 | int mask = (kcontrol->private_value >> 16) & 0xff; | 2341 | int mask = (kcontrol->private_value >> 16) & 0xff; |
@@ -2333,13 +2368,9 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, | |||
2333 | /* First mute outputs, and wait 1/8000 sec (125 us) | 2368 | /* First mute outputs, and wait 1/8000 sec (125 us) |
2334 | * to make sure this takes. This avoids clicking noises. | 2369 | * to make sure this takes. This avoids clicking noises. |
2335 | */ | 2370 | */ |
2336 | spin_lock_irqsave(&dbri->lock, flags); | ||
2337 | |||
2338 | cs4215_setdata(dbri, 1); | 2371 | cs4215_setdata(dbri, 1); |
2339 | udelay(125); | 2372 | udelay(125); |
2340 | cs4215_setdata(dbri, 0); | 2373 | cs4215_setdata(dbri, 0); |
2341 | |||
2342 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2343 | } | 2374 | } |
2344 | return changed; | 2375 | return changed; |
2345 | } | 2376 | } |