diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile b/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile index d8aa960558..9e89ffe7b9 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile @@ -8,7 +8,8 @@ R5KernelAddon ich_ac97 : kernel drivers bin : debug.c ich.c io.c - util.c + util.c + ac97.c ; # For OpenBeOS we should be building the driver objects this way. @@ -19,6 +20,7 @@ R5KernelAddon ich_ac97 : kernel drivers bin : # ich.c # io.c # util.c +# ac97.c # : # -fno-pic -D_KERNEL_MODE # ; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c new file mode 100644 index 0000000000..8a7c4485a1 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c @@ -0,0 +1,147 @@ +/* + * BeOS Driver for Intel ICH AC'97 Link interface + * + * Copyright (c) 2002, Marcus Overhagen + * + * All rights reserved. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include "ac97.h" + +//#define DEBUG 1 + +#include "debug.h" +#include "io.h" + +const char * +ac97_get_3d_stereo_enhancement() +{ + const char * technique[] = { + "No 3D Stereo Enhancement", + "Analog Devices", + "Creative Technology", + "National Semiconductor", + "Yamaha", + "BBE Sound", + "Crystal Semiconductor", + "Qsound Labs", + "Spatializer Audio Laboratories", + "SRS Labs", + "Platform Tech", + "AKM Semiconductor", + "Aureal", + "Aztech Labs", + "Binaura", + "ESS Technology", + "Harman International", + "Nvidea", + "Philips" + "Texas Instruments", + "VLSI Technology", + "TriTech", + "Realtek", + "Samsung", + "Wolfson Microelectronics", + "Delta Integration", + "SigmaTel", + "KS Waves", + "Rockwell", + "Unknown (29)", + "Unknown (30)", + "Unknown (31)" + }; + uint16 data; + data = ich_codec_read(AC97_RESET); + data = (data >> 10) & 31; + return technique[data]; +} + +const char * +ac97_get_vendor_id_description() +{ + static char desc[10]; + uint32 id = ac97_get_vendor_id(); + char f = (id >> 24) & 0xff; + char s = (id >> 16) & 0xff; + char t = (id >> 8) & 0xff; + if (f == 0) f = '?'; + if (s == 0) s = '?'; + if (t == 0) t = '?'; + sprintf(desc,"%c%c%c %u",f,s,t,id & 0xff); + return desc; +} + +uint32 +ac97_get_vendor_id() +{ + uint16 data1; + uint16 data2; + data1 = ich_codec_read(AC97_VENDOR_ID1); + data2 = ich_codec_read(AC97_VENDOR_ID2); + return (((uint32)data1) << 16) | data2; +} + +void +ac97_amp_enable(bool yesno) +{ + switch (ac97_get_vendor_id()) + { + case 0x43525931: /* Cirrus Logic CS4299 rev A */ + case 0x43525933: /* Cirrus Logic CS4299 rev C */ + case 0x43525934: /* Cirrus Logic CS4299 rev D */ + { + LOG(("using Cirrus enable")); + if (yesno) + ich_codec_write(0x68, 0x8004); + else + ich_codec_write(0x68, 0); + break; + } + + default: + { + LOG(("powerdown register was = %#04x\n",ich_codec_read(AC97_POWERDOWN))); + if (yesno) + ich_codec_write(AC97_POWERDOWN, ich_codec_read(AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */ + else + ich_codec_write(AC97_POWERDOWN, ich_codec_read(AC97_POWERDOWN) | 0x8000); /* switch off */ + LOG(("powerdown register is = %#04x\n",ich_codec_read(AC97_POWERDOWN))); + break; + } + } +} + +void +ac97_init() +{ + switch (ac97_get_vendor_id()) + { + case 0x41445461: /* Analog Devices AD1886 */ + LOG(("using AD1886 init")); + ich_codec_write(0x72, 0x0010); + break; + default: + break; + } +} diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.h b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.h new file mode 100644 index 0000000000..dd1e16a24c --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.h @@ -0,0 +1,62 @@ +/* + * BeOS Driver for Intel ICH AC'97 Link interface + * + * Copyright (c) 2002, Marcus Overhagen + * + * All rights reserved. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _AC97_H_ +#define _AC97_H_ + +enum AC97_REGISTER { + AC97_RESET = 0x00, + AC97_MASTER_VOLUME = 0x02, + AC97_AUX_OUT_VOLUME = 0x04, + AC97_MONO_VOLUME = 0x06, + AC97_MASTER_TONE = 0x08, + AC97_PC_BEEP_VOLUME = 0x0A, + AC97_PHONE_VOLUME = 0x0C, + AC97_MIC_VOLUME = 0x0E, + AC97_LINE_IN_VOLUME = 0x10, + AC97_CD_VOLUME = 0x12, + AC97_VIDEO_VOLUME = 0x14, + AC97_AUX_IN_VOLUME = 0x16, + AC97_PCM_OUT_VOLUME = 0x18, + AC97_RECORD_SELECT = 0x1A, + AC97_RECORD_GAIN = 0x1C, + AC97_RECORD_GAIN_MIC = 0x1E, + AC97_GENERAL_PURPOSE = 0x20, + AC97_3D_CONTROL = 0x22, + AC97_PAGING = 0x24, + AC97_POWERDOWN = 0x26, + AC97_VENDOR_ID1 = 0x7C, + AC97_VENDOR_ID2 = 0x7E +}; + +const char * ac97_get_3d_stereo_enhancement(); +const char * ac97_get_vendor_id_description(); +uint32 ac97_get_vendor_id(); +void ac97_amp_enable(bool yesno); +void ac97_init(); + +#endif diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c index 4204113165..a39ea532ca 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c @@ -27,14 +27,22 @@ */ #include #include +#include +#include #include #include "debug.h" #include "ich.h" +static const char * logfile="/boot/home/ich_ac97.log"; +static sem_id loglock; + void debug_printf(const char *text,...); +void log_printf(const char *text,...); +void log_create(); void debug_printf(const char *text,...) { +#if DEBUG != 5 char buf[1024]; va_list ap; @@ -47,5 +55,32 @@ void debug_printf(const char *text,...) #if DEBUG > 1 snooze(150000); #endif +#endif +} + +void log_create() +{ + int fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + const char *text = DRIVER_NAME ", " VERSION "\n"; + loglock = create_sem(1,"logfile sem"); + write(fd,text,strlen(text)); + close(fd); +} + +void log_printf(const char *text,...) +{ + int fd; + char buf[1024]; + va_list ap; + + acquire_sem(loglock); + fd = open(logfile, O_WRONLY | O_APPEND); + va_start(ap,text); + vsprintf(buf,text,ap); + va_end(ap); + write(fd,buf,strlen(buf)); + /* fsync(fd); */ + close(fd); + release_sem(loglock); } diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h index e74a33800a..8b2e1739db 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h @@ -28,20 +28,32 @@ #ifndef _DEBUG_H_ #define _DEBUG_H_ +/* DEBUG == 0, no debugging + * DEBUG == 1, dprintf & LOG + * DEBUG == 2, dprintf with snooze & LOG + * DEBUG == 5, only LOG + */ + #ifndef DEBUG - #define DEBUG 0 + #define DEBUG 5 #endif #undef TRACE #undef ASSERT #if DEBUG > 0 - #define TRACE(a) debug_printf a - #define ASSERT(a) if (a) {} else TRACE(("ASSERT failed! file = %s, line = %d\n",__FILE__,__LINE__)) + #define TRACE(a) debug_printf a + #define ASSERT(a) if (a) {} else TRACE(("ASSERT failed! file = %s, line = %d\n",__FILE__,__LINE__)) + #define LOG(a) log_printf a + #define LOG_CREATE() log_create() + void log_create(); + void log_printf(const char *text,...); void debug_printf(const char *text,...); #else #define TRACE(a) ((void)(0)) #define ASSERT(a) ((void)(0)) + #define LOG(a) ((void)(0)) + #define LOG_CREATE() #endif #endif diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c index 9800c55cec..d2a2d76db5 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c @@ -25,7 +25,6 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -#define VERSION "Version 1.0, Copyright (c) 2002 Marcus Overhagen, compiled on " ## __DATE__ ## " " ## __TIME__ ## "\n" //#define DEBUG 1 @@ -40,6 +39,7 @@ #include "ich.h" #include "util.h" #include "ac97_multi.h" +#include "ac97.h" int32 api_version = B_CUR_DRIVER_API_VERSION; @@ -201,10 +201,13 @@ bool interrupt_test(void) free(testresult); #if DEBUG - if (result) + if (result) { TRACE(("got interrupt after %Lu us\n",duration)); - else + LOG(("got interrupt after %Lu us\n",duration)); + } else { TRACE(("no interrupt, timeout after %Lu us\n",duration)); + LOG(("no interrupt, timeout after %Lu us\n",duration)); + } #endif return result; @@ -311,23 +314,26 @@ init_driver(void) bigtime_t start; TRACE(("init_driver\n")); - TRACE((VERSION)); + LOG_CREATE(); ASSERT(sizeof(ich_bd) == 8); rv = probe_device(); if (rv != B_OK) { + LOG(("No supported audio hardware found.\n")); TRACE(("hardware not found\n")); return B_ERROR; } dprintf("ich-ac97: " VERSION "\n"); dprintf("ich-ac97: found %s, IRQ = %ld, NAMBAR = %#lX, NABMBAR = %#lX, MMBAR = %#lX, MBBAR = %#lX\n",config->name,config->irq,config->nambar,config->nabmbar,config->mmbar,config->mbbar); + LOG(("Found %s\nIRQ = %ld\nNAMBAR = %#lX\nNABMBAR = %#lX\nMMBAR = %#lX\nMBBAR = %#lX\n",config->name,config->irq,config->nambar,config->nabmbar,config->mmbar,config->mbbar)); /* before doing anything else, map the IO memory */ rv = map_io_memory(); if (rv != B_OK) { dprintf("ich-ac97: mapping of memory IO space failed\n"); + LOG(("mapping of memory IO space failed\n")); return B_ERROR; } @@ -344,6 +350,7 @@ init_driver(void) rv = ich_reg_read_32(ICH_REG_GLOB_CNT); if ((rv & CNT_COLD) == 0) { TRACE(("cold reset failed\n")); + LOG(("cold reset failed\n")); } /* wait until a codec is ready */ @@ -356,8 +363,10 @@ init_driver(void) } if ((rv & STA_PCR)) { TRACE(("primary codec ready after %Ld us\n",(system_time() - start))); + LOG(("primary codec ready after %Ld us\n",(system_time() - start))); } else { TRACE(("primary codec not ready after %Ld us\n",(system_time() - start))); + LOG(("primary codec not ready after %Ld us\n",(system_time() - start))); } while ((system_time() - start) < 1000000) { rv = ich_reg_read_32(ICH_REG_GLOB_STA); @@ -367,8 +376,10 @@ init_driver(void) } if ((rv & STA_SCR)) { TRACE(("secondary codec ready after %Ld us\n",(system_time() - start))); + LOG(("secondary codec ready after %Ld us\n",(system_time() - start))); } else { TRACE(("secondary codec not ready after %Ld us\n",(system_time() - start))); + LOG(("secondary codec not ready after %Ld us\n",(system_time() - start))); } if ((rv & (STA_PCR | STA_SCR)) == 0) { dprintf("ich-ac97: compatible chipset found, but no codec ready!\n"); @@ -377,6 +388,7 @@ init_driver(void) } if ((rv & STA_PCR) == 0 && (rv & STA_SCR) != 0) { TRACE(("using secondary codec!\n")); + LOG(("using secondary codec!\n")); config->nambar += 0x80; } @@ -387,6 +399,7 @@ init_driver(void) if (0 == chan_pi || 0 == chan_po || 0 == chan_mc) { dprintf("ich-ac97: couldn't allocate memory for channel descriptors!\n"); + LOG(("couldn't allocate memory for channel descriptors!\n")); chan_free_resources(); unmap_io_memory(); return B_ERROR; @@ -409,6 +422,7 @@ init_driver(void) chan_pi->bd_area < B_OK || chan_pi->buffer_area < B_OK || chan_pi->userbuffer_area < B_OK || chan_mc->bd_area < B_OK || chan_mc->buffer_area < B_OK || chan_mc->userbuffer_area < B_OK) { dprintf("ich-ac97: couldn't allocate memory for DMA buffers!\n"); + LOG(("ich-ac97: couldn't allocate memory for DMA buffers!\n")); chan_free_resources(); unmap_io_memory(); return B_ERROR; @@ -420,7 +434,8 @@ init_driver(void) chan_mc->buffer_ready_sem = create_sem(0,"mc buffer ready"); /* 0 available mic in buffers */ if (chan_po->buffer_ready_sem < B_OK || chan_pi->buffer_ready_sem < B_OK || chan_mc->buffer_ready_sem < B_OK) { - dprintf("ich-ac97: couldn't semaphores!\n"); + dprintf("ich-ac97: couldn't create semaphores!\n"); + LOG(("ich-ac97: couldn't create semaphores!\n")); chan_free_resources(); unmap_io_memory(); return B_ERROR; @@ -436,8 +451,12 @@ init_driver(void) ich_codec_write(0x00, 0x0000); snooze(50000); // 50 ms - TRACE(("reading codec\n")); - TRACE(("codec = %#04x\n",ich_codec_read(0x00))); + ac97_init(); + ac97_amp_enable(true); + + LOG(("codec vendor id = %#08x\n",ac97_get_vendor_id())); + LOG(("codec descripton = %s\n",ac97_get_vendor_id_description())); + LOG(("codec 3d enhancement = %s\n",ac97_get_3d_stereo_enhancement())); /* reset all channels */ reset_chan(chan_pi); @@ -452,6 +471,7 @@ init_driver(void) /* first test if interrupts are working, on some Laptops they don't work :-( */ if (config->irq != 0 && false == interrupt_test()) { TRACE(("interrupt not working, using a kernel thread for polling\n")); + LOG(("interrupt not working, using a kernel thread for polling\n")); config->irq = 0; /* don't use interrupts */ } @@ -497,6 +517,9 @@ uninit_driver(void) if (chan_po) TRACE(("chan_po frames_count = %Ld\n",chan_po->played_frames_count)); if (chan_pi) TRACE(("chan_pi frames_count = %Ld\n",chan_pi->played_frames_count)); if (chan_mc) TRACE(("chan_mc frames_count = %Ld\n",chan_mc->played_frames_count)); + if (chan_po) LOG(("chan_po frames_count = %Ld\n",chan_po->played_frames_count)); + if (chan_pi) LOG(("chan_pi frames_count = %Ld\n",chan_pi->played_frames_count)); + if (chan_mc) LOG(("chan_mc frames_count = %Ld\n",chan_mc->played_frames_count)); #endif /* reset all channels */ diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h index de296a2761..0f536ffa22 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h @@ -30,9 +30,10 @@ #include "hardware.h" +#define VERSION "Version 1.1, Copyright (c) 2002 Marcus Overhagen, compiled on " ## __DATE__ ## " " ## __TIME__ #define DRIVER_NAME "ich_ac97" -#define BUFFER_SIZE 512 +#define BUFFER_SIZE 2048 #define BUFFER_COUNT 2 #define BUFFER_FRAMES_COUNT (BUFFER_SIZE / 4)