diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/arm/aaci.c | 56 |
1 files changed, 33 insertions, 23 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 91acc9a243ec..7c1fc64cb53d 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #define DRIVER_NAME "aaci-pl041" | 31 | #define DRIVER_NAME "aaci-pl041" |
32 | 32 | ||
33 | #define FRAME_PERIOD_US 21 | ||
34 | |||
33 | /* | 35 | /* |
34 | * PM support is not complete. Turn it off. | 36 | * PM support is not complete. Turn it off. |
35 | */ | 37 | */ |
@@ -48,7 +50,11 @@ static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97) | |||
48 | if (v & SLFR_1RXV) | 50 | if (v & SLFR_1RXV) |
49 | readl(aaci->base + AACI_SL1RX); | 51 | readl(aaci->base + AACI_SL1RX); |
50 | 52 | ||
51 | writel(maincr, aaci->base + AACI_MAINCR); | 53 | if (maincr != readl(aaci->base + AACI_MAINCR)) { |
54 | writel(maincr, aaci->base + AACI_MAINCR); | ||
55 | readl(aaci->base + AACI_MAINCR); | ||
56 | udelay(1); | ||
57 | } | ||
52 | } | 58 | } |
53 | 59 | ||
54 | /* | 60 | /* |
@@ -64,8 +70,8 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
64 | unsigned short val) | 70 | unsigned short val) |
65 | { | 71 | { |
66 | struct aaci *aaci = ac97->private_data; | 72 | struct aaci *aaci = ac97->private_data; |
73 | int timeout; | ||
67 | u32 v; | 74 | u32 v; |
68 | int timeout = 5000; | ||
69 | 75 | ||
70 | if (ac97->num >= 4) | 76 | if (ac97->num >= 4) |
71 | return; | 77 | return; |
@@ -81,14 +87,17 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
81 | writel(val << 4, aaci->base + AACI_SL2TX); | 87 | writel(val << 4, aaci->base + AACI_SL2TX); |
82 | writel(reg << 12, aaci->base + AACI_SL1TX); | 88 | writel(reg << 12, aaci->base + AACI_SL1TX); |
83 | 89 | ||
84 | /* | 90 | /* Initially, wait one frame period */ |
85 | * Wait for the transmission of both slots to complete. | 91 | udelay(FRAME_PERIOD_US); |
86 | */ | 92 | |
93 | /* And then wait an additional eight frame periods for it to be sent */ | ||
94 | timeout = FRAME_PERIOD_US * 8; | ||
87 | do { | 95 | do { |
96 | udelay(1); | ||
88 | v = readl(aaci->base + AACI_SLFR); | 97 | v = readl(aaci->base + AACI_SLFR); |
89 | } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout); | 98 | } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout); |
90 | 99 | ||
91 | if (!timeout) | 100 | if (v & (SLFR_1TXB|SLFR_2TXB)) |
92 | dev_err(&aaci->dev->dev, | 101 | dev_err(&aaci->dev->dev, |
93 | "timeout waiting for write to complete\n"); | 102 | "timeout waiting for write to complete\n"); |
94 | 103 | ||
@@ -101,9 +110,8 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
101 | static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 110 | static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
102 | { | 111 | { |
103 | struct aaci *aaci = ac97->private_data; | 112 | struct aaci *aaci = ac97->private_data; |
113 | int timeout, retries = 10; | ||
104 | u32 v; | 114 | u32 v; |
105 | int timeout = 5000; | ||
106 | int retries = 10; | ||
107 | 115 | ||
108 | if (ac97->num >= 4) | 116 | if (ac97->num >= 4) |
109 | return ~0; | 117 | return ~0; |
@@ -117,35 +125,34 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | |||
117 | */ | 125 | */ |
118 | writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); | 126 | writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); |
119 | 127 | ||
120 | /* | 128 | /* Initially, wait one frame period */ |
121 | * Wait for the transmission to complete. | 129 | udelay(FRAME_PERIOD_US); |
122 | */ | 130 | |
131 | /* And then wait an additional eight frame periods for it to be sent */ | ||
132 | timeout = FRAME_PERIOD_US * 8; | ||
123 | do { | 133 | do { |
134 | udelay(1); | ||
124 | v = readl(aaci->base + AACI_SLFR); | 135 | v = readl(aaci->base + AACI_SLFR); |
125 | } while ((v & SLFR_1TXB) && --timeout); | 136 | } while ((v & SLFR_1TXB) && --timeout); |
126 | 137 | ||
127 | if (!timeout) { | 138 | if (v & SLFR_1TXB) { |
128 | dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n"); | 139 | dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n"); |
129 | v = ~0; | 140 | v = ~0; |
130 | goto out; | 141 | goto out; |
131 | } | 142 | } |
132 | 143 | ||
133 | /* | 144 | /* Now wait for the response frame */ |
134 | * Give the AC'97 codec more than enough time | 145 | udelay(FRAME_PERIOD_US); |
135 | * to respond. (42us = ~2 frames at 48kHz.) | ||
136 | */ | ||
137 | udelay(42); | ||
138 | 146 | ||
139 | /* | 147 | /* And then wait an additional eight frame periods for data */ |
140 | * Wait for slot 2 to indicate data. | 148 | timeout = FRAME_PERIOD_US * 8; |
141 | */ | ||
142 | timeout = 5000; | ||
143 | do { | 149 | do { |
150 | udelay(1); | ||
144 | cond_resched(); | 151 | cond_resched(); |
145 | v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); | 152 | v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); |
146 | } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout); | 153 | } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout); |
147 | 154 | ||
148 | if (!timeout) { | 155 | if (v != (SLFR_1RXV|SLFR_2RXV)) { |
149 | dev_err(&aaci->dev->dev, "timeout on RX valid\n"); | 156 | dev_err(&aaci->dev->dev, "timeout on RX valid\n"); |
150 | v = ~0; | 157 | v = ~0; |
151 | goto out; | 158 | goto out; |
@@ -179,6 +186,7 @@ aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) | |||
179 | int timeout = 5000; | 186 | int timeout = 5000; |
180 | 187 | ||
181 | do { | 188 | do { |
189 | udelay(1); | ||
182 | val = readl(aacirun->base + AACI_SR); | 190 | val = readl(aacirun->base + AACI_SR); |
183 | } while (val & mask && timeout--); | 191 | } while (val & mask && timeout--); |
184 | } | 192 | } |
@@ -874,7 +882,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci) | |||
874 | * Give the AC'97 codec more than enough time | 882 | * Give the AC'97 codec more than enough time |
875 | * to wake up. (42us = ~2 frames at 48kHz.) | 883 | * to wake up. (42us = ~2 frames at 48kHz.) |
876 | */ | 884 | */ |
877 | udelay(42); | 885 | udelay(FRAME_PERIOD_US * 2); |
878 | 886 | ||
879 | ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); | 887 | ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); |
880 | if (ret) | 888 | if (ret) |
@@ -989,6 +997,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) | |||
989 | * disabling the channel doesn't clear the FIFO. | 997 | * disabling the channel doesn't clear the FIFO. |
990 | */ | 998 | */ |
991 | writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); | 999 | writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); |
1000 | readl(aaci->base + AACI_MAINCR); | ||
1001 | udelay(1); | ||
992 | writel(aaci->maincr, aaci->base + AACI_MAINCR); | 1002 | writel(aaci->maincr, aaci->base + AACI_MAINCR); |
993 | 1003 | ||
994 | /* | 1004 | /* |