aboutsummaryrefslogtreecommitdiffstats
path: root/sound/arm/pxa2xx-ac97.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/arm/pxa2xx-ac97.c')
-rw-r--r--sound/arm/pxa2xx-ac97.c119
1 files changed, 60 insertions, 59 deletions
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index c96c8a2aa1c2..3acbc6023d19 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -37,69 +37,74 @@ static DECLARE_MUTEX(car_mutex);
37static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); 37static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
38static volatile long gsr_bits; 38static volatile long gsr_bits;
39 39
40static unsigned short pxa2xx_ac97_read(ac97_t *ac97, unsigned short reg) 40/*
41 * Beware PXA27x bugs:
42 *
43 * o Slot 12 read from modem space will hang controller.
44 * o CDONE, SDONE interrupt fails after any slot 12 IO.
45 *
46 * We therefore have an hybrid approach for waiting on SDONE (interrupt or
47 * 1 jiffy timeout if interrupt never comes).
48 */
49
50static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
41{ 51{
42 unsigned short val = -1; 52 unsigned short val = -1;
43 volatile u32 *reg_addr; 53 volatile u32 *reg_addr;
44 54
45 down(&car_mutex); 55 down(&car_mutex);
46 if (CAR & CAR_CAIP) {
47 printk(KERN_CRIT"%s: CAR_CAIP already set\n", __FUNCTION__);
48 goto out;
49 }
50 56
51 /* set up primary or secondary codec space */ 57 /* set up primary or secondary codec space */
52 reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; 58 reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
53 reg_addr += (reg >> 1); 59 reg_addr += (reg >> 1);
54 60
55 /* start read access across the ac97 link */ 61 /* start read access across the ac97 link */
62 GSR = GSR_CDONE | GSR_SDONE;
56 gsr_bits = 0; 63 gsr_bits = 0;
57 val = *reg_addr; 64 val = *reg_addr;
58 if (reg == AC97_GPIO_STATUS) 65 if (reg == AC97_GPIO_STATUS)
59 goto out; 66 goto out;
60 wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); 67 if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
61 if (!gsr_bits & GSR_SDONE) { 68 !((GSR | gsr_bits) & GSR_SDONE)) {
62 printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", 69 printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
63 __FUNCTION__, reg, gsr_bits); 70 __FUNCTION__, reg, GSR | gsr_bits);
64 val = -1; 71 val = -1;
65 goto out; 72 goto out;
66 } 73 }
67 74
68 /* valid data now */ 75 /* valid data now */
76 GSR = GSR_CDONE | GSR_SDONE;
69 gsr_bits = 0; 77 gsr_bits = 0;
70 val = *reg_addr; 78 val = *reg_addr;
71 /* but we've just started another cycle... */ 79 /* but we've just started another cycle... */
72 wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); 80 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
73 81
74out: up(&car_mutex); 82out: up(&car_mutex);
75 return val; 83 return val;
76} 84}
77 85
78static void pxa2xx_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) 86static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
79{ 87{
80 volatile u32 *reg_addr; 88 volatile u32 *reg_addr;
81 89
82 down(&car_mutex); 90 down(&car_mutex);
83 91
84 if (CAR & CAR_CAIP) {
85 printk(KERN_CRIT "%s: CAR_CAIP already set\n", __FUNCTION__);
86 goto out;
87 }
88
89 /* set up primary or secondary codec space */ 92 /* set up primary or secondary codec space */
90 reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; 93 reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
91 reg_addr += (reg >> 1); 94 reg_addr += (reg >> 1);
95
96 GSR = GSR_CDONE | GSR_SDONE;
92 gsr_bits = 0; 97 gsr_bits = 0;
93 *reg_addr = val; 98 *reg_addr = val;
94 wait_event_timeout(gsr_wq, gsr_bits & GSR_CDONE, 1); 99 if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
95 if (!gsr_bits & GSR_SDONE) 100 !((GSR | gsr_bits) & GSR_CDONE))
96 printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", 101 printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
97 __FUNCTION__, reg, gsr_bits); 102 __FUNCTION__, reg, GSR | gsr_bits);
98 103
99out: up(&car_mutex); 104 up(&car_mutex);
100} 105}
101 106
102static void pxa2xx_ac97_reset(ac97_t *ac97) 107static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
103{ 108{
104 /* First, try cold reset */ 109 /* First, try cold reset */
105 GCR &= GCR_COLD_RST; /* clear everything but nCRST */ 110 GCR &= GCR_COLD_RST; /* clear everything but nCRST */
@@ -172,13 +177,13 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)
172 return IRQ_NONE; 177 return IRQ_NONE;
173} 178}
174 179
175static ac97_bus_ops_t pxa2xx_ac97_ops = { 180static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
176 .read = pxa2xx_ac97_read, 181 .read = pxa2xx_ac97_read,
177 .write = pxa2xx_ac97_write, 182 .write = pxa2xx_ac97_write,
178 .reset = pxa2xx_ac97_reset, 183 .reset = pxa2xx_ac97_reset,
179}; 184};
180 185
181static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = { 186static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = {
182 .name = "AC97 PCM out", 187 .name = "AC97 PCM out",
183 .dev_addr = __PREG(PCDR), 188 .dev_addr = __PREG(PCDR),
184 .drcmr = &DRCMRTXPCDR, 189 .drcmr = &DRCMRTXPCDR,
@@ -186,7 +191,7 @@ static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = {
186 DCMD_BURST32 | DCMD_WIDTH4, 191 DCMD_BURST32 | DCMD_WIDTH4,
187}; 192};
188 193
189static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = { 194static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = {
190 .name = "AC97 PCM in", 195 .name = "AC97 PCM in",
191 .dev_addr = __PREG(PCDR), 196 .dev_addr = __PREG(PCDR),
192 .drcmr = &DRCMRRXPCDR, 197 .drcmr = &DRCMRRXPCDR,
@@ -194,12 +199,12 @@ static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = {
194 DCMD_BURST32 | DCMD_WIDTH4, 199 DCMD_BURST32 | DCMD_WIDTH4,
195}; 200};
196 201
197static snd_pcm_t *pxa2xx_ac97_pcm; 202static struct snd_pcm *pxa2xx_ac97_pcm;
198static ac97_t *pxa2xx_ac97_ac97; 203static struct snd_ac97 *pxa2xx_ac97_ac97;
199 204
200static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream) 205static int pxa2xx_ac97_pcm_startup(struct snd_pcm_substream *substream)
201{ 206{
202 snd_pcm_runtime_t *runtime = substream->runtime; 207 struct snd_pcm_runtime *runtime = substream->runtime;
203 pxa2xx_audio_ops_t *platform_ops; 208 pxa2xx_audio_ops_t *platform_ops;
204 int r; 209 int r;
205 210
@@ -218,7 +223,7 @@ static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream)
218 return 0; 223 return 0;
219} 224}
220 225
221static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream) 226static void pxa2xx_ac97_pcm_shutdown(struct snd_pcm_substream *substream)
222{ 227{
223 pxa2xx_audio_ops_t *platform_ops; 228 pxa2xx_audio_ops_t *platform_ops;
224 229
@@ -227,15 +232,15 @@ static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream)
227 platform_ops->shutdown(substream, platform_ops->priv); 232 platform_ops->shutdown(substream, platform_ops->priv);
228} 233}
229 234
230static int pxa2xx_ac97_pcm_prepare(snd_pcm_substream_t *substream) 235static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream)
231{ 236{
232 snd_pcm_runtime_t *runtime = substream->runtime; 237 struct snd_pcm_runtime *runtime = substream->runtime;
233 int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 238 int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
234 AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; 239 AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
235 return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate); 240 return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate);
236} 241}
237 242
238static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = { 243static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = {
239 .playback_params = &pxa2xx_ac97_pcm_out, 244 .playback_params = &pxa2xx_ac97_pcm_out,
240 .capture_params = &pxa2xx_ac97_pcm_in, 245 .capture_params = &pxa2xx_ac97_pcm_in,
241 .startup = pxa2xx_ac97_pcm_startup, 246 .startup = pxa2xx_ac97_pcm_startup,
@@ -245,39 +250,37 @@ static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = {
245 250
246#ifdef CONFIG_PM 251#ifdef CONFIG_PM
247 252
248static int pxa2xx_ac97_do_suspend(snd_card_t *card, pm_message_t state) 253static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state)
249{ 254{
250 if (card->power_state != SNDRV_CTL_POWER_D3cold) { 255 pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
251 pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; 256
252 snd_pcm_suspend_all(pxa2xx_ac97_pcm); 257 snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
253 snd_ac97_suspend(pxa2xx_ac97_ac97); 258 snd_pcm_suspend_all(pxa2xx_ac97_pcm);
254 snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); 259 snd_ac97_suspend(pxa2xx_ac97_ac97);
255 if (platform_ops && platform_ops->suspend) 260 if (platform_ops && platform_ops->suspend)
256 platform_ops->suspend(platform_ops->priv); 261 platform_ops->suspend(platform_ops->priv);
257 GCR |= GCR_ACLINK_OFF; 262 GCR |= GCR_ACLINK_OFF;
258 pxa_set_cken(CKEN2_AC97, 0); 263 pxa_set_cken(CKEN2_AC97, 0);
259 }
260 264
261 return 0; 265 return 0;
262} 266}
263 267
264static int pxa2xx_ac97_do_resume(snd_card_t *card) 268static int pxa2xx_ac97_do_resume(struct snd_card *card)
265{ 269{
266 if (card->power_state != SNDRV_CTL_POWER_D0) { 270 pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
267 pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; 271
268 pxa_set_cken(CKEN2_AC97, 1); 272 pxa_set_cken(CKEN2_AC97, 1);
269 if (platform_ops && platform_ops->resume) 273 if (platform_ops && platform_ops->resume)
270 platform_ops->resume(platform_ops->priv); 274 platform_ops->resume(platform_ops->priv);
271 snd_ac97_resume(pxa2xx_ac97_ac97); 275 snd_ac97_resume(pxa2xx_ac97_ac97);
272 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 276 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
273 }
274 277
275 return 0; 278 return 0;
276} 279}
277 280
278static int pxa2xx_ac97_suspend(struct platform_device *dev, pm_message_t state) 281static int pxa2xx_ac97_suspend(struct platform_device *dev, pm_message_t state)
279{ 282{
280 snd_card_t *card = platform_get_drvdata(dev); 283 struct snd_card *card = platform_get_drvdata(dev);
281 int ret = 0; 284 int ret = 0;
282 285
283 if (card) 286 if (card)
@@ -288,7 +291,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *dev, pm_message_t state)
288 291
289static int pxa2xx_ac97_resume(struct platform_device *dev) 292static int pxa2xx_ac97_resume(struct platform_device *dev)
290{ 293{
291 snd_card_t *card = platform_get_drvdata(dev); 294 struct snd_card *card = platform_get_drvdata(dev);
292 int ret = 0; 295 int ret = 0;
293 296
294 if (card) 297 if (card)
@@ -304,9 +307,9 @@ static int pxa2xx_ac97_resume(struct platform_device *dev)
304 307
305static int pxa2xx_ac97_probe(struct platform_device *dev) 308static int pxa2xx_ac97_probe(struct platform_device *dev)
306{ 309{
307 snd_card_t *card; 310 struct snd_card *card;
308 ac97_bus_t *ac97_bus; 311 struct snd_ac97_bus *ac97_bus;
309 ac97_template_t ac97_template; 312 struct snd_ac97_template ac97_template;
310 int ret; 313 int ret;
311 314
312 ret = -ENOMEM; 315 ret = -ENOMEM;
@@ -349,8 +352,6 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
349 snprintf(card->longname, sizeof(card->longname), 352 snprintf(card->longname, sizeof(card->longname),
350 "%s (%s)", dev->dev.driver->name, card->mixername); 353 "%s (%s)", dev->dev.driver->name, card->mixername);
351 354
352 snd_card_set_pm_callback(card, pxa2xx_ac97_do_suspend,
353 pxa2xx_ac97_do_resume, NULL);
354 ret = snd_card_register(card); 355 ret = snd_card_register(card);
355 if (ret == 0) { 356 if (ret == 0) {
356 platform_set_drvdata(dev, card); 357 platform_set_drvdata(dev, card);
@@ -370,7 +371,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
370 371
371static int pxa2xx_ac97_remove(struct platform_device *dev) 372static int pxa2xx_ac97_remove(struct platform_device *dev)
372{ 373{
373 snd_card_t *card = platform_get_drvdata(dev); 374 struct snd_card *card = platform_get_drvdata(dev);
374 375
375 if (card) { 376 if (card) {
376 snd_card_free(card); 377 snd_card_free(card);