Add user friendly debugging, and enable an external amplifier.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@525 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper 2002-07-28 22:16:23 +00:00
parent b1698c8e74
commit 08d3f7d47c
7 changed files with 294 additions and 12 deletions

View File

@ -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
# ;

View File

@ -0,0 +1,147 @@
/*
* BeOS Driver for Intel ICH AC'97 Link interface
*
* Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
*
* 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 <OS.h>
#include <MediaDefs.h>
#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;
}
}

View File

@ -0,0 +1,62 @@
/*
* BeOS Driver for Intel ICH AC'97 Link interface
*
* Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
*
* 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

View File

@ -27,14 +27,22 @@
*/
#include <KernelExport.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <OS.h>
#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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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)