BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / drivers / audio / ac97 / es1370 / es1370.c
blobf5ecedffc5ba0e3f5072b8e986bc38e162a9870d
1 /*
2 * ES1370 Haiku Driver for ES1370 audio
4 * Copyright 2002-2007, Haiku, Inc.
5 * Distributed under the terms of the MIT License.
7 * Authors:
8 * Jerome Duval, jerome.duval@free.fr
9 */
11 #include <KernelExport.h>
12 #include <PCI.h>
13 #include <driver_settings.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "es1370.h"
18 #include "debug.h"
19 #include "config.h"
20 #include "util.h"
21 #include "io.h"
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <malloc.h>
26 status_t init_hardware(void);
27 status_t init_driver(void);
28 void uninit_driver(void);
29 const char ** publish_devices(void);
30 device_hooks * find_device(const char *);
31 status_t es1370_init(es1370_dev * card);
33 static char pci_name[] = B_PCI_MODULE_NAME;
34 pci_module_info *pci;
36 int32 num_cards;
37 es1370_dev cards[NUM_CARDS];
38 int32 num_names;
39 char * names[NUM_CARDS*20+1];
41 extern device_hooks multi_hooks;
43 es1370_settings current_settings = {
44 44100, // sample rate
45 512, // buffer frames
46 2, // buffer count
50 /* es1370 Memory management */
52 static es1370_mem *
53 es1370_mem_new(es1370_dev *card, size_t size)
55 es1370_mem *mem;
57 if ((mem = malloc(sizeof(*mem))) == NULL)
58 return (NULL);
60 mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "es1370 buffer");
61 mem->size = size;
62 if (mem->area < B_OK) {
63 free(mem);
64 return NULL;
66 return mem;
69 static void
70 es1370_mem_delete(es1370_mem *mem)
72 if(mem->area > B_OK)
73 delete_area(mem->area);
74 free(mem);
77 static void *
78 es1370_mem_alloc(es1370_dev *card, size_t size)
80 es1370_mem *mem;
82 mem = es1370_mem_new(card, size);
83 if (mem == NULL)
84 return (NULL);
86 LIST_INSERT_HEAD(&(card->mems), mem, next);
88 return mem;
91 static void
92 es1370_mem_free(es1370_dev *card, void *ptr)
94 es1370_mem *mem;
96 LIST_FOREACH(mem, &card->mems, next) {
97 if (mem->log_base != ptr)
98 continue;
99 LIST_REMOVE(mem, next);
101 es1370_mem_delete(mem);
102 break;
106 /* es1370 stream functions */
108 status_t
109 es1370_stream_set_audioparms(es1370_stream *stream, uint8 channels,
110 uint8 b16, uint32 sample_rate)
112 uint8 sample_size, frame_size;
113 LOG(("es1370_stream_set_audioparms\n"));
115 if ((stream->channels == channels) &&
116 (stream->b16 == b16) &&
117 (stream->sample_rate == sample_rate))
118 return B_OK;
120 if(stream->buffer)
121 es1370_mem_free(stream->card, stream->buffer->log_base);
123 stream->b16 = b16;
124 stream->sample_rate = sample_rate;
125 stream->channels = channels;
127 sample_size = stream->b16 + 1;
128 frame_size = sample_size * stream->channels;
130 stream->buffer = es1370_mem_alloc(stream->card, stream->bufframes * frame_size * stream->bufcount);
132 stream->trigblk = 0; /* This shouldn't be needed */
133 stream->blkmod = stream->bufcount;
134 stream->blksize = stream->bufframes * frame_size;
136 return B_OK;
139 status_t
140 es1370_stream_commit_parms(es1370_stream *stream)
142 uint8 sample_size, frame_size;
143 uint32 ctrl;
144 es1370_dev *card = stream->card;
145 LOG(("es1370_stream_commit_parms\n"));
147 ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL) & ~CTRL_PCLKDIV;
148 ctrl |= DAC2_SRTODIV((uint16)stream->sample_rate) << CTRL_SH_PCLKDIV;
149 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl);
151 sample_size = stream->b16 + 1;
152 frame_size = sample_size * stream->channels;
154 if (stream->use & ES1370_USE_RECORD) {
155 es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, 0xd);
156 es1370_reg_write_32(&card->config, ES1370_REG_ADC_FRAMEADR & 0xff, (uint32)stream->buffer->phy_base);
157 es1370_reg_write_32(&card->config, ES1370_REG_ADC_FRAMECNT & 0xff, ((stream->blksize * stream->bufcount) >> 2) - 1);
158 es1370_reg_write_32(&card->config, ES1370_REG_ADC_SCOUNT & 0xff, stream->bufframes - 1);
159 } else {
160 es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, 0xc);
161 es1370_reg_write_32(&card->config, ES1370_REG_DAC2_FRAMEADR & 0xff, (uint32)stream->buffer->phy_base);
162 es1370_reg_write_32(&card->config, ES1370_REG_DAC2_FRAMECNT & 0xff, ((stream->blksize * stream->bufcount) >> 2) - 1);
163 es1370_reg_write_32(&card->config, ES1370_REG_DAC2_SCOUNT & 0xff, stream->bufframes - 1);
164 LOG(("es1370_stream_commit_parms %ld %ld\n", ((stream->blksize * stream->bufcount) >> 2) - 1, (stream->blksize / frame_size) - 1));
167 return B_OK;
170 status_t
171 es1370_stream_get_nth_buffer(es1370_stream *stream, uint8 chan, uint8 buf,
172 char** buffer, size_t *stride)
174 uint8 sample_size, frame_size;
175 LOG(("es1370_stream_get_nth_buffer\n"));
177 sample_size = stream->b16 + 1;
178 frame_size = sample_size * stream->channels;
180 *buffer = stream->buffer->log_base + (buf * stream->bufframes * frame_size)
181 + chan * sample_size;
182 *stride = frame_size;
184 return B_OK;
187 static uint32
188 es1370_stream_curaddr(es1370_stream *stream)
190 es1370_dev *card = stream->card;
191 uint32 reg = 0, cnt = 0;
192 if (stream->use & ES1370_USE_RECORD) {
193 reg = ES1370_REG_ADC_FRAMECNT;
194 } else {
195 reg = ES1370_REG_DAC2_FRAMECNT;
197 es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, reg >> 8);
198 cnt = es1370_reg_read_32(&card->config, reg & 0xff) >> 16;
199 //TRACE(("stream_curaddr %lx\n", (cnt << 2) / stream->blksize));
200 return (cnt << 2) / stream->blksize;
203 void
204 es1370_stream_start(es1370_stream *stream, void (*inth) (void *), void *inthparam)
206 uint32 sctrl = 0, ctrl = 0;
207 es1370_dev *card = stream->card;
208 LOG(("es1370_stream_start\n"));
210 stream->inth = inth;
211 stream->inthparam = inthparam;
213 stream->state |= ES1370_STATE_STARTED;
215 sctrl = es1370_reg_read_32(&card->config, ES1370_REG_SERIAL_CONTROL);
216 ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL);
218 if (stream->use & ES1370_USE_RECORD) {
219 sctrl &= ~(SCTRL_R1SEB | SCTRL_R1SMB);
220 if (stream->b16)
221 sctrl |= SCTRL_R1SEB;
222 if (stream->channels == 2)
223 sctrl |= SCTRL_R1SMB;
224 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_R1INTEN);
225 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_R1INTEN);
227 ctrl |= CTRL_ADC_EN;
228 } else {
229 sctrl &= ~(SCTRL_P2SEB | SCTRL_P2SMB | 0x003f0000);
230 if (stream->b16)
231 sctrl |= SCTRL_P2SEB;
232 if (stream->channels == 2)
233 sctrl |= SCTRL_P2SMB;
234 sctrl |= (stream->b16 + 1) << SCTRL_SH_P2ENDINC;
235 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_P2INTEN);
236 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_P2INTEN);
238 ctrl |= CTRL_DAC2_EN;
241 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl);
242 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl);
244 #ifdef DEBUG
245 //dump_hardware_regs(&stream->card->config);
246 #endif
249 void
250 es1370_stream_halt(es1370_stream *stream)
252 uint32 ctrl;
253 es1370_dev *card = stream->card;
254 LOG(("es1370_stream_halt\n"));
256 stream->state &= ~ES1370_STATE_STARTED;
258 ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL);
259 if (stream->use & ES1370_USE_RECORD)
260 ctrl &= ~CTRL_ADC_EN;
261 else
262 ctrl &= ~CTRL_DAC2_EN;
263 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl);
266 es1370_stream *
267 es1370_stream_new(es1370_dev *card, uint8 use, uint32 bufframes, uint8 bufcount)
269 es1370_stream *stream;
270 cpu_status status;
271 LOG(("es1370_stream_new\n"));
273 stream = malloc(sizeof(es1370_stream));
274 if (stream == NULL)
275 return (NULL);
276 stream->card = card;
277 stream->use = use;
278 stream->state = !ES1370_STATE_STARTED;
279 stream->b16 = 0;
280 stream->sample_rate = 0;
281 stream->channels = 0;
282 stream->bufframes = bufframes;
283 stream->bufcount = bufcount;
284 stream->inth = NULL;
285 stream->inthparam = NULL;
286 stream->buffer = NULL;
287 stream->blksize = 0;
288 stream->trigblk = 0;
289 stream->blkmod = 0;
291 stream->buffer_cycle = 0;
292 stream->frames_count = 0;
293 stream->real_time = 0;
294 stream->update_needed = false;
296 status = lock();
297 LIST_INSERT_HEAD((&card->streams), stream, next);
298 unlock(status);
300 return stream;
303 void
304 es1370_stream_delete(es1370_stream *stream)
306 cpu_status status;
307 LOG(("es1370_stream_delete\n"));
309 es1370_stream_halt(stream);
311 if(stream->buffer)
312 es1370_mem_free(stream->card, stream->buffer->log_base);
314 status = lock();
315 LIST_REMOVE(stream, next);
316 unlock(status);
318 free(stream);
321 /* es1370 interrupt */
323 static int32
324 es1370_int(void *arg)
326 es1370_dev *card = arg;
327 bool gotone = false;
328 uint32 curblk;
329 es1370_stream *stream = NULL;
330 uint32 sta, sctrl;
332 // TRACE(("es1370_int(%p)\n", card));
334 sta = es1370_reg_read_32(&card->config, ES1370_REG_STATUS);
335 if (sta & card->interrupt_mask) {
337 //TRACE(("interrupt !! %x\n", sta));
338 sctrl = es1370_reg_read_32(&card->config, ES1370_REG_SERIAL_CONTROL);
340 LIST_FOREACH(stream, &card->streams, next) {
341 if (stream->use & ES1370_USE_RECORD) {
342 if ((sta & STAT_ADC) == 0)
343 continue;
344 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_R1INTEN);
345 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_R1INTEN);
346 } else {
347 if ((sta & STAT_DAC2) == 0)
348 continue;
349 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_P2INTEN);
350 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_P2INTEN);
353 curblk = es1370_stream_curaddr(stream);
354 // TRACE(("INTR at trigblk %lu, stream->trigblk %lu\n", curblk, stream->trigblk));
355 if (curblk == stream->trigblk) {
356 stream->trigblk++;
357 stream->trigblk = stream->trigblk % stream->blkmod;
358 if (stream->inth)
359 stream->inth(stream->inthparam);
361 gotone = true;
363 } else {
364 //TRACE(("interrupt masked %x, ", card->interrupt_mask));
365 //TRACE(("sta %x\n", sta));
368 if (gotone)
369 return B_INVOKE_SCHEDULER;
371 //TRACE(("Got unhandled interrupt\n"));
372 return B_UNHANDLED_INTERRUPT;
376 /* es1370 driver functions */
379 /* detect presence of our hardware */
380 status_t
381 init_hardware(void)
383 int ix=0;
384 pci_info info;
385 status_t err = ENODEV;
387 LOG_CREATE();
389 PRINT(("init_hardware()\n"));
391 if (get_module(pci_name, (module_info **)&pci))
392 return ENOSYS;
394 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
395 if (info.vendor_id == 0x1274
396 && (info.device_id == 0x5000
397 /*|| info.device_id == 0x1371
398 || info.device_id == 0x5880*/)
401 err = B_OK;
403 ix++;
406 put_module(pci_name);
408 return err;
411 static void
412 make_device_names(
413 es1370_dev * card)
415 sprintf(card->name, "audio/hmulti/es1370/%ld", card-cards+1);
416 names[num_names++] = card->name;
418 names[num_names] = NULL;
422 status_t
423 es1370_init(es1370_dev * card)
425 card->interrupt_mask = STAT_DAC2 | STAT_ADC;
427 /* Init streams list */
428 LIST_INIT(&(card->streams));
430 /* Init mems list */
431 LIST_INIT(&(card->mems));
433 return B_OK;
436 static status_t
437 es1370_setup(es1370_dev * card)
439 status_t err = B_OK;
440 unsigned char cmd;
442 PRINT(("es1370_setup(%p)\n", card));
444 make_device_names(card);
446 card->config.base = card->info.u.h0.base_registers[0];
447 card->config.irq = card->info.u.h0.interrupt_line;
448 card->config.type = 0;
450 PRINT(("%s deviceid = %#04x chiprev = %x model = %x enhanced at %lx\n", card->name, card->info.device_id,
451 card->info.revision, card->info.u.h0.subsystem_id, card->config.base));
453 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2);
454 PRINT(("PCI command before: %x\n", cmd));
455 (*pci->write_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2, cmd | PCI_command_io);
456 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2);
457 PRINT(("PCI command after: %x\n", cmd));
459 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, SCTRL_P2INTEN | SCTRL_R1INTEN);
460 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, CTRL_CDC_EN);
462 /* reset the codec */
463 PRINT(("codec reset\n"));
464 es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x2);
465 snooze (20);
466 es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x3);
467 snooze (20);
468 es1370_codec_write(&card->config, CODEC_CLOCK_SEL, 0x0);
470 /* set max volume on master and mixer outputs */
471 es1370_codec_write(&card->config, CODEC_MASTER_VOL_L, 0x0);
472 es1370_codec_write(&card->config, CODEC_MASTER_VOL_R, 0x0);
473 es1370_codec_write(&card->config, CODEC_VOICE_VOL_L, 0x0);
474 es1370_codec_write(&card->config, CODEC_VOICE_VOL_R, 0x0);
476 /* unmute CD playback */
477 es1370_codec_write(&card->config, CODEC_OUTPUT_MIX1, ES1370_OUTPUT_MIX1_CDL | ES1370_OUTPUT_MIX1_CDR);
478 /* unmute mixer output */
479 es1370_codec_write(&card->config, CODEC_OUTPUT_MIX2, ES1370_OUTPUT_MIX2_VOICEL | ES1370_OUTPUT_MIX2_VOICER);
481 snooze(50000); // 50 ms
483 PRINT(("installing interrupt : %lx\n", card->config.irq));
484 err = install_io_interrupt_handler(card->config.irq, es1370_int, card, 0);
485 if (err != B_OK) {
486 PRINT(("failed to install interrupt\n"));
487 return err;
490 if ((err = es1370_init(card)))
491 return (err);
493 PRINT(("init_driver done\n"));
495 return err;
499 status_t
500 init_driver(void)
502 void *settings_handle;
503 pci_info info;
504 int ix = 0;
505 status_t err;
506 num_cards = 0;
508 PRINT(("init_driver()\n"));
510 // get driver settings
511 settings_handle = load_driver_settings ("es1370.settings");
512 if (settings_handle != NULL) {
513 const char *item;
514 char *end;
515 uint32 value;
517 item = get_driver_parameter (settings_handle, "sample_rate", "44100", "44100");
518 value = strtoul (item, &end, 0);
519 if (*end == '\0') current_settings.sample_rate = value;
521 item = get_driver_parameter (settings_handle, "buffer_frames", "512", "512");
522 value = strtoul (item, &end, 0);
523 if (*end == '\0') current_settings.buffer_frames = value;
525 item = get_driver_parameter (settings_handle, "buffer_count", "2", "2");
526 value = strtoul (item, &end, 0);
527 if (*end == '\0') current_settings.buffer_count = value;
529 unload_driver_settings (settings_handle);
532 if (get_module(pci_name, (module_info **) &pci))
533 return ENOSYS;
535 while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) {
536 if (info.vendor_id == 0x1274
537 && (info.device_id == 0x5000
538 /*|| info.device_id == 0x1371
539 || info.device_id == 0x5880*/)
541 if (num_cards == NUM_CARDS) {
542 PRINT(("Too many es1370 cards installed!\n"));
543 break;
545 memset(&cards[num_cards], 0, sizeof(es1370_dev));
546 cards[num_cards].info = info;
547 #ifdef __HAIKU__
548 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function,
549 DRIVER_NAME, &cards[num_cards])) < B_OK) {
550 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n",
551 DRIVER_NAME, info.bus, info.device, info.function,
552 strerror(err));
553 continue;
555 #endif
556 if (es1370_setup(&cards[num_cards])) {
557 PRINT(("Setup of es1370 %ld failed\n", num_cards+1));
558 #ifdef __HAIKU__
559 (*pci->unreserve_device)(info.bus, info.device, info.function,
560 DRIVER_NAME, &cards[num_cards]);
561 #endif
563 else {
564 num_cards++;
568 if (!num_cards) {
569 PRINT(("no cards\n"));
570 put_module(pci_name);
571 PRINT(("no suitable cards found\n"));
572 return ENODEV;
575 return B_OK;
579 static void
580 es1370_shutdown(es1370_dev *card)
582 PRINT(("shutdown(%p)\n", card));
583 //ac97_amp_enable(&card->config, false);
584 card->interrupt_mask = 0;
586 remove_io_interrupt_handler(card->config.irq, es1370_int, card);
590 void
591 uninit_driver(void)
593 int ix, cnt = num_cards;
594 num_cards = 0;
596 PRINT(("uninit_driver()\n"));
597 for (ix=0; ix<cnt; ix++) {
598 es1370_shutdown(&cards[ix]);
599 #ifdef __HAIKU__
600 (*pci->unreserve_device)(cards[ix].info.bus,
601 cards[ix].info.device, cards[ix].info.function,
602 DRIVER_NAME, &cards[ix]);
603 #endif
605 memset(&cards, 0, sizeof(cards));
606 put_module(pci_name);
610 const char **
611 publish_devices(void)
613 int ix = 0;
614 PRINT(("publish_devices()\n"));
616 for (ix=0; names[ix]; ix++) {
617 PRINT(("publish %s\n", names[ix]));
619 return (const char **)names;
623 device_hooks *
624 find_device(const char * name)
626 int ix;
628 PRINT(("find_device(%s)\n", name));
630 for (ix=0; ix<num_cards; ix++) {
631 if (!strcmp(cards[ix].name, name)) {
632 return &multi_hooks;
635 PRINT(("find_device(%s) failed\n", name));
636 return NULL;
639 int32 api_version = B_CUR_DRIVER_API_VERSION;