aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-11-17 04:32:43 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:16:51 -0500
commit33ea25c113a7d63645b10ed89851e08f7c984d1a (patch)
tree58433ce44c87af1565f250a141006e73e96cce13 /sound
parent6560c349c501388a1f3030d02fb49e7067e6597e (diff)
[ALSA] au1x00 - Code clean up
Modules: MIPS AU1x00 driver Clean up snd-au1x00 driver code: - Remove global variables - Remove old compatibility codes - Fix DMA-link allocation/release functions in hw_params and hw_free callbacks (they may be called multiple times) - Fix spinlocks Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/mips/au1x00.c300
1 files changed, 150 insertions, 150 deletions
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index d08a42b24b1f..a8f9a3b6e73d 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -50,12 +50,7 @@
50MODULE_AUTHOR("Charles Eidsness <charles@cooper-street.com>"); 50MODULE_AUTHOR("Charles Eidsness <charles@cooper-street.com>");
51MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver"); 51MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver");
52MODULE_LICENSE("GPL"); 52MODULE_LICENSE("GPL");
53#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
54MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}"); 53MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}");
55#else
56MODULE_CLASSES("{sound}");
57MODULE_DEVICES("{{AMD,Au1000 AC'97}}");
58#endif
59 54
60#define PLAYBACK 0 55#define PLAYBACK 0
61#define CAPTURE 1 56#define CAPTURE 1
@@ -68,8 +63,6 @@ MODULE_DEVICES("{{AMD,Au1000 AC'97}}");
68#define READ_WAIT 2 63#define READ_WAIT 2
69#define RW_DONE 3 64#define RW_DONE 3
70 65
71DECLARE_WAIT_QUEUE_HEAD(ac97_command_wq);
72
73typedef struct au1000_period au1000_period_t; 66typedef struct au1000_period au1000_period_t;
74struct au1000_period 67struct au1000_period
75{ 68{
@@ -94,7 +87,8 @@ struct audio_stream {
94 int dma; 87 int dma;
95 spinlock_t dma_lock; 88 spinlock_t dma_lock;
96 au1000_period_t * buffer; 89 au1000_period_t * buffer;
97 unsigned long period_size; 90 unsigned int period_size;
91 unsigned int periods;
98}; 92};
99 93
100typedef struct snd_card_au1000 { 94typedef struct snd_card_au1000 {
@@ -109,11 +103,9 @@ typedef struct snd_card_au1000 {
109 audio_stream_t *stream[2]; /* playback & capture */ 103 audio_stream_t *stream[2]; /* playback & capture */
110} au1000_t; 104} au1000_t;
111 105
112static au1000_t *au1000 = NULL;
113
114/*--------------------------- Local Functions --------------------------------*/ 106/*--------------------------- Local Functions --------------------------------*/
115static void 107static void
116au1000_set_ac97_xmit_slots(long xmit_slots) 108au1000_set_ac97_xmit_slots(au1000_t *au1000, long xmit_slots)
117{ 109{
118 u32 volatile ac97_config; 110 u32 volatile ac97_config;
119 111
@@ -126,7 +118,7 @@ au1000_set_ac97_xmit_slots(long xmit_slots)
126} 118}
127 119
128static void 120static void
129au1000_set_ac97_recv_slots(long recv_slots) 121au1000_set_ac97_recv_slots(au1000_t *au1000, long recv_slots)
130{ 122{
131 u32 volatile ac97_config; 123 u32 volatile ac97_config;
132 124
@@ -140,79 +132,92 @@ au1000_set_ac97_recv_slots(long recv_slots)
140 132
141 133
142static void 134static void
143au1000_dma_stop(audio_stream_t *stream) 135au1000_release_dma_link(audio_stream_t *stream)
144{ 136{
145 unsigned long flags;
146 au1000_period_t * pointer; 137 au1000_period_t * pointer;
147 au1000_period_t * pointer_next; 138 au1000_period_t * pointer_next;
148 139
149 if (stream->buffer != NULL) { 140 stream->period_size = 0;
150 spin_lock_irqsave(&stream->dma_lock, flags); 141 stream->periods = 0;
151 disable_dma(stream->dma); 142 pointer = stream->buffer;
152 spin_unlock_irqrestore(&stream->dma_lock, flags); 143 if (! pointer)
144 return;
145 do {
146 pointer_next = pointer->next;
147 kfree(pointer);
148 pointer = pointer_next;
149 } while (pointer != stream->buffer);
150 stream->buffer = NULL;
151}
152
153static int
154au1000_setup_dma_link(audio_stream_t *stream, unsigned int period_bytes,
155 unsigned int periods)
156{
157 snd_pcm_substream_t *substream = stream->substream;
158 snd_pcm_runtime_t *runtime = substream->runtime;
159 unsigned long dma_start;
160 int i;
161
162 dma_start = virt_to_phys(runtime->dma_area);
153 163
154 pointer = stream->buffer; 164 if (stream->period_size == period_bytes &&
155 pointer_next = stream->buffer->next; 165 stream->periods == periods)
166 return 0; /* not changed */
156 167
157 do { 168 au1000_release_dma_link(stream);
158 kfree(pointer);
159 pointer = pointer_next;
160 pointer_next = pointer->next;
161 } while (pointer != stream->buffer);
162 169
163 stream->buffer = NULL; 170 stream->period_size = period_bytes;
171 stream->periods = periods;
172
173 stream->buffer = kmalloc(sizeof(au1000_period_t), GFP_KERNEL);
174 if (! stream->buffer)
175 return -ENOMEM;
176 pointer = stream->buffer;
177 for (i = 0; i < periods; i++) {
178 pointer->start = (u32)(dma_start + (i * period_bytes));
179 pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1);
180 if (i < periods - 1) {
181 pointer->next = kmalloc(sizeof(struct au1000_period), GFP_KERNEL);
182 if (! pointer->next) {
183 au1000_release_dma_link(stream);
184 return -ENOMEM;
185 }
186 pointer = pointer->next;
187 }
164 } 188 }
189 pointer->next = stream->buffer;
190 return 0;
165} 191}
166 192
167static void 193static void
168au1000_dma_start(audio_stream_t *stream) 194au1000_dma_stop(audio_stream_t *stream)
169{ 195{
170 snd_pcm_substream_t *substream = stream->substream; 196 snd_assert(stream->buffer, return);
171 snd_pcm_runtime_t *runtime = substream->runtime; 197 disable_dma(stream->dma);
198}
172 199
173 unsigned long flags, dma_start; 200static void
174 int i; 201au1000_dma_start(audio_stream_t *stream)
175 au1000_period_t * pointer; 202{
203 snd_assert(stream->buffer, return);
176 204
177 if (stream->buffer == NULL) { 205 init_dma(stream->dma);
178 dma_start = virt_to_phys(runtime->dma_area); 206 if (get_dma_active_buffer(stream->dma) == 0) {
179 207 clear_dma_done0(stream->dma);
180 stream->period_size = frames_to_bytes(runtime, 208 set_dma_addr0(stream->dma, stream->buffer->start);
181 runtime->period_size); 209 set_dma_count0(stream->dma, stream->period_size >> 1);
182 stream->buffer = kmalloc(sizeof(au1000_period_t), GFP_KERNEL); 210 set_dma_addr1(stream->dma, stream->buffer->next->start);
183 pointer = stream->buffer; 211 set_dma_count1(stream->dma, stream->period_size >> 1);
184 for (i = 0 ; i < runtime->periods ; i++) { 212 } else {
185 pointer->start = (u32)(dma_start + 213 clear_dma_done1(stream->dma);
186 (i * stream->period_size)); 214 set_dma_addr1(stream->dma, stream->buffer->start);
187 pointer->relative_end = (u32) 215 set_dma_count1(stream->dma, stream->period_size >> 1);
188 (((i+1) * stream->period_size) - 0x1); 216 set_dma_addr0(stream->dma, stream->buffer->next->start);
189 if ( i < runtime->periods - 1) { 217 set_dma_count0(stream->dma, stream->period_size >> 1);
190 pointer->next = kmalloc(sizeof(au1000_period_t)
191 , GFP_KERNEL);
192 pointer = pointer->next;
193 }
194 }
195 pointer->next = stream->buffer;
196
197 spin_lock_irqsave(&stream->dma_lock, flags);
198 init_dma(stream->dma);
199 if (get_dma_active_buffer(stream->dma) == 0) {
200 clear_dma_done0(stream->dma);
201 set_dma_addr0(stream->dma, stream->buffer->start);
202 set_dma_count0(stream->dma, stream->period_size >> 1);
203 set_dma_addr1(stream->dma, stream->buffer->next->start);
204 set_dma_count1(stream->dma, stream->period_size >> 1);
205 } else {
206 clear_dma_done1(stream->dma);
207 set_dma_addr1(stream->dma, stream->buffer->start);
208 set_dma_count1(stream->dma, stream->period_size >> 1);
209 set_dma_addr0(stream->dma, stream->buffer->next->start);
210 set_dma_count0(stream->dma, stream->period_size >> 1);
211 }
212 enable_dma_buffers(stream->dma);
213 start_dma(stream->dma);
214 spin_unlock_irqrestore(&stream->dma_lock, flags);
215 } 218 }
219 enable_dma_buffers(stream->dma);
220 start_dma(stream->dma);
216} 221}
217 222
218static irqreturn_t 223static irqreturn_t
@@ -238,11 +243,9 @@ au1000_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
238 enable_dma_buffer1(stream->dma); 243 enable_dma_buffer1(stream->dma);
239 break; 244 break;
240 case (DMA_D0 | DMA_D1): 245 case (DMA_D0 | DMA_D1):
241 spin_unlock(&stream->dma_lock);
242 printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma); 246 printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma);
243 au1000_dma_stop(stream); 247 au1000_dma_stop(stream);
244 au1000_dma_start(stream); 248 au1000_dma_start(stream);
245 spin_lock(&stream->dma_lock);
246 break; 249 break;
247 case (~DMA_D0 & ~DMA_D1): 250 case (~DMA_D0 & ~DMA_D1):
248 printk(KERN_ERR "DMA %d empty irq.\n",stream->dma); 251 printk(KERN_ERR "DMA %d empty irq.\n",stream->dma);
@@ -261,7 +264,7 @@ static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
261 .mask = 0, 264 .mask = 0,
262}; 265};
263 266
264static snd_pcm_hardware_t snd_au1000 = 267static snd_pcm_hardware_t snd_au1000_hw =
265{ 268{
266 .info = (SNDRV_PCM_INFO_INTERLEAVED | \ 269 .info = (SNDRV_PCM_INFO_INTERLEAVED | \
267 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), 270 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
@@ -283,10 +286,12 @@ static snd_pcm_hardware_t snd_au1000 =
283static int 286static int
284snd_au1000_playback_open(snd_pcm_substream_t * substream) 287snd_au1000_playback_open(snd_pcm_substream_t * substream)
285{ 288{
289 au1000_t *au1000 = substream->pcm->private_data;
290
286 au1000->stream[PLAYBACK]->substream = substream; 291 au1000->stream[PLAYBACK]->substream = substream;
287 au1000->stream[PLAYBACK]->buffer = NULL; 292 au1000->stream[PLAYBACK]->buffer = NULL;
288 substream->private_data = au1000->stream[PLAYBACK]; 293 substream->private_data = au1000->stream[PLAYBACK];
289 substream->runtime->hw = snd_au1000; 294 substream->runtime->hw = snd_au1000_hw;
290 return (snd_pcm_hw_constraint_list(substream->runtime, 0, 295 return (snd_pcm_hw_constraint_list(substream->runtime, 0,
291 SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); 296 SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
292} 297}
@@ -294,10 +299,12 @@ snd_au1000_playback_open(snd_pcm_substream_t * substream)
294static int 299static int
295snd_au1000_capture_open(snd_pcm_substream_t * substream) 300snd_au1000_capture_open(snd_pcm_substream_t * substream)
296{ 301{
302 au1000_t *au1000 = substream->pcm->private_data;
303
297 au1000->stream[CAPTURE]->substream = substream; 304 au1000->stream[CAPTURE]->substream = substream;
298 au1000->stream[CAPTURE]->buffer = NULL; 305 au1000->stream[CAPTURE]->buffer = NULL;
299 substream->private_data = au1000->stream[CAPTURE]; 306 substream->private_data = au1000->stream[CAPTURE];
300 substream->runtime->hw = snd_au1000; 307 substream->runtime->hw = snd_au1000_hw;
301 return (snd_pcm_hw_constraint_list(substream->runtime, 0, 308 return (snd_pcm_hw_constraint_list(substream->runtime, 0,
302 SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); 309 SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
303 310
@@ -306,6 +313,8 @@ snd_au1000_capture_open(snd_pcm_substream_t * substream)
306static int 313static int
307snd_au1000_playback_close(snd_pcm_substream_t * substream) 314snd_au1000_playback_close(snd_pcm_substream_t * substream)
308{ 315{
316 au1000_t *au1000 = substream->pcm->private_data;
317
309 au1000->stream[PLAYBACK]->substream = NULL; 318 au1000->stream[PLAYBACK]->substream = NULL;
310 return 0; 319 return 0;
311} 320}
@@ -313,6 +322,8 @@ snd_au1000_playback_close(snd_pcm_substream_t * substream)
313static int 322static int
314snd_au1000_capture_close(snd_pcm_substream_t * substream) 323snd_au1000_capture_close(snd_pcm_substream_t * substream)
315{ 324{
325 au1000_t *au1000 = substream->pcm->private_data;
326
316 au1000->stream[CAPTURE]->substream = NULL; 327 au1000->stream[CAPTURE]->substream = NULL;
317 return 0; 328 return 0;
318} 329}
@@ -321,25 +332,36 @@ static int
321snd_au1000_hw_params(snd_pcm_substream_t * substream, 332snd_au1000_hw_params(snd_pcm_substream_t * substream,
322 snd_pcm_hw_params_t * hw_params) 333 snd_pcm_hw_params_t * hw_params)
323{ 334{
324 return snd_pcm_lib_malloc_pages(substream, 335 audio_stream_t *stream = substream->private_data;
325 params_buffer_bytes(hw_params)); 336 int err;
337
338 err = snd_pcm_lib_malloc_pages(substream,
339 params_buffer_bytes(hw_params));
340 if (err < 0)
341 return err;
342 return au1000_setup_dma_link(stream,
343 params_period_bytes(hw_params),
344 params_periods(hw_params));
326} 345}
327 346
328static int 347static int
329snd_au1000_hw_free(snd_pcm_substream_t * substream) 348snd_au1000_hw_free(snd_pcm_substream_t * substream)
330{ 349{
350 audio_stream_t *stream = substream->private_data;
351 au1000_release_dma_link(stream);
331 return snd_pcm_lib_free_pages(substream); 352 return snd_pcm_lib_free_pages(substream);
332} 353}
333 354
334static int 355static int
335snd_au1000_playback_prepare(snd_pcm_substream_t * substream) 356snd_au1000_playback_prepare(snd_pcm_substream_t * substream)
336{ 357{
358 au1000_t *au1000 = substream->pcm->private_data;
337 snd_pcm_runtime_t *runtime = substream->runtime; 359 snd_pcm_runtime_t *runtime = substream->runtime;
338 360
339 if (runtime->channels == 1 ) 361 if (runtime->channels == 1)
340 au1000_set_ac97_xmit_slots(AC97_SLOT_4); 362 au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_4);
341 else 363 else
342 au1000_set_ac97_xmit_slots(AC97_SLOT_3 | AC97_SLOT_4); 364 au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
343 snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate); 365 snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
344 return 0; 366 return 0;
345} 367}
@@ -347,12 +369,13 @@ snd_au1000_playback_prepare(snd_pcm_substream_t * substream)
347static int 369static int
348snd_au1000_capture_prepare(snd_pcm_substream_t * substream) 370snd_au1000_capture_prepare(snd_pcm_substream_t * substream)
349{ 371{
372 au1000_t *au1000 = substream->pcm->private_data;
350 snd_pcm_runtime_t *runtime = substream->runtime; 373 snd_pcm_runtime_t *runtime = substream->runtime;
351 374
352 if (runtime->channels == 1 ) 375 if (runtime->channels == 1)
353 au1000_set_ac97_recv_slots(AC97_SLOT_4); 376 au1000_set_ac97_recv_slots(au1000, AC97_SLOT_4);
354 else 377 else
355 au1000_set_ac97_recv_slots(AC97_SLOT_3 | AC97_SLOT_4); 378 au1000_set_ac97_recv_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
356 snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); 379 snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
357 return 0; 380 return 0;
358} 381}
@@ -363,6 +386,7 @@ snd_au1000_trigger(snd_pcm_substream_t * substream, int cmd)
363 audio_stream_t *stream = substream->private_data; 386 audio_stream_t *stream = substream->private_data;
364 int err = 0; 387 int err = 0;
365 388
389 spin_lock(&stream->dma_lock);
366 switch (cmd) { 390 switch (cmd) {
367 case SNDRV_PCM_TRIGGER_START: 391 case SNDRV_PCM_TRIGGER_START:
368 au1000_dma_start(stream); 392 au1000_dma_start(stream);
@@ -374,6 +398,7 @@ snd_au1000_trigger(snd_pcm_substream_t * substream, int cmd)
374 err = -EINVAL; 398 err = -EINVAL;
375 break; 399 break;
376 } 400 }
401 spin_unlock(&stream->dma_lock);
377 return err; 402 return err;
378} 403}
379 404
@@ -382,12 +407,11 @@ snd_au1000_pointer(snd_pcm_substream_t * substream)
382{ 407{
383 audio_stream_t *stream = substream->private_data; 408 audio_stream_t *stream = substream->private_data;
384 snd_pcm_runtime_t *runtime = substream->runtime; 409 snd_pcm_runtime_t *runtime = substream->runtime;
385 unsigned long flags;
386 long location; 410 long location;
387 411
388 spin_lock_irqsave(&stream->dma_lock, flags); 412 spin_lock(&stream->dma_lock);
389 location = get_dma_residue(stream->dma); 413 location = get_dma_residue(stream->dma);
390 spin_unlock_irqrestore(&stream->dma_lock, flags); 414 spin_unlock(&stream->dma_lock);
391 location = stream->buffer->relative_end - location; 415 location = stream->buffer->relative_end - location;
392 if (location == -1) 416 if (location == -1)
393 location = 0; 417 location = 0;
@@ -438,6 +462,9 @@ snd_au1000_pcm_new(void)
438 pcm->info_flags = 0; 462 pcm->info_flags = 0;
439 strcpy(pcm->name, "Au1000 AC97 PCM"); 463 strcpy(pcm->name, "Au1000 AC97 PCM");
440 464
465 spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock);
466 spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);
467
441 flags = claim_dma_lock(); 468 flags = claim_dma_lock();
442 if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX, 469 if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
443 "AC97 TX", au1000_dma_interrupt, SA_INTERRUPT, 470 "AC97 TX", au1000_dma_interrupt, SA_INTERRUPT,
@@ -457,8 +484,6 @@ snd_au1000_pcm_new(void)
457 set_dma_mode(au1000->stream[CAPTURE]->dma, 484 set_dma_mode(au1000->stream[CAPTURE]->dma,
458 get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC); 485 get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC);
459 release_dma_lock(flags); 486 release_dma_lock(flags);
460 spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock);
461 spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);
462 au1000->pcm = pcm; 487 au1000->pcm = pcm;
463 return 0; 488 return 0;
464} 489}
@@ -469,9 +494,11 @@ snd_au1000_pcm_new(void)
469static unsigned short 494static unsigned short
470snd_au1000_ac97_read(ac97_t *ac97, unsigned short reg) 495snd_au1000_ac97_read(ac97_t *ac97, unsigned short reg)
471{ 496{
497 au1000_t *au1000 = ac97->private_data;
472 u32 volatile cmd; 498 u32 volatile cmd;
473 u16 volatile data; 499 u16 volatile data;
474 int i; 500 int i;
501
475 spin_lock(&au1000->ac97_lock); 502 spin_lock(&au1000->ac97_lock);
476/* would rather use the interupt than this polling but it works and I can't 503/* would rather use the interupt than this polling but it works and I can't
477get the interupt driven case to work efficiently */ 504get the interupt driven case to work efficiently */
@@ -505,8 +532,10 @@ get the interupt driven case to work efficiently */
505static void 532static void
506snd_au1000_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) 533snd_au1000_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
507{ 534{
535 au1000_t *au1000 = ac97->private_data;
508 u32 cmd; 536 u32 cmd;
509 int i; 537 int i;
538
510 spin_lock(&au1000->ac97_lock); 539 spin_lock(&au1000->ac97_lock);
511/* would rather use the interupt than this polling but it works and I can't 540/* would rather use the interupt than this polling but it works and I can't
512get the interupt driven case to work efficiently */ 541get the interupt driven case to work efficiently */
@@ -522,28 +551,13 @@ get the interupt driven case to work efficiently */
522 au1000->ac97_ioport->cmd = cmd; 551 au1000->ac97_ioport->cmd = cmd;
523 spin_unlock(&au1000->ac97_lock); 552 spin_unlock(&au1000->ac97_lock);
524} 553}
525static void
526snd_au1000_ac97_free(ac97_t *ac97)
527{
528 au1000->ac97 = NULL;
529}
530 554
531static int __devinit 555static int __devinit
532snd_au1000_ac97_new(void) 556snd_au1000_ac97_new(au1000_t *au1000)
533{ 557{
534 int err; 558 int err;
535
536#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
537 ac97_bus_t *pbus;
538 ac97_template_t ac97;
539 static ac97_bus_ops_t ops = {
540 .write = snd_au1000_ac97_write,
541 .read = snd_au1000_ac97_read,
542 };
543#else
544 ac97_bus_t bus, *pbus; 559 ac97_bus_t bus, *pbus;
545 ac97_t ac97; 560 ac97_t ac97;
546#endif
547 561
548 if ((au1000->ac97_res_port = request_region(AC97C_CONFIG, 562 if ((au1000->ac97_res_port = request_region(AC97C_CONFIG,
549 sizeof(au1000_ac97_reg_t), "Au1x00 AC97")) == NULL) { 563 sizeof(au1000_ac97_reg_t), "Au1x00 AC97")) == NULL) {
@@ -554,8 +568,6 @@ snd_au1000_ac97_new(void)
554 568
555 spin_lock_init(&au1000->ac97_lock); 569 spin_lock_init(&au1000->ac97_lock);
556 570
557 spin_lock(&au1000->ac97_lock);
558
559 /* configure pins for AC'97 571 /* configure pins for AC'97
560 TODO: move to board_setup.c */ 572 TODO: move to board_setup.c */
561 au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC); 573 au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC);
@@ -572,26 +584,16 @@ snd_au1000_ac97_new(void)
572 au1000->ac97_ioport->config = 0x0; 584 au1000->ac97_ioport->config = 0x0;
573 mdelay(5); 585 mdelay(5);
574 586
575 spin_unlock(&au1000->ac97_lock);
576
577 /* Initialise AC97 middle-layer */ 587 /* Initialise AC97 middle-layer */
578#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
579 if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0) 588 if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0)
580 return err; 589 return err;
581#else 590
582 memset(&bus, 0, sizeof(bus));
583 bus.write = snd_au1000_ac97_write;
584 bus.read = snd_au1000_ac97_read;
585 if ((err = snd_ac97_bus(au1000->card, &bus, &pbus)) < 0)
586 return err;
587#endif
588 memset(&ac97, 0, sizeof(ac97)); 591 memset(&ac97, 0, sizeof(ac97));
589 ac97.private_data = au1000; 592 ac97.private_data = au1000;
590 ac97.private_free = snd_au1000_ac97_free;
591 if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0) 593 if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0)
592 return err; 594 return err;
593 return 0;
594 595
596 return 0;
595} 597}
596 598
597/*------------------------------ Setup / Destroy ----------------------------*/ 599/*------------------------------ Setup / Destroy ----------------------------*/
@@ -599,6 +601,7 @@ snd_au1000_ac97_new(void)
599void 601void
600snd_au1000_free(snd_card_t *card) 602snd_au1000_free(snd_card_t *card)
601{ 603{
604 au1000_t *au1000 = card->private_data;
602 605
603 if (au1000->ac97_res_port) { 606 if (au1000->ac97_res_port) {
604 /* put internal AC97 block into reset */ 607 /* put internal AC97 block into reset */
@@ -614,73 +617,70 @@ snd_au1000_free(snd_card_t *card)
614 free_au1000_dma(au1000->stream[CAPTURE]->dma); 617 free_au1000_dma(au1000->stream[CAPTURE]->dma);
615 618
616 kfree(au1000->stream[PLAYBACK]); 619 kfree(au1000->stream[PLAYBACK]);
617 au1000->stream[PLAYBACK] = NULL;
618 kfree(au1000->stream[CAPTURE]); 620 kfree(au1000->stream[CAPTURE]);
619 au1000->stream[CAPTURE] = NULL;
620 kfree(au1000);
621 au1000 = NULL;
622
623} 621}
624 622
623
624static snd_card_t *au1000_card;
625
625static int __init 626static int __init
626au1000_init(void) 627au1000_init(void)
627{ 628{
628 int err; 629 int err;
630 snd_card_t *card;
631 au1000_t *au1000;
629 632
630 au1000 = kmalloc(sizeof(au1000_t), GFP_KERNEL); 633 card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(au1000_t));
631 if (au1000 == NULL) 634 if (card == NULL)
632 return -ENOMEM;
633 au1000->stream[PLAYBACK] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
634 if (au1000->stream[PLAYBACK] == NULL)
635 return -ENOMEM;
636 au1000->stream[CAPTURE] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
637 if (au1000->stream[CAPTURE] == NULL)
638 return -ENOMEM; 635 return -ENOMEM;
636
637 card->private_free = snd_au1000_free;
638 au1000 = card->private_data;
639 /* so that snd_au1000_free will work as intended */ 639 /* so that snd_au1000_free will work as intended */
640 au1000->card = card;
640 au1000->stream[PLAYBACK]->dma = -1; 641 au1000->stream[PLAYBACK]->dma = -1;
641 au1000->stream[CAPTURE]->dma = -1; 642 au1000->stream[CAPTURE]->dma = -1;
642 au1000->ac97_res_port = NULL; 643 au1000->ac97_res_port = NULL;
643 644 au1000->stream[PLAYBACK] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
644 au1000->card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(au1000_t)); 645 au1000->stream[CAPTURE] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
645 if (au1000->card == NULL) { 646 if (au1000->stream[PLAYBACK] == NULL ||
646 snd_au1000_free(au1000->card); 647 au1000->stream[CAPTURE] == NULL) {
648 snd_card_free(card);
647 return -ENOMEM; 649 return -ENOMEM;
648 } 650 }
649 651
650 au1000->card->private_data = (au1000_t *)au1000; 652 if ((err = snd_au1000_ac97_new(au1000)) < 0 ) {
651 au1000->card->private_free = snd_au1000_free; 653 snd_card_free(card);
652
653 if ((err = snd_au1000_ac97_new()) < 0 ) {
654 snd_card_free(au1000->card);
655 return err; 654 return err;
656 } 655 }
657 656
658 if ((err = snd_au1000_pcm_new()) < 0) { 657 if ((err = snd_au1000_pcm_new(au1000)) < 0) {
659 snd_card_free(au1000->card); 658 snd_card_free(card);
660 return err; 659 return err;
661 } 660 }
662 661
663 strcpy(au1000->card->driver, "AMD-Au1000-AC97"); 662 strcpy(card->driver, "Au1000-AC97");
664 strcpy(au1000->card->shortname, "Au1000-AC97"); 663 strcpy(card->shortname, "AMD Au1000-AC97");
665 sprintf(au1000->card->longname, "AMD Au1000--AC97 ALSA Driver"); 664 sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver");
666 665
667 if ((err = snd_card_set_generic_dev(au1000->card)) < 0) { 666 if ((err = snd_card_set_generic_dev(card)) < 0) {
668 snd_card_free(au1000->card); 667 snd_card_free(card);
669 return err; 668 return err;
670 } 669 }
671 670
672 if ((err = snd_card_register(au1000->card)) < 0) { 671 if ((err = snd_card_register(card)) < 0) {
673 snd_card_free(au1000->card); 672 snd_card_free(card);
674 return err; 673 return err;
675 } 674 }
676 675
677 printk( KERN_INFO "ALSA AC97: Driver Initialized\n" ); 676 printk( KERN_INFO "ALSA AC97: Driver Initialized\n" );
677 au1000_card = card;
678 return 0; 678 return 0;
679} 679}
680 680
681static void __exit au1000_exit(void) 681static void __exit au1000_exit(void)
682{ 682{
683 snd_card_free(au1000->card); 683 snd_card_free(au1000_card);
684} 684}
685 685
686module_init(au1000_init); 686module_init(au1000_init);