1 /*
2 * Copyright 2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Jérôme Duval (korli@users.berlios.de)
7 */
8
9
10 #include "driver.h"
11
12 #define ALIGN(size, align) (((size) + align - 1) & ~(align - 1))
13 #define PAGE_ALIGN(size) (((size) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1))
14
15 #define STREAM_CMD 0x0 /* Command */
16 #define STREAM_STATUS 0x1 /* IRQ Status */
17 #define STREAM_PRD 0x4 /* PRD Table Address */
18
19 static const struct {
20 uint32 multi_rate;
21 uint32 rate;
22 } kRates[] = {
23 {B_SR_8000, 8000},
24 {B_SR_11025, 11025},
25 {B_SR_16000, 16000},
26 {B_SR_22050, 22050},
27 {B_SR_32000, 32000},
28 {B_SR_44100, 44100},
29 {B_SR_48000, 48000},
30 {B_SR_88200, 88200},
31 {B_SR_96000, 96000},
32 {B_SR_176400, 176400},
33 {B_SR_192000, 192000},
34 };
35
36 static int
geode_codec_wait(geode_controller * controller)37 geode_codec_wait(geode_controller *controller)
38 {
39 int i;
40
41 #define GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT 500
42 for (i = GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT; (i >= 0)
43 && (controller->Read32(ACC_CODEC_CNTL) & ACC_CODEC_CNTL_CMD_NEW); i--)
44 snooze(10);
45
46 return (i < 0);
47 }
48
49 uint16
geode_codec_read(geode_controller * controller,uint8 regno)50 geode_codec_read(geode_controller *controller, uint8 regno)
51 {
52 int i;
53 uint32 v;
54 ASSERT(regno >= 0);
55
56 controller->Write32(ACC_CODEC_CNTL,
57 ACC_CODEC_CNTL_READ_CMD | ACC_CODEC_CNTL_CMD_NEW |
58 ACC_CODEC_REG2ADDR(regno));
59
60 if (geode_codec_wait(controller) != B_OK) {
61 dprintf("codec busy (2)\n");
62 return 0xffff;
63 }
64
65 #define GCSCAUDIO_READ_CODEC_TIMEOUT 50
66 for (i = GCSCAUDIO_READ_CODEC_TIMEOUT; i >= 0; i--) {
67 v = controller->Read32(ACC_CODEC_STATUS);
68 if ((v & ACC_CODEC_STATUS_STS_NEW) &&
69 (ACC_CODEC_ADDR2REG(v) == regno))
70 break;
71
72 snooze(10);
73 }
74
75 if (i < 0) {
76 dprintf("codec busy (3)\n");
77 return 0xffff;
78 }
79
80 return v;
81 }
82
83 void
geode_codec_write(geode_controller * controller,uint8 regno,uint16 value)84 geode_codec_write(geode_controller *controller, uint8 regno, uint16 value)
85 {
86 ASSERT(regno >= 0);
87
88 controller->Write32(ACC_CODEC_CNTL,
89 ACC_CODEC_CNTL_WRITE_CMD |
90 ACC_CODEC_CNTL_CMD_NEW |
91 ACC_CODEC_REG2ADDR(regno) |
92 (value & ACC_CODEC_CNTL_CMD_DATA_MASK));
93
94 if (geode_codec_wait(controller) != B_OK) {
95 dprintf("codec busy (4)\n");
96 }
97 }
98
99
100 //! Called with interrupts off
101 static void
stream_handle_interrupt(geode_controller * controller,geode_stream * stream)102 stream_handle_interrupt(geode_controller* controller, geode_stream* stream)
103 {
104 uint8 status;
105 uint32 position, bufferSize;
106
107 if (!stream->running)
108 return;
109
110 status = stream->Read8(STREAM_STATUS);
111
112 if (status & ACC_BMx_STATUS_BM_EOP_ERR) {
113 dprintf("geode: stream status bus master error\n");
114 }
115 if (status & ACC_BMx_STATUS_EOP) {
116 dprintf("geode: stream status end of page\n");
117 }
118
119 position = controller->Read32(ACC_BM0_PNTR + stream->dma_offset);
120 bufferSize = ALIGN(stream->sample_size * stream->num_channels * stream->buffer_length, 128);
121
122 // Buffer Completed Interrupt
123 acquire_spinlock(&stream->lock);
124
125 stream->real_time = system_time();
126 stream->frames_count += stream->buffer_length;
127 stream->buffer_cycle = 1 - (position / (bufferSize + 1)); // added 1 to avoid having 2
128
129 release_spinlock(&stream->lock);
130
131 release_sem_etc(stream->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
132 }
133
134
135 static int32
geode_interrupt_handler(geode_controller * controller)136 geode_interrupt_handler(geode_controller* controller)
137 {
138 uint16 intr = controller->Read16(ACC_IRQ_STATUS);
139 if (intr == 0)
140 return B_UNHANDLED_INTERRUPT;
141
142 for (uint32 index = 0; index < GEODE_MAX_STREAMS; index++) {
143 if (controller->streams[index]
144 && (intr & controller->streams[index]->status) != 0) {
145 stream_handle_interrupt(controller,
146 controller->streams[index]);
147 }
148 }
149
150 return B_HANDLED_INTERRUPT;
151 }
152
153
154 static status_t
reset_controller(geode_controller * controller)155 reset_controller(geode_controller* controller)
156 {
157 controller->Write32(ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST
158 | ACC_CODEC_CNTL_CMD_NEW);
159
160 if (geode_codec_wait(controller) != B_OK) {
161 dprintf("codec reset busy (1)\n");
162 }
163
164 // stop streams
165
166 // stop DMA
167
168 // reset DMA position buffer
169
170 return B_OK;
171 }
172
173 // #pragma mark - public stream functions
174
175
176 void
geode_stream_delete(geode_stream * stream)177 geode_stream_delete(geode_stream* stream)
178 {
179 if (stream->buffer_ready_sem >= B_OK)
180 delete_sem(stream->buffer_ready_sem);
181
182 if (stream->buffer_area >= B_OK)
183 delete_area(stream->buffer_area);
184
185 if (stream->buffer_descriptors_area >= B_OK)
186 delete_area(stream->buffer_descriptors_area);
187
188 free(stream);
189 }
190
191
192 geode_stream*
geode_stream_new(geode_controller * controller,int type)193 geode_stream_new(geode_controller* controller, int type)
194 {
195 geode_stream* stream = (geode_stream*)calloc(1, sizeof(geode_stream));
196 if (stream == NULL)
197 return NULL;
198
199 stream->buffer_ready_sem = B_ERROR;
200 stream->buffer_area = B_ERROR;
201 stream->buffer_descriptors_area = B_ERROR;
202 stream->type = type;
203 stream->controller = controller;
204
205 switch (type) {
206 case STREAM_PLAYBACK:
207 stream->status = ACC_IRQ_STATUS_BM0_IRQ_STS;
208 stream->offset = 0;
209 stream->dma_offset = 0;
210 stream->ac97_rate_reg = AC97_PCM_FRONT_DAC_RATE;
211 break;
212
213 case STREAM_RECORD:
214 stream->status = ACC_IRQ_STATUS_BM1_IRQ_STS;
215 stream->offset = 0x8;
216 stream->dma_offset = 0x4;
217 stream->ac97_rate_reg = AC97_PCM_L_R_ADC_RATE;
218 break;
219
220 default:
221 dprintf("%s: Unknown stream type %d!\n", __func__, type);
222 free(stream);
223 stream = NULL;
224 }
225
226 controller->streams[controller->num_streams++] = stream;
227 return stream;
228 }
229
230
231 /*! Starts a stream's DMA engine, and enables generating and receiving
232 interrupts for this stream.
233 */
234 status_t
geode_stream_start(geode_stream * stream)235 geode_stream_start(geode_stream* stream)
236 {
237 uint8 value;
238 dprintf("geode_stream_start()\n");
239 stream->buffer_ready_sem = create_sem(0, stream->type == STREAM_PLAYBACK
240 ? "geode_playback_sem" : "geode_record_sem");
241 if (stream->buffer_ready_sem < B_OK)
242 return stream->buffer_ready_sem;
243
244 if (stream->type == STREAM_PLAYBACK)
245 value = ACC_BMx_CMD_WRITE;
246 else
247 value = ACC_BMx_CMD_READ;
248
249 stream->Write8(STREAM_CMD, value | ACC_BMx_CMD_BYTE_ORD_EL
250 | ACC_BMx_CMD_BM_CTL_ENABLE);
251
252 stream->running = true;
253 return B_OK;
254 }
255
256
257 /*! Stops the stream's DMA engine, and turns off interrupts for this
258 stream.
259 */
260 status_t
geode_stream_stop(geode_stream * stream)261 geode_stream_stop(geode_stream* stream)
262 {
263 dprintf("geode_stream_stop()\n");
264 stream->Write8(STREAM_CMD, ACC_BMx_CMD_BM_CTL_DISABLE);
265
266 stream->running = false;
267 delete_sem(stream->buffer_ready_sem);
268 stream->buffer_ready_sem = -1;
269
270 return B_OK;
271 }
272
273
274 status_t
geode_stream_setup_buffers(geode_stream * stream,const char * desc)275 geode_stream_setup_buffers(geode_stream* stream, const char* desc)
276 {
277 uint32 bufferSize, alloc;
278 uint32 index;
279 physical_entry pe;
280 struct acc_prd* bufferDescriptors;
281 uint8* buffer;
282 status_t rc;
283
284 /* Clear previously allocated memory */
285 if (stream->buffer_area >= B_OK) {
286 delete_area(stream->buffer_area);
287 stream->buffer_area = B_ERROR;
288 }
289
290 if (stream->buffer_descriptors_area >= B_OK) {
291 delete_area(stream->buffer_descriptors_area);
292 stream->buffer_descriptors_area = B_ERROR;
293 }
294
295 /* Calculate size of buffer (aligned to 128 bytes) */
296 bufferSize = stream->sample_size * stream->num_channels
297 * stream->buffer_length;
298 bufferSize = ALIGN(bufferSize, 128);
299
300 dprintf("geode: sample size %" B_PRIu32 ", num channels %" B_PRIu32 ", buffer length %"
301 B_PRIu32 "\n",
302 stream->sample_size, stream->num_channels, stream->buffer_length);
303
304 /* Calculate total size of all buffers (aligned to size of B_PAGE_SIZE) */
305 alloc = bufferSize * stream->num_buffers;
306 alloc = PAGE_ALIGN(alloc);
307
308 /* Allocate memory for buffers */
309 stream->buffer_area = create_area("geode buffers", (void**)&buffer,
310 B_ANY_KERNEL_ADDRESS, alloc, B_32_BIT_CONTIGUOUS,
311 B_READ_AREA | B_WRITE_AREA);
312 // TODO: The rest of the code doesn't deal correctly with physical
313 // addresses > 4 GB, so we have to force 32 bit addresses here.
314 if (stream->buffer_area < B_OK)
315 return stream->buffer_area;
316
317 /* Get the physical address of memory */
318 rc = get_memory_map(buffer, alloc, &pe, 1);
319 if (rc != B_OK) {
320 delete_area(stream->buffer_area);
321 return rc;
322 }
323
324 phys_addr_t bufferPhysicalAddress = pe.address;
325
326 dprintf("%s(%s): Allocated %" B_PRId32 " bytes for %" B_PRIu32 " buffers\n", __func__, desc,
327 alloc, stream->num_buffers);
328
329 /* Store pointers (both virtual/physical) */
330 for (index = 0; index < stream->num_buffers; index++) {
331 stream->buffers[index] = buffer + (index * bufferSize);
332 stream->physical_buffers[index] = bufferPhysicalAddress
333 + (index * bufferSize);
334 }
335
336 /* Now allocate BDL for buffer range */
337 alloc = stream->num_buffers * sizeof(struct acc_prd) + 1;
338 alloc = PAGE_ALIGN(alloc);
339
340 stream->buffer_descriptors_area = create_area("geode buffer descriptors",
341 (void**)&bufferDescriptors, B_ANY_KERNEL_ADDRESS, alloc,
342 B_32_BIT_CONTIGUOUS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
343 // TODO: The rest of the code doesn't deal correctly with physical
344 // addresses > 4 GB, so we have to force 32 bit addresses here.
345 if (stream->buffer_descriptors_area < B_OK) {
346 delete_area(stream->buffer_area);
347 return stream->buffer_descriptors_area;
348 }
349
350 /* Get the physical address of memory */
351 rc = get_memory_map(bufferDescriptors, alloc, &pe, 1);
352 if (rc != B_OK) {
353 delete_area(stream->buffer_area);
354 delete_area(stream->buffer_descriptors_area);
355 return rc;
356 }
357
358 stream->physical_buffer_descriptors = pe.address;
359
360 dprintf("%s(%s): Allocated %" B_PRIu32 " bytes for %" B_PRIu32 " BDLEs\n", __func__, desc,
361 alloc, stream->num_buffers);
362
363 /* Setup buffer descriptor list (BDL) entries */
364 for (index = 0; index < stream->num_buffers; index++, bufferDescriptors++) {
365 bufferDescriptors->address = stream->physical_buffers[index];
366 bufferDescriptors->ctrlsize = bufferSize | ACC_BMx_PRD_CTRL_EOP;
367 // we want an interrupt after every buffer
368 }
369 bufferDescriptors->address = stream->physical_buffer_descriptors;
370 bufferDescriptors->ctrlsize = ACC_BMx_PRD_CTRL_JMP;
371
372 for (index = 0; index < sizeof(kRates) / sizeof(kRates[0]); index++) {
373 if (kRates[index].multi_rate == stream->sample_rate) {
374 stream->rate = kRates[index].rate;
375 break;
376 }
377 }
378
379 /* Configure stream registers */
380 dprintf("IRA: %s: setup stream SR=%" B_PRIu32 "\n", __func__, stream->rate);
381
382 stream->Write32(STREAM_PRD, stream->physical_buffer_descriptors);
383
384 ac97_set_rate(stream->controller->ac97, stream->ac97_rate_reg, stream->rate);
385 snooze(1000);
386 return B_OK;
387 }
388
389
390 // #pragma mark - public controller functions
391
392
393 /*! Setup hardware for use; detect codecs; etc */
394 status_t
geode_hw_init(geode_controller * controller)395 geode_hw_init(geode_controller* controller)
396 {
397 uint16 cmd;
398 status_t status;
399
400 cmd = (gPci->read_pci_config)(controller->pci_info.bus,
401 controller->pci_info.device, controller->pci_info.function, PCI_command, 2);
402 if (!(cmd & PCI_command_master)) {
403 (gPci->write_pci_config)(controller->pci_info.bus,
404 controller->pci_info.device, controller->pci_info.function,
405 PCI_command, 2, cmd | PCI_command_master);
406 dprintf("geode: enabling PCI bus mastering\n");
407 }
408
409 controller->nabmbar = controller->pci_info.u.h0.base_registers[0];
410
411 /* Absolute minimum hw is online; we can now install interrupt handler */
412 controller->irq = controller->pci_info.u.h0.interrupt_line;
413 status = install_io_interrupt_handler(controller->irq,
414 (interrupt_handler)geode_interrupt_handler, controller, 0);
415 if (status != B_OK)
416 goto error;
417
418 /* Get controller into valid state */
419 status = reset_controller(controller);
420 if (status != B_OK) {
421 dprintf("geode: reset_controller failed\n");
422 goto reset_failed;
423 }
424
425 /* attach the codec */
426 ac97_attach(&controller->ac97, (codec_reg_read)geode_codec_read,
427 (codec_reg_write)geode_codec_write, controller,
428 controller->pci_info.u.h0.subsystem_vendor_id,
429 controller->pci_info.u.h0.subsystem_id);
430
431 snooze(1000);
432
433 controller->multi = (geode_multi*)calloc(1, sizeof(geode_multi));
434 if (controller->multi == NULL)
435 return B_NO_MEMORY;
436
437 controller->playback_stream = geode_stream_new(controller, STREAM_PLAYBACK);
438 controller->record_stream = geode_stream_new(controller, STREAM_RECORD);
439
440 return B_OK;
441
442 reset_failed:
443 remove_io_interrupt_handler(controller->irq,
444 (interrupt_handler)geode_interrupt_handler, controller);
445 error:
446 dprintf("geode: ERROR: %s(%" B_PRId32 ")\n", strerror(status), status);
447
448 return status;
449 }
450
451
452 /*! Stop any activity */
453 void
geode_hw_stop(geode_controller * controller)454 geode_hw_stop(geode_controller* controller)
455 {
456 int index;
457
458 /* Stop all audio streams */
459 for (index = 0; index < GEODE_MAX_STREAMS; index++) {
460 if (controller->streams[index] && controller->streams[index]->running)
461 geode_stream_stop(controller->streams[index]);
462 }
463 }
464
465
466 /*! Free resources */
467 void
geode_hw_uninit(geode_controller * controller)468 geode_hw_uninit(geode_controller* controller)
469 {
470 if (controller == NULL)
471 return;
472
473 /* Stop all audio streams */
474 geode_hw_stop(controller);
475
476 reset_controller(controller);
477
478 remove_io_interrupt_handler(controller->irq,
479 (interrupt_handler)geode_interrupt_handler, controller);
480
481 free(controller->multi);
482
483 geode_stream_delete(controller->playback_stream);
484 geode_stream_delete(controller->record_stream);
485
486 }
487
488