diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 39ecda4306..757bb28c91 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -156,8 +156,8 @@ SYSTEM_ADD_ONS_PRINT_TRANSPORT = HP\ JetDirect IPP LPR Parallel\ Port ; SYSTEM_ADD_ONS_SCREENSAVERS = Butterfly DebugNow Flurry $(HAIKU_INCLUDE_TRADEMARKS)Haiku Icons IFS Leaves Message Spider ; -SYSTEM_ADD_ONS_DRIVERS_AUDIO = auich auvia echo3g emuxki hda ; -SYSTEM_ADD_ONS_DRIVERS_AUDIO_OLD = ; #cmedia sis7018 usb_audio ; +SYSTEM_ADD_ONS_DRIVERS_AUDIO = auich auvia echo3g emuxki hda sis7018 ; +SYSTEM_ADD_ONS_DRIVERS_AUDIO_OLD = ; #cmedia usb_audio ; SYSTEM_ADD_ONS_DRIVERS_GRAPHICS = $(X86_ONLY)radeon $(X86_ONLY)nvidia $(X86_ONLY)neomagic $(X86_ONLY)matrox $(X86_ONLY)intel_extreme $(X86_ONLY)s3 $(X86_ONLY)vesa #$(X86_ONLY)via #$(X86_ONLY)vmware diff --git a/src/add-ons/kernel/drivers/audio/Jamfile b/src/add-ons/kernel/drivers/audio/Jamfile index 341200f730..f65610da6a 100644 --- a/src/add-ons/kernel/drivers/audio/Jamfile +++ b/src/add-ons/kernel/drivers/audio/Jamfile @@ -9,6 +9,5 @@ SubInclude HAIKU_TOP src add-ons kernel drivers audio ice1712 ; SubInclude HAIKU_TOP src add-ons kernel drivers audio module_driver ; SubInclude HAIKU_TOP src add-ons kernel drivers audio null ; SubInclude HAIKU_TOP src add-ons kernel drivers audio sb16 ; -SubInclude HAIKU_TOP src add-ons kernel drivers audio sis7018 ; SubInclude HAIKU_TOP src add-ons kernel drivers audio usb_audio ; diff --git a/src/add-ons/kernel/drivers/audio/ac97/Jamfile b/src/add-ons/kernel/drivers/audio/ac97/Jamfile index d5ea1de416..02e175f84f 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/Jamfile +++ b/src/add-ons/kernel/drivers/audio/ac97/Jamfile @@ -1,9 +1,9 @@ SubDir HAIKU_TOP src add-ons kernel drivers audio ac97 ; -SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 ali5451 ; SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 auich ; SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 auvia ; SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 es1370 ; SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 geode ; SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 ich ; # SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 ichaudio ; +SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 sis7018 ; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/Jamfile b/src/add-ons/kernel/drivers/audio/ac97/ali5451/Jamfile deleted file mode 100644 index c9dcff550b..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/Jamfile +++ /dev/null @@ -1,16 +0,0 @@ -SubDir HAIKU_TOP src add-ons kernel drivers audio ac97 ali5451 ; - -SetSubDirSupportedPlatformsBeOSCompatible ; - -UsePrivateHeaders media ; - -SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; -SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) ] ; - -KernelAddon ali5451 : - driver.c - ali_multi.c - ali_hardware.c - util.c - ac97.c -; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_hardware.c b/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_hardware.c deleted file mode 100644 index 5c01f3be25..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_hardware.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ - - -#include -#include -#include -#include - -#include "ac97.h" -#include "queue.h" -#include "driver.h" -#include "util.h" -#include "ali_hardware.h" -#include "debug.h" - - -#define ALI_5451_V02 0x02 - -// ALI registers - -#define ALI_MPUR0 0x20 -#define ALI_MPUR1 0x21 -#define ALI_MPUR2 0x22 -#define ALI_MPUR3 0x23 - -#define ALI_ACR0 0x40 -#define ALI_ACR1 0x44 -#define ALI_ACR2 0x48 - -#define ALI_START_A 0x80 -#define ALI_STOP_A 0x84 - -#define ALI_AIN_A 0x98 -#define ALI_LFO_A 0xa0 - #define ALI_LFO_A_ENDLP_IE 0x1000 - #define ALI_LFO_A_MIDLP_IE 0x2000 -#define ALI_AINTEN_A 0xa4 -#define ALI_VOL_A 0xa8 -#define ALI_STIMER 0xc8 -#define ALI_T_DIGIMIXER 0xd4 -#define ALI_AIN_B 0xd8 - -#define ALI_CSO_ALPHA_FMS 0xe0 -#define ALI_PPTR_LBA 0xe4 -#define ALI_ESO_DELTA 0xe8 -#define ALI_FMC_RVOL_CVOL 0xec -#define ALI_GVSEL_MISC 0xf0 -#define ALI_EBUF1 0xf4 -#define ALI_EBUF2 0xf8 - -extern pci_module_info *gPCI; - - -/* card i/o */ - - -static uint32 -io_read32(ali_dev *card, ulong offset) -{ - return (*gPCI->read_io_32)(card->io_base + offset); -} - - -static uint8 -io_read8(ali_dev *card, ulong offset) -{ - return (*gPCI->read_io_8)(card->io_base + offset); -} - - -static void -io_write32(ali_dev *card, ulong offset, uint32 value) -{ - (*gPCI->write_io_32)(card->io_base + offset, value); -} - - -static void -io_write16(ali_dev *card, ulong offset, uint16 value) -{ - (*gPCI->write_io_16)(card->io_base + offset, value); -} - - -static void -io_write8(ali_dev *card, ulong offset, uint8 value) -{ - (*gPCI->write_io_8)(card->io_base + offset, value); -} - - -/* codec i/o */ - - -static bool -ac97_is_ready(ali_dev *card, uint32 offset) -{ - uint8 cnt = 200; - uint32 val; - - while (cnt--) { - val = io_read32(card, offset); - if (!(val & 0x8000)) - return true; - spin(1); - } - - io_write32(card, offset, val & ~0x8000); - TRACE("ac97 not ready\n"); - return false; -} - - -static bool -ac97_is_stimer_ready(ali_dev *card) -{ - uint8 cnt = 200; - uint32 t1, t2; - - t1 = io_read32(card, ALI_STIMER); - - while (cnt--) { - t2 = io_read32(card, ALI_STIMER); - if (t2 != t1) - return true; - spin(1); - } - - TRACE("ac97 stimer not ready\n"); - return false; -} - - -static uint16 -ac97_read(void *cookie, uint8 reg) -{ - ali_dev *card = (ali_dev *) cookie; - uint32 ac_reg; - - ac_reg = (card->info.revision == ALI_5451_V02)?ALI_ACR0:ALI_ACR1; - - if (!ac97_is_ready(card, ac_reg) || !ac97_is_stimer_ready(card)) - return 0; - - io_write16(card, ac_reg, (uint16) reg | 0x8000); - - if (!ac97_is_stimer_ready(card) || !ac97_is_ready(card, ac_reg)) - return 0; - - return (uint16) (io_read32(card, ac_reg) >> 16); -} - - -static void -ac97_write(void *cookie, uint8 reg, uint16 val) -{ - ali_dev *card = (ali_dev *) cookie; - uint32 dw_val; - - if (!ac97_is_ready(card, ALI_ACR0) || !ac97_is_stimer_ready(card)) - return; - - dw_val = reg | 0x8000 | (uint32) val << 16; - if (card->info.revision == ALI_5451_V02) - dw_val |= 0x0100; - - io_write32(card, ALI_ACR0, dw_val); -} - - -static bool -hardware_reset(ali_dev *card) -{ - uint32 cmd_reg; - uint8 bval; - - // pci reset - cmd_reg = (*gPCI->read_pci_config)(card->info.bus, card->info.device, - card->info.function, 0x44, 4); - (*gPCI->write_pci_config)(card->info.bus, card->info.device, - card->info.function, 0x44, 4, cmd_reg | 0x08000000); - snooze(500); - cmd_reg = (*gPCI->read_pci_config)(card->info.bus, card->info.device, - card->info.function, 0x44, 4); - (*gPCI->write_pci_config)(card->info.bus, card->info.device, - card->info.function, 0x44, 4, cmd_reg & 0xfffbffff); - snooze(5000); - - bval = io_read8(card, ALI_ACR2); - bval |= 2; - io_write8(card, ALI_ACR2, bval); - snooze(5000); - bval = io_read8(card, ALI_ACR2); - bval &= 0xfd; - io_write8(card, ALI_ACR2, bval); - snooze(15000); - - return true; -} - - -status_t -hardware_init(ali_dev *card) -{ - if (!hardware_reset(card)) - return B_ERROR; - - LOCK(card->lock_hw); - - io_write32(card, ALI_AINTEN_A, 0); - // disable voice interrupts - io_write32(card, ALI_AIN_A, 0xffffffff); - // clr voice interrupt flags - io_write32(card, ALI_VOL_A, 0); - // master & wave volumes - io_write8(card, ALI_MPUR2, 0x10); - - io_write32(card, ALI_LFO_A, ALI_LFO_A_ENDLP_IE | ALI_LFO_A_MIDLP_IE); - - UNLOCK(card->lock_hw); - - ac97_attach(&card->codec, ac97_read, ac97_write, card, - card->info.u.h0.subsystem_vendor_id, card->info.u.h0.subsystem_id); - - TRACE("hardware init ok\n"); - return B_OK; -} - - -void -hardware_terminate(ali_dev *card) -{ - LOCK(card->lock_hw); - - io_write32(card, ALI_AINTEN_A, 0); - // disable voice interrupts - io_write32(card, ALI_AIN_A, 0xffffffff); - // clr voice interrupt flags - - UNLOCK(card->lock_hw); - - ac97_detach(card->codec); -} - - -uint32 -ali_read_int(ali_dev *card) -{ - return io_read32(card, ALI_AIN_A); -} - - -/* voices handling */ - - -static uint16 -ali_delta_from_rate(uint32 rate, bool rec) -{ - uint32 delta; - - if (rate < 8000) - rate = 8000; - if (48000 < rate) - rate = 48000; - - switch (rate) { - case 8000: delta = (rec?0x6000:0x2ab); break; - case 44100: delta = (rec?0x116a:0xeb3); break; - case 48000: delta = 0x1000; break; - default: - delta = (rec?((48000 << 12) / rate):(((rate << 12) + rate) / 48000)); - } - - return (uint16) delta; -} - - -static uint32 -ali_control_mode(ali_stream *stream) -{ - uint32 ctrl = 1; - - if (util_format_is_signed(stream->format.format)) - ctrl |= 2; - if (1 < stream->channels) - ctrl |= 4; - if (util_format_to_sample_size(stream->format.format) == 2) - ctrl |= 8; - - return ctrl; -} - - -bool -ali_voice_start(ali_stream *stream) -{ - LOCK(stream->card->lock_hw); - - // setup per-voice registers - - io_write8(stream->card, ALI_LFO_A, stream->used_voice); - // select voice - - io_write32(stream->card, ALI_CSO_ALPHA_FMS, 0); - // cso = 0, alpha = 0 - io_write32(stream->card, ALI_PPTR_LBA, (uint32) stream->buffer->phy_base); - // pptr & lba - io_write32(stream->card, ALI_ESO_DELTA, - ((uint32) stream->buf_frames * stream->buf_count - 1) << 16 - | ali_delta_from_rate(stream->format.rate, stream->rec)); - // eso & delta - - io_write32(stream->card, ALI_GVSEL_MISC, - ali_control_mode(stream) << 12); - // gvsel=0, pan=0, vol=0, ctrl, ec=0 - - // reset envelopes - io_write32(stream->card, ALI_EBUF1, 0); - io_write32(stream->card, ALI_EBUF2, 0); - - UNLOCK(stream->card->lock_hw); - - io_write32(stream->card, ALI_AIN_A, (uint32) 1 << stream->used_voice); - // clr voice interrupt - io_write32(stream->card, ALI_AINTEN_A, stream->card->used_voices); - // enable interupt for voice - - io_write32(stream->card, ALI_START_A, (uint32) 1 << stream->used_voice); - // start voice - - if (stream->rec) - io_write32(stream->card, ALI_T_DIGIMIXER, - (uint32) 1 << stream->used_voice); - // enable special channel for recording - - return true; -} - - -void -ali_voice_stop(ali_stream *stream) -{ - io_write32(stream->card, ALI_STOP_A, (uint32) 1 << stream->used_voice); - - if (stream->rec) - io_write32(stream->card, ALI_T_DIGIMIXER, 0); -} - - -void -ali_voice_clr_int(ali_stream *stream) -{ - io_write32(stream->card, ALI_AIN_A, (uint32) 1 << stream->used_voice); -} diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_hardware.h b/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_hardware.h deleted file mode 100644 index fa4ddbbaff..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_hardware.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef _ALI_HARDWARE_H -#define _ALI_HARDWARE_H - - -status_t hardware_init(ali_dev *card); -void hardware_terminate(ali_dev *card); - -uint32 ali_read_int(ali_dev *card); - -bool ali_voice_start(ali_stream *stream); -void ali_voice_stop(ali_stream *stream); -void ali_voice_clr_int(ali_stream *stream); - -#endif // _ALI_HARDWARE_H diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_multi.c b/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_multi.c deleted file mode 100644 index 098884a242..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_multi.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ - - -#include -#include -#include -#include -#include - -#include "ac97.h" -#include "queue.h" -#include "driver.h" -#include "util.h" -#include "ali_hardware.h" -#include "ali_multi.h" -#include "debug.h" - - -#define ALI_SUPPORTED_OUTPUT_CHANNELS 2 -#define ALI_SUPPORTED_INPUT_CHANNELS 2 - -#define ALI_VALID_OUTPUT_SAMPLE_RATES (B_SR_8000 | B_SR_11025 | B_SR_12000 | \ - B_SR_16000 | B_SR_22050 | B_SR_24000 | B_SR_32000 | B_SR_44100 | B_SR_48000) -#define ALI_VALID_OUTPUT_FORMATS (B_FMT_16BIT | B_FMT_8BIT_S | B_FMT_8BIT_U) -#define ALI_VALID_INPUT_SAMPLE_RATES (B_SR_48000) -#define ALI_VALID_INPUT_FORMATS ALI_VALID_OUTPUT_FORMATS - -#define ALI_MIXER_GRANULARITY 1.5f - -#define ALI_MIX_OUTPUT_ID 0x000 -#define ALI_MIX_INPUT_ID 0x100 - -#define ALI_MIX_GROUP_ID 1 -#define ALI_MIX_MUTE_ID 2 -#define ALI_MIX_LEFT_ID 3 -#define ALI_MIX_RIGHT_ID 4 -#define ALI_MIX_MONO_ID ALI_MIX_RIGHT_ID -#define ALI_MIX_MIC_BOOST_ID 5 -#define ALI_MIX_INPUT_SELECTOR_ID 6 -#define ALI_MIX_RECORD_INPUT 15 - -#define ALI_MIX_FT_STEREO 1 -#define ALI_MIX_FT_MUTE 2 -#define ALI_MIX_FT_MICBST 4 -#define ALI_MIX_FT_GAIN 8 -#define ALI_MIX_FT_INSEL 16 - -typedef struct { - int32 string_id; - const char *name; - uint8 reg; - float min_gain; - float max_gain; - uint8 features; -} ali_ac97_mixer_info; - -#define ALI_OUTPUT_MIXERS 7 -#define ALI_INPUT_MIXERS 1 -#define ALI_ALL_MIXERS (ALI_OUTPUT_MIXERS + ALI_INPUT_MIXERS) - -static const ali_ac97_mixer_info ali_ac97_mixers[ALI_ALL_MIXERS] = { - {S_MASTER, NULL, AC97_MASTER_VOLUME, -46.5f, 0.0f, ALI_MIX_FT_STEREO | ALI_MIX_FT_MUTE}, - {S_WAVE, NULL, AC97_PCM_OUT_VOLUME, -34.5f, 12.0f, ALI_MIX_FT_STEREO | ALI_MIX_FT_MUTE}, - {S_HEADPHONE, NULL, AC97_AUX_OUT_VOLUME, -34.5f, 12.0f, ALI_MIX_FT_STEREO | ALI_MIX_FT_MUTE}, - {S_CD, NULL, AC97_CD_VOLUME, -34.5f, 12.0f, ALI_MIX_FT_STEREO | ALI_MIX_FT_MUTE}, - {S_LINE, NULL, AC97_LINE_IN_VOLUME, -34.5f, 12.0f, ALI_MIX_FT_STEREO | ALI_MIX_FT_MUTE}, - {S_MIC, NULL, AC97_MIC_VOLUME, -34.5f, 12.0f, ALI_MIX_FT_MUTE | ALI_MIX_FT_MICBST}, - {S_AUX, NULL, AC97_AUX_IN_VOLUME, -34.5f, 12.0f, ALI_MIX_FT_STEREO | ALI_MIX_FT_MUTE}, - {S_null, "Record", AC97_RECORD_GAIN, 0.0f, 22.5f, - ALI_MIX_FT_STEREO | ALI_MIX_FT_MUTE | ALI_MIX_FT_GAIN | ALI_MIX_FT_INSEL}, -}; - -typedef struct { - int32 string_id; - const char *name; -} ali_ac97_mux_input_info; - -#define ALI_MUX_INPUTS 7 - -static const ali_ac97_mux_input_info ali_ac97_mux_inputs[ALI_MUX_INPUTS] = { - {S_MIC, NULL}, - {S_CD, NULL}, - {S_MUTE, NULL}, - {S_AUX, NULL}, - {S_LINE, NULL}, - {S_STEREO_MIX, NULL}, - {S_MONO_MIX, NULL}, -}; - -static const multi_channel_info channel_descriptions[] = { - { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, - { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, - { 2, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, - { 3, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, - { 4, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, - { 5, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, - { 6, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, - { 7, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, -}; - - -static status_t -get_description(void *cookie, multi_description *data) -{ - multi_description description; - if (user_memcpy(&description, data, sizeof(multi_description)) != B_OK) - return B_BAD_ADDRESS; - - description.interface_version = B_CURRENT_INTERFACE_VERSION; - description.interface_minimum = B_CURRENT_INTERFACE_VERSION; - - strcpy(description.friendly_name, "ALI M5451"); - strcpy(description.vendor_info, "Krzysztof Ćwiertnia"); - - description.output_channel_count = ALI_SUPPORTED_OUTPUT_CHANNELS; - description.input_channel_count = ALI_SUPPORTED_INPUT_CHANNELS; - description.output_bus_channel_count = ALI_SUPPORTED_OUTPUT_CHANNELS; - description.input_bus_channel_count = ALI_SUPPORTED_INPUT_CHANNELS; - description.aux_bus_channel_count = 0; - - description.output_formats = ALI_VALID_OUTPUT_FORMATS; - description.output_rates = ALI_VALID_OUTPUT_SAMPLE_RATES; - - description.input_formats = ALI_VALID_INPUT_FORMATS; - description.input_rates = ALI_VALID_INPUT_SAMPLE_RATES; - - description.lock_sources = B_MULTI_LOCK_INTERNAL; - description.timecode_sources = 0; - description.interface_flags = B_MULTI_INTERFACE_PLAYBACK|B_MULTI_INTERFACE_RECORD; - description.start_latency = 30000; - - strcpy(description.control_panel,""); - - if (user_memcpy(data, &description, sizeof(multi_description)) != B_OK) - return B_BAD_ADDRESS; - - if (description.request_channel_count - >= sizeof(channel_descriptions) / sizeof(channel_descriptions[0])) { - if (user_memcpy(data->channels, - &channel_descriptions, sizeof(channel_descriptions)) != B_OK) - return B_BAD_ADDRESS; - } - - return B_OK; -} - - -static status_t -get_enabled_channels(ali_dev *card, multi_channel_enable *data) -{ - B_SET_CHANNEL(data->enable_bits, 0, true); - B_SET_CHANNEL(data->enable_bits, 1, true); - B_SET_CHANNEL(data->enable_bits, 2, true); - B_SET_CHANNEL(data->enable_bits, 3, true); - - data->lock_source = B_MULTI_LOCK_INTERNAL; - - return B_OK; -} - - -static status_t -get_global_format(ali_dev *card, multi_format_info *data) -{ - data->output_latency = 0; - data->input_latency = 0; - data->timecode_kind = 0; - - data->output.format = card->global_output_format.format; - data->output.rate = card->global_output_format.rate; - - data->input.format = card->global_input_format.format; - data->input.rate = card->global_input_format.rate; - - return B_OK; -} - - -static status_t -set_global_format(ali_dev *card, multi_format_info *data) -{ - if ((ALI_VALID_OUTPUT_FORMATS & data->output.format) != 0) - card->global_output_format.format = data->output.format; - if ((ALI_VALID_OUTPUT_SAMPLE_RATES & data->output.rate) != 0) - card->global_output_format.rate = data->output.rate; - - if ((ALI_VALID_INPUT_FORMATS & data->input.format) != 0) - card->global_input_format.format = data->input.format; - if ((ALI_VALID_INPUT_SAMPLE_RATES & data->input.rate) != 0) - card->global_input_format.rate = data->input.rate; - - if (!ali_stream_prepare(card->playback_stream, 2, - card->global_output_format.format, - util_sample_rate_in_bits(card->global_output_format.rate))) - return B_ERROR; - if (!ali_stream_prepare(card->record_stream, 2, - card->global_input_format.format, - util_sample_rate_in_bits(card->global_input_format.rate))) - return B_ERROR; - - return B_OK; -} - - -static void -get_mix_mixer(ali_dev *card, multi_mix_value *mmv, int32 id) -{ - uint8 mixer_id = (uint8) id >> 4, gadget_id = (uint8) id & 0xf; - const ali_ac97_mixer_info *mixer_info; - - if (ALI_ALL_MIXERS <= mixer_id) - return; - mixer_info = &ali_ac97_mixers[mixer_id]; - - switch (gadget_id) { - case ALI_MIX_MUTE_ID: - mmv->u.enable = ((ac97_reg_cached_read(card->codec, mixer_info->reg) - & 0x8000) == 0x8000); - break; - - case ALI_MIX_LEFT_ID: - case ALI_MIX_RIGHT_ID: - { - float val = (ALI_MIXER_GRANULARITY - * ((ac97_reg_cached_read(card->codec, mixer_info->reg) - >> ((gadget_id==ALI_MIX_LEFT_ID)?8:0)) & 0x1f)); - mmv->u.gain = ((mixer_info->features&ALI_MIX_FT_GAIN) - ? mixer_info->min_gain + val : mixer_info->max_gain - val); - } - break; - - case ALI_MIX_MIC_BOOST_ID: - mmv->u.enable = ((ac97_reg_cached_read(card->codec, mixer_info->reg) - & 0x40) == 0x40); - break; - - case ALI_MIX_INPUT_SELECTOR_ID: - mmv->u.mux = (ac97_reg_cached_read(card->codec, - AC97_RECORD_SELECT) & 0x7); - if (ALI_MUX_INPUTS <= mmv->u.mux) { - mmv->u.mux = 0x2; - ac97_reg_cached_write(card->codec, AC97_RECORD_SELECT, 0x202); - } - break; - } -} - - -static status_t -get_mix(ali_dev *card, multi_mix_value_info *mmvi) -{ - int32 i; - - for (i = 0; i < mmvi->item_count; i++) - get_mix_mixer(card, &(mmvi->values[i]), - mmvi->values[i].id - MULTI_AUDIO_BASE_ID); - - return B_OK; -} - - -static void -set_mix_mixer(ali_dev *card, multi_mix_value *mmv, int32 id) -{ - uint8 mixer_id = (uint8) id >> 4, gadget_id = (uint8) id & 0xf; - const ali_ac97_mixer_info *mixer_info; - uint16 val; - - if (ALI_ALL_MIXERS <= mixer_id) - return; - mixer_info = &ali_ac97_mixers[mixer_id]; - - switch (gadget_id) { - case ALI_MIX_MUTE_ID: - val = ac97_reg_cached_read(card->codec, mixer_info->reg); - val = mmv->u.enable ? val | 0x8000 : val & 0x7fff; - ac97_reg_cached_write(card->codec, mixer_info->reg, val); - break; - - case ALI_MIX_LEFT_ID: - case ALI_MIX_RIGHT_ID: - val = ac97_reg_cached_read(card->codec, mixer_info->reg); - val &= (gadget_id == ALI_MIX_LEFT_ID) ? 0x805f : 0x9f00; - val |= (uint16) (((mixer_info->features&ALI_MIX_FT_GAIN) - ? mixer_info->min_gain + mmv->u.gain - : mixer_info->max_gain - mmv->u.gain) - / ALI_MIXER_GRANULARITY) - << ((gadget_id == ALI_MIX_LEFT_ID) ? 8 : 0); - ac97_reg_cached_write(card->codec, mixer_info->reg, val); - break; - - case ALI_MIX_MIC_BOOST_ID: - val = ac97_reg_cached_read(card->codec, mixer_info->reg); - val = mmv->u.enable ? val | 0x40 : val & 0xffbf; - ac97_reg_cached_write(card->codec, mixer_info->reg, val); - break; - - case ALI_MIX_INPUT_SELECTOR_ID: - val = (mmv->u.mux << 8) | mmv->u.mux; - ac97_reg_cached_write(card->codec, AC97_RECORD_SELECT, val); - break; - } -} - - -static status_t -set_mix(ali_dev *card, multi_mix_value_info *mmvi) -{ - int32 i; - - for (i = 0; i < mmvi->item_count; i++) - set_mix_mixer(card, &(mmvi->values[i]), - mmvi->values[i].id - MULTI_AUDIO_BASE_ID); - - return B_OK; -} - - -static int32 -create_group_control(multi_mix_control *multi, int32 *idx, int32 id, - int32 parent, int32 string_id, const char *name) -{ - multi_mix_control *control = multi + *idx; - - control->id = MULTI_AUDIO_BASE_ID + id; - control->parent = parent; - control->flags = B_MULTI_MIX_GROUP; - control->master = MULTI_AUDIO_MASTER_ID; - control->string = string_id; - if (string_id == S_null && name) - strcpy(control->name, name); - - (*idx)++; - - return control->id; -} - - -static void -create_vol_control(multi_mix_control *multi, int32 *idx, int32 id, int32 parent) -{ - const ali_ac97_mixer_info *mixer_info; - multi_mix_control *control; - - id &= 0xf; - - if (ALI_ALL_MIXERS <= id) - return; - mixer_info = &ali_ac97_mixers[id]; - - id <<= 4; - - parent = create_group_control(multi, idx, (parent & 0x100) | id - | ALI_MIX_GROUP_ID, parent, mixer_info->string_id, mixer_info->name); - - control = multi + *idx; - - if (mixer_info->features & ALI_MIX_FT_MUTE) { - control->id = MULTI_AUDIO_BASE_ID | (parent & 0x100) | id - | ALI_MIX_MUTE_ID; - control->parent = parent; - control->flags = B_MULTI_MIX_ENABLE; - control->master = MULTI_AUDIO_MASTER_ID; - control->string = S_MUTE; - - control++; - (*idx)++; - } - - control->id = MULTI_AUDIO_BASE_ID | (parent & 0x100) | id - | ((mixer_info->features&ALI_MIX_FT_STEREO) - ?ALI_MIX_LEFT_ID:ALI_MIX_MONO_ID); - control->parent = parent; - control->flags = B_MULTI_MIX_GAIN; - control->master = MULTI_AUDIO_MASTER_ID; - control->string = S_GAIN; - // S_null; ? FIXME - - control->u.gain.min_gain = mixer_info->min_gain; - control->u.gain.max_gain = mixer_info->max_gain; - control->u.gain.granularity = ALI_MIXER_GRANULARITY; - - if (mixer_info->features & ALI_MIX_FT_STEREO) { - control[1] = control[0]; - control++; - (*idx)++; - - control->master = control->id; - control->id = MULTI_AUDIO_BASE_ID | (parent & 0x100) | id - | ALI_MIX_RIGHT_ID; - } - - control++; - (*idx)++; - - if (mixer_info->features & ALI_MIX_FT_MICBST) { - control->id = MULTI_AUDIO_BASE_ID | (parent & 0x100) | id - | ALI_MIX_MIC_BOOST_ID; - control->parent = parent; - control->flags = B_MULTI_MIX_ENABLE; - control->master = MULTI_AUDIO_MASTER_ID; - control->string = S_null; - strcpy(control->name, "+20dB"); - - control++; - (*idx)++; - } - - if (mixer_info->features & ALI_MIX_FT_INSEL) { - int32 is_parent; - const ali_ac97_mux_input_info *mux_input; - - is_parent = control->id = MULTI_AUDIO_BASE_ID | (parent & 0x100) - | id | ALI_MIX_INPUT_SELECTOR_ID; - control->parent = parent; - control->flags = B_MULTI_MIX_MUX; - control->master = MULTI_AUDIO_MASTER_ID; - control->string = S_INPUT; - - control++; - (*idx)++; - - for (id = 0; id < ALI_MUX_INPUTS; id++) { - mux_input = &ali_ac97_mux_inputs[id]; - - control->id = MULTI_AUDIO_BASE_ID | (parent & 0x100) | (id<<4) - | ALI_MIX_RECORD_INPUT; - control->parent = is_parent; - control->flags = B_MULTI_MIX_MUX_VALUE; - control->master = MULTI_AUDIO_MASTER_ID; - control->string = mux_input->string_id; - if (control->string == S_null && mux_input->name) - strcpy(control->name, mux_input->name); - - control++; - (*idx)++; - } - } -} - - -static status_t -list_mix_controls(ali_dev *card, multi_mix_control_info *mmci) -{ - int32 index = 0, parent, i; - - parent = create_group_control(mmci->controls, &index, ALI_MIX_OUTPUT_ID, 0, - S_OUTPUT, NULL); - for (i = 0; i < ALI_OUTPUT_MIXERS; i++) - create_vol_control(mmci->controls, &index, i, parent); - - parent = create_group_control(mmci->controls, &index, ALI_MIX_INPUT_ID, 0, - S_INPUT, NULL); - for (i = ALI_OUTPUT_MIXERS; i < ALI_OUTPUT_MIXERS + ALI_INPUT_MIXERS; i++) - create_vol_control(mmci->controls, &index, i, parent); - - mmci->control_count = index; - - return B_OK; -} - - -static status_t -get_buffers(ali_dev *card, multi_buffer_list *data) -{ - uint8 buf_ndx, ch_ndx; - - data->return_playback_buffers = card->playback_stream->buf_count; - data->return_playback_channels = card->playback_stream->channels; - data->return_playback_buffer_size = card->playback_stream->buf_frames; - - for (buf_ndx = 0; buf_ndxplayback_stream->buf_count; buf_ndx++) - for (ch_ndx = 0; ch_ndx < card->playback_stream->channels; ch_ndx++) - ali_stream_get_buffer_part(card->playback_stream, ch_ndx, buf_ndx, - &data->playback_buffers[buf_ndx][ch_ndx].base, - &data->playback_buffers[buf_ndx][ch_ndx].stride); - - data->return_record_buffers = card->record_stream->buf_count; - data->return_record_channels = card->record_stream->channels; - data->return_record_buffer_size = card->record_stream->buf_frames; - - for (buf_ndx = 0; buf_ndx < card->record_stream->buf_count; buf_ndx++) - for (ch_ndx = 0; ch_ndx < card->record_stream->channels; ch_ndx++) - ali_stream_get_buffer_part(card->record_stream, ch_ndx, buf_ndx, - &data->record_buffers[buf_ndx][ch_ndx].base, - &data->record_buffers[buf_ndx][ch_ndx].stride); - - return B_OK; -} - - -static status_t -buffer_exchange(ali_dev *card, multi_buffer_info *info) -{ - status_t res; - ali_stream *play_s, *rec_s; - - multi_buffer_info buffer_info; - if (user_memcpy(&buffer_info, info, sizeof(multi_buffer_info)) != B_OK) - return B_BAD_ADDRESS; - - play_s = card->playback_stream; - rec_s = card->record_stream; - - if (!play_s || !rec_s) - return B_ERROR; - - if (!play_s->is_playing) - if (!ali_stream_start(play_s)) - return B_ERROR; - if (!rec_s->is_playing) - if (!ali_stream_start(rec_s)) - return B_ERROR; - - res = acquire_sem_etc(card->sem_buf_ready, 1, B_CAN_INTERRUPT, 0); - if (res != B_OK) { - TRACE("buffer_exchange: error acquiring semaphore\n"); - return res; - } - - LOCK(card->lock_sts); - - buffer_info.played_frames_count = play_s->frames_count; - buffer_info.played_real_time = play_s->real_time; - buffer_info.playback_buffer_cycle = play_s->buffer_cycle; - - buffer_info.recorded_frames_count = rec_s->frames_count; - buffer_info.recorded_real_time = rec_s->real_time; - buffer_info.record_buffer_cycle = rec_s->buffer_cycle; - - UNLOCK(card->lock_sts); - - if (user_memcpy(info, &buffer_info, sizeof(multi_buffer_info)) != B_OK) - return B_BAD_ADDRESS; - - return B_OK; -} - - -static status_t -force_stop(ali_dev *card) -{ - ali_stream *stream; - - TRACE("force_stop\n"); - - LIST_FOREACH(stream, &card->streams, next) { - ali_stream_stop(stream); - } - - return B_OK; -} - - -status_t -multi_audio_control(void *cookie, uint32 op, void *arg, size_t len) -{ - switch (op) { - case B_MULTI_GET_DESCRIPTION: return get_description(cookie, arg); - - case B_MULTI_GET_EVENT_INFO: return B_ERROR; - case B_MULTI_SET_EVENT_INFO: return B_ERROR; - case B_MULTI_GET_EVENT: return B_ERROR; - - case B_MULTI_GET_ENABLED_CHANNELS: return get_enabled_channels(cookie, arg); - case B_MULTI_SET_ENABLED_CHANNELS: return B_OK; - case B_MULTI_GET_GLOBAL_FORMAT: return get_global_format(cookie, arg); - case B_MULTI_SET_GLOBAL_FORMAT: return set_global_format(cookie, arg); - - case B_MULTI_GET_CHANNEL_FORMATS: return B_ERROR; - case B_MULTI_SET_CHANNEL_FORMATS: return B_ERROR; - case B_MULTI_GET_MIX: return get_mix(cookie, arg); - case B_MULTI_SET_MIX: return set_mix(cookie, arg); - - case B_MULTI_LIST_MIX_CHANNELS: return B_ERROR; - case B_MULTI_LIST_MIX_CONTROLS: return list_mix_controls(cookie, arg); - case B_MULTI_LIST_MIX_CONNECTIONS: return B_ERROR; - - case B_MULTI_GET_BUFFERS: return get_buffers(cookie, arg); - case B_MULTI_SET_BUFFERS: return B_ERROR; - // do not support in-software buffers - - case B_MULTI_SET_START_TIME: return B_ERROR; - case B_MULTI_BUFFER_EXCHANGE: return buffer_exchange(cookie, arg); - case B_MULTI_BUFFER_FORCE_STOP: return force_stop(cookie); - } - - return B_BAD_VALUE; -} diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_multi.h b/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_multi.h deleted file mode 100644 index 77bd19ee07..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/ali_multi.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef _ALI_MULTI_H -#define _ALI_MULTI_H - - -status_t multi_audio_control(void *cookie, uint32 op, void *arg, size_t len); - -#endif // _ALI_MULTI_H diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/debug.h b/src/add-ons/kernel/drivers/audio/ac97/ali5451/debug.h deleted file mode 100644 index a13d47418a..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/debug.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef _ALI_DEBUG_H -#define _ALI_DEBUG_H - - -#ifdef TRACE -#undef TRACE -#endif - -#define TRACE_ALI - -#ifdef TRACE_ALI -#define TRACE(a...) dprintf("\33[34mali5451:\33[0m " a) -#else -#define TRACE(a...) -#endif - -#endif // _ALI_DEBUG_H diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/driver.c b/src/add-ons/kernel/drivers/audio/ac97/ali5451/driver.c deleted file mode 100644 index 70c2ef8a0c..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/driver.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ - - -#include -#include -#include -#include -#include -#include - -#include "ac97.h" -#include "queue.h" -#include "ali_multi.h" -#include "driver.h" -#include "util.h" -#include "ali_hardware.h" -#include "debug.h" - - -int32 api_version = B_CUR_DRIVER_API_VERSION; - -int32 gCardsCount; -ali_dev gCards[MAX_CARDS]; -pci_module_info *gPCI; - - -/* streams handling */ - - -static ali_stream * -ali_stream_new(ali_dev *card, bool rec, uint8 buf_count) -{ - ali_stream *stream; - - if (!buf_count) - return NULL; - - stream = malloc(sizeof(ali_stream)); - if (!stream) - return NULL; - - stream->card = card; - - stream->buffer = NULL; - - stream->buf_count = buf_count; - stream->buf_frames = 0; - - stream->rec = rec; - stream->channels = 0; - stream->format.format = 0; - stream->format.rate = 0; - - stream->is_playing = false; - - stream->used_voice = -1; - - stream->frames_count = 0; - stream->real_time = 0; - stream->buffer_cycle = (rec ? buf_count - 1 : 0); - - LOCK(card->lock_sts); - LIST_INSERT_HEAD(&(card->streams), stream, next); - UNLOCK(card->lock_sts); - - return stream; -} - - -static void -ali_stream_unprepare(ali_stream *stream) -{ - ali_stream_stop(stream); - - if (stream->buffer) { - ali_mem_free(stream->card, stream->buffer->log_base); - stream->buffer = NULL; - } - - stream->channels = 0; - stream->format.format = 0; - stream->format.rate = 0; - - if (-1 < stream->used_voice) { - LOCK(stream->card->lock_voices); - stream->card->used_voices &= ~((uint32) 1 << stream->used_voice); - UNLOCK(stream->card->lock_voices); - } -} - - -static void -ali_stream_delete(ali_stream *stream) -{ - ali_stream_unprepare(stream); - - LOCK(stream->card->lock_sts); - LIST_REMOVE(stream, next); - UNLOCK(stream->card->lock_sts); - - free(stream); -} - - -bool -ali_stream_prepare(ali_stream *stream, uint8 channels, uint32 format, - uint32 sample_rate) -{ - uint8 frame_size = util_format_to_sample_size(format) * channels, ch; - - TRACE("stream_prepare: frame_size: %d\n", (int) frame_size); - - if (!frame_size) - return false; - - if (stream->channels == channels && stream->format.format == format && - stream->format.rate == sample_rate) - return true; - - ali_stream_unprepare(stream); - - stream->channels = channels; - stream->format.format = format; - stream->format.rate = sample_rate; - - // find and set voice - LOCK(stream->card->lock_voices); - if (stream->rec) { - if ((stream->card->used_voices & (uint32) 1 << ALI_RECORD_VOICE) == 0) { - stream->used_voice = ALI_RECORD_VOICE; - stream->card->used_voices |= (uint32) 1 << ALI_RECORD_VOICE; - } - } else { - for (ch = 0; ch < ALI_VOICES; ch++) { - if ((stream->card->used_voices & (uint32) 1 << ch) == 0) { - stream->used_voice = ch; - stream->card->used_voices |= (uint32) 1 << ch; - break; - } - } - } - UNLOCK(stream->card->lock_voices); - - if (stream->used_voice == -1) { - ali_stream_unprepare(stream); - TRACE("stream_prepare: no free voices\n"); - return false; - } - - stream->buf_frames = util_get_buffer_length_for_rate(stream->format.rate); - - stream->buffer = ali_mem_alloc(stream->card, stream->buf_frames - * frame_size * stream->buf_count); - if (!stream->buffer) { - ali_stream_unprepare(stream); - TRACE("stream_prepare: failed to create buffer\n"); - return false; - } - - return true; -} - - -bool -ali_stream_start(ali_stream *stream) -{ - if (stream->is_playing) - return true; - - if (!ali_voice_start(stream)) { - TRACE("stream_start: trouble starting voice\n"); - return false; - } - - stream->is_playing = true; - - TRACE("stream_start: %s using voice: %d\n", - stream->rec?"recording":"playing", stream->used_voice); - - return true; -} - - -void -ali_stream_stop(ali_stream *stream) -{ - if (!stream->is_playing) - return; - - ali_voice_stop(stream); - - stream->is_playing = false; -} - - -void -ali_stream_get_buffer_part(ali_stream *stream, uint8 ch_ndx, uint8 buf_ndx, - char **buffer, size_t *stride) -{ - uint8 sample_size = util_format_to_sample_size(stream->format.format), - frame_size = sample_size * stream->channels; - - *buffer = stream->buffer->log_base + frame_size * stream->buf_frames - * buf_ndx + sample_size * ch_ndx; - *stride = frame_size; -} - - -static int32 -ali_interrupt_handler(void *cookie) -{ - ali_dev *card = (ali_dev *) cookie; - bool handled = false; - uint32 aina; - ali_stream *stream; - - aina = ali_read_int(card); - if (!aina) - goto exit_; - - LIST_FOREACH(stream, &card->streams, next) { - if (!stream->is_playing || stream->used_voice == -1) - continue; - - if ((aina & (uint32) 1 << stream->used_voice) == 0) - continue; - - ali_voice_clr_int(stream); - // clear interrupt flag - - // interrupts are disabled already when entering handler, lock only - acquire_spinlock(&card->lock_sts); - stream->frames_count += stream->buf_frames; - stream->real_time = system_time(); - stream->buffer_cycle = (stream->buffer_cycle + 1) % stream->buf_count; - release_spinlock(&card->lock_sts); - - release_sem_etc(card->sem_buf_ready, 1, B_DO_NOT_RESCHEDULE); - - handled = true; - } - -exit_: - if (!handled) - TRACE("unhandled interrupt\n"); - - return handled ? B_INVOKE_SCHEDULER : B_UNHANDLED_INTERRUPT; -} - - -static void -make_device_names(ali_dev *card) -{ - sprintf(card->name, DEVFS_PATH_FORMAT, card - gCards + 1); -} - - -static void -ali_terminate(ali_dev *card) -{ - TRACE("terminate\n"); - - remove_io_interrupt_handler(card->irq, ali_interrupt_handler, card); - - if (card->sem_buf_ready != -1) - delete_sem(card->sem_buf_ready); - - hardware_terminate(card); -} - - -static status_t -ali_setup(ali_dev *card) -{ - uint32 cmd_reg; - status_t res; - - make_device_names(card); - - cmd_reg = (*gPCI->read_pci_config)(card->info.bus, card->info.device, - card->info.function, PCI_command, 2); - cmd_reg |= PCI_command_io | PCI_command_memory | PCI_command_master; - (*gPCI->write_pci_config)(card->info.bus, card->info.device, - card->info.function, PCI_command, 2, cmd_reg); - - card->io_base = card->info.u.h0.base_registers[0]; - TRACE("setup: base io is: %08x\n", (unsigned int) card->io_base); - - card->irq = card->info.u.h0.interrupt_line; - TRACE("setup: irq is: %02x\n", card->irq); - - card->codec = NULL; - card->lock_hw = 0; - card->lock_sts = 0; - card->lock_voices = 0; - - card->sem_buf_ready = create_sem(0, "ali5451_buf_ready"); - if (card->sem_buf_ready < B_OK) { - TRACE("setup: failed to create semaphore\n"); - return -1; - } - - TRACE("setup: revision: %02x\n", card->info.revision); - - card->playback_stream = NULL; - card->record_stream = NULL; - - card->used_voices = 0; - - card->global_output_format.format = B_FMT_16BIT; - card->global_output_format.rate = B_SR_48000; - card->global_input_format = card->global_output_format; - - res = install_io_interrupt_handler(card->irq, ali_interrupt_handler, card, - 0); - if (res != B_OK) { - TRACE("setup: cannot install interrupt handler\n"); - return res; - } - - res = hardware_init(card); - if (res != B_OK) - ali_terminate(card); - - return res; -} - - -/* driver's public functions */ - - -status_t -init_hardware(void) -{ - status_t res = ENODEV; - pci_info info; - int32 i; - - if (get_module(B_PCI_MODULE_NAME, (module_info**) &gPCI) != B_OK) - return res; - - for (i = 0; (*gPCI->get_nth_pci_info)(i, &info) == B_OK; i++) { - if (info.class_base == PCI_multimedia && - info.vendor_id == ALI_VENDOR_ID && - info.device_id == ALI_DEVICE_ID) { - TRACE("hardware found\n"); - res = B_OK; - break; - } - } - - put_module(B_PCI_MODULE_NAME); - - return res; -} - - -status_t -init_driver(void) -{ - pci_info info; - int32 i; - status_t err; - - if (get_module(B_PCI_MODULE_NAME, (module_info**) &gPCI) != B_OK) - return ENODEV; - - gCardsCount = 0; - - for (i = 0; (*gPCI->get_nth_pci_info)(i, &info) == B_OK; i++) { - if (info.class_base == PCI_multimedia && - info.vendor_id == ALI_VENDOR_ID && - info.device_id == ALI_DEVICE_ID) { - if (gCardsCount == MAX_CARDS) { - TRACE("init_driver: too many cards\n"); - break; - } - - memset(&gCards[gCardsCount], 0, sizeof(ali_dev)); - gCards[gCardsCount].info = info; - if ((err = (*gPCI->reserve_device)(info.bus, info.device, info.function, - DRIVER_NAME, &gCards[gCardsCount])) < B_OK) { - dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", - DRIVER_NAME, info.bus, info.device, info.function, - strerror(err)); - continue; - } - if (ali_setup(&gCards[gCardsCount])) { - TRACE("init_driver: setup of ali %ld failed\n", gCardsCount + 1); - (*gPCI->unreserve_device)(info.bus, info.device, info.function, - DRIVER_NAME, &gCards[gCardsCount]); - } - else - gCardsCount++; - } - } - - if (!gCardsCount) { - put_module(B_PCI_MODULE_NAME); - TRACE("init_driver: no cards found\n"); - return ENODEV; - } - - return B_OK; -} - - -void -uninit_driver(void) -{ - int32 i = gCardsCount; - - while (i--) { - ali_terminate(&gCards[i]); - (*gPCI->unreserve_device)(gCards[i].info.bus, gCards[i].info.device, - gCards[i].info.function, DRIVER_NAME, &gCards[i]); - } - memset(&gCards, 0, sizeof(gCards)); - - put_module(B_PCI_MODULE_NAME); - - gCardsCount = 0; -} - - -const char ** -publish_devices(void) -{ - static const char *names[MAX_CARDS + 1]; - int32 i; - - for (i = 0; i < gCardsCount; i++) - names[i] = gCards[i].name; - names[gCardsCount] = NULL; - - return (const char **) names; -} - - -/* driver's hooks */ - - -static status_t -ali_audio_open(const char *name, uint32 flags, void **cookie) -{ - ali_dev *card = NULL; - int32 i; - - for (i = 0; i < gCardsCount; i++) { - if (!strcmp(gCards[i].name, name)) { - card = &gCards[i]; - } - } - - if (!card) { - TRACE("audio_open: card not found\n"); - return B_ERROR; - } - - if (card->playback_stream || card->record_stream) - return B_ERROR; - - *cookie = card; - - card->playback_stream = ali_stream_new(card, false, ALI_BUF_CNT); - card->record_stream = ali_stream_new(card, true, ALI_BUF_CNT); - - if (!ali_stream_prepare(card->playback_stream, 2, - card->global_output_format.format, - util_sample_rate_in_bits(card->global_output_format.rate))) - return B_ERROR; - if (!ali_stream_prepare(card->record_stream, 2, - card->global_input_format.format, - util_sample_rate_in_bits(card->global_input_format.rate))) - return B_ERROR; - - return B_OK; -} - - -static status_t -ali_audio_read(void *cookie, off_t a, void *b, size_t *num_bytes) -{ - TRACE("audio_read attempt\n"); - - *num_bytes = 0; - return B_IO_ERROR; -} - - -static status_t -ali_audio_write(void *cookie, off_t a, const void *b, size_t *num_bytes) -{ - TRACE("audio_write attempt\n"); - - *num_bytes = 0; - return B_IO_ERROR; -} - - -static status_t -ali_audio_control(void *cookie, uint32 op, void *arg, size_t len) -{ - if (!cookie) - TRACE("audio_control: no cookie\n"); - - return cookie?multi_audio_control(cookie, op, arg, len):B_BAD_VALUE; -} - - -static status_t -ali_audio_close(void *cookie) -{ - ali_dev *card = (ali_dev *) cookie; - ali_stream *stream; - - LIST_FOREACH(stream, &card->streams, next) { - ali_stream_stop(stream); - } - - return B_OK; -} - - -static status_t -ali_audio_free(void *cookie) -{ - ali_dev *card = (ali_dev *) cookie; - - while (!LIST_EMPTY(&card->streams)) - ali_stream_delete(LIST_FIRST(&card->streams)); - - card->playback_stream = NULL; - card->record_stream = NULL; - - return B_OK; -} - - -device_hooks driver_hooks = { - ali_audio_open, - ali_audio_close, - ali_audio_free, - ali_audio_control, - ali_audio_read, - ali_audio_write -}; - - -device_hooks * -find_device(const char *name) -{ - return &driver_hooks; -} diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/driver.h b/src/add-ons/kernel/drivers/audio/ac97/ali5451/driver.h deleted file mode 100644 index 4435b40fb9..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/driver.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef _ALI_AUDIO_DRIVER_H -#define _ALI_AUDIO_DRIVER_H - - -#define MULTI_AUDIO_BASE_ID 1024 -#define MULTI_AUDIO_DEV_PATH "audio/hmulti" -#define MULTI_AUDIO_MASTER_ID 0 - -#define DEVFS_PATH_FORMAT MULTI_AUDIO_DEV_PATH "/ali5451/%lu" - -#define MAX_CARDS 3 -#define DEVNAME 32 - -#define ALI_VENDOR_ID 0x10b9 -#define ALI_DEVICE_ID 0x5451 - -#define ALI_BUF_CNT 2 -#define ALI_MAX_CHN 2 -#define ALI_VOICES 32 -#define ALI_RECORD_VOICE 31 - -#define DRIVER_NAME "ali5451" - -typedef struct _ali_mem -{ - LIST_ENTRY(_ali_mem) next; - - void *log_base; - void *phy_base; - - area_id area; - size_t size; -} ali_mem; - -typedef struct { - uint32 format; - uint32 rate; -} ali_format; - -typedef struct _ali_stream -{ - LIST_ENTRY(_ali_stream) next; - - struct _ali_dev *card; - - ali_mem *buffer; - - uint8 buf_count; - uint32 buf_frames; - - bool rec; - uint8 channels; - ali_format format; - - bool is_playing; - - int8 used_voice; - - // multi_audio - volatile int64 frames_count; - volatile bigtime_t real_time; - volatile int32 buffer_cycle; -} ali_stream; - -typedef struct _ali_dev -{ - char name[DEVNAME]; - pci_info info; - ulong io_base; - uint8 irq; - - ac97_dev *codec; - - spinlock lock_hw; - spinlock lock_sts; - spinlock lock_voices; - sem_id sem_buf_ready; - - ali_stream *playback_stream; - ali_stream *record_stream; - - uint32 used_voices; - - ali_format global_output_format; - ali_format global_input_format; - - LIST_HEAD(, _ali_stream) streams; - LIST_HEAD(, _ali_mem) mems; -} ali_dev; - -#define LOCK(_lock) \ - { \ - cpu_status cp = disable_interrupts(); \ - acquire_spinlock(&_lock) -#define UNLOCK(_lock) \ - release_spinlock(&_lock); \ - restore_interrupts(cp); \ - } - -bool ali_stream_prepare(ali_stream *stream, uint8 channels, uint32 format, - uint32 sample_rate); -bool ali_stream_start(ali_stream *stream); -void ali_stream_stop(ali_stream *stream); -void ali_stream_get_buffer_part(ali_stream *stream, uint8 ch_ndx, uint8 buf_ndx, - char ** buffer, size_t *stride); - -#endif // _ALI_AUDIO_DRIVER_H diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/queue.h b/src/add-ons/kernel/drivers/audio/ac97/ali5451/queue.h deleted file mode 100644 index 396c70fb2e..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/queue.h +++ /dev/null @@ -1,529 +0,0 @@ -/* $NetBSD: queue.h,v 1.31 2002/06/01 23:51:05 lukem Exp $ */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. - * - * A singly-linked list is headed by a single forward pointer. The - * elements are singly linked for minimum space and pointer manipulation - * overhead at the expense of O(n) removal for arbitrary elements. New - * elements can be added to the list after an existing element or at the - * head of the list. Elements being removed from the head of the list - * should use the explicit macro for this purpose for optimum - * efficiency. A singly-linked list may only be traversed in the forward - * direction. Singly-linked lists are ideal for applications with large - * datasets and few or no removals or for implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so only elements can only be removed from the - * head of the list. New elements can be added to the list after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ -#if defined(_KERNEL) && defined(QUEUEDEBUG) -#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ - if ((head)->lh_first && \ - (head)->lh_first->field.le_prev != &(head)->lh_first) \ - panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); -#define QUEUEDEBUG_LIST_OP(elm, field) \ - if ((elm)->field.le_next && \ - (elm)->field.le_next->field.le_prev != \ - &(elm)->field.le_next) \ - panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ - if (*(elm)->field.le_prev != (elm)) \ - panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__); -#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ - (elm)->field.le_next = (void *)1L; \ - (elm)->field.le_prev = (void *)1L; -#else -#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) -#define QUEUEDEBUG_LIST_OP(elm, field) -#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) -#endif - -#define LIST_INIT(head) do { \ - (head)->lh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QUEUEDEBUG_LIST_OP((listelm), field) \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QUEUEDEBUG_LIST_OP((listelm), field) \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (/*CONSTCOND*/0) - -#define LIST_REMOVE(elm, field) do { \ - QUEUEDEBUG_LIST_OP((elm), field) \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ - QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ -} while (/*CONSTCOND*/0) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = ((head)->lh_first); \ - (var); \ - (var) = ((var)->field.le_next)) - -/* - * List access methods. - */ -#define LIST_EMPTY(head) ((head)->lh_first == NULL) -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) - -#define SLIST_INIT(head) do { \ - (head)->slh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (/*CONSTCOND*/0) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = (head)->slh_first; \ - while(curelm->field.sle_next != (elm)) \ - curelm = curelm->field.sle_next; \ - curelm->field.sle_next = \ - curelm->field.sle_next->field.sle_next; \ - } \ -} while (/*CONSTCOND*/0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (/*CONSTCOND*/0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define SIMPLEQ_REMOVE(head, elm, type, field) do { \ - if ((head)->sqh_first == (elm)) { \ - SIMPLEQ_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->sqh_first; \ - while (curelm->field.sqe_next != (elm)) \ - curelm = curelm->field.sqe_next; \ - if ((curelm->field.sqe_next = \ - curelm->field.sqe_next->field.sqe_next) == NULL) \ - (head)->sqh_last = &(curelm)->field.sqe_next; \ - } \ -} while (/*CONSTCOND*/0) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for ((var) = ((head)->sqh_first); \ - (var); \ - (var) = ((var)->field.sqe_next)) - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * Tail queue functions. - */ -#if defined(_KERNEL) && defined(QUEUEDEBUG) -#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ - if ((head)->tqh_first && \ - (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ - panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); -#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ - if (*(head)->tqh_last != NULL) \ - panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__); -#define QUEUEDEBUG_TAILQ_OP(elm, field) \ - if ((elm)->field.tqe_next && \ - (elm)->field.tqe_next->field.tqe_prev != \ - &(elm)->field.tqe_next) \ - panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__); -#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ - (elm)->field.tqe_next = (void *)1L; \ - (elm)->field.tqe_prev = (void *)1L; -#else -#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) -#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) -#define QUEUEDEBUG_TAILQ_OP(elm, field) -#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) -#endif - -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QUEUEDEBUG_TAILQ_OP((listelm), field) \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QUEUEDEBUG_TAILQ_OP((listelm), field) \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - QUEUEDEBUG_TAILQ_OP((elm), field) \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ - QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ -} while (/*CONSTCOND*/0) - -/* - * Tail queue access methods. - */ -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = ((head)->tqh_first); \ - (var); \ - (var) = ((var)->field.tqe_next)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ - (var); \ - (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { (void *)&head, (void *)&head } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = (void *)(head); \ - (head)->cqh_last = (void *)(head); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = (void *)(head); \ - if ((head)->cqh_last == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = (void *)(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for ((var) = ((head)->cqh_first); \ - (var) != (void *)(head); \ - (var) = ((var)->field.cqe_next)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for ((var) = ((head)->cqh_last); \ - (var) != (void *)(head); \ - (var) = ((var)->field.cqe_prev)) - -/* - * Circular queue access methods. - */ -#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#endif /* !_SYS_QUEUE_H_ */ diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/util.c b/src/add-ons/kernel/drivers/audio/ac97/ali5451/util.c deleted file mode 100644 index fafc9459e0..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/util.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * Original code for memory management is - * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ - - -#include -#include -#include -#include -#include - -#include "ac97.h" -#include "queue.h" -#include "driver.h" -#include "util.h" -#include "debug.h" - - -/* memory management */ - - -static uint32 -round_to_pagesize(uint32 size) -{ - return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); -} - - -static area_id -alloc_mem(void **phy, void **log, size_t size, const char *name) -{ -// TODO: phy should be phys_addr_t*! - physical_entry pe; - void *logadr; - area_id areaid; - status_t rv; - - size = round_to_pagesize(size); - areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS, size, - B_32_BIT_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); - // TODO: The rest of the code doesn't deal correctly with physical - // addresses > 4 GB, so we have to force 32 bit addresses here. - if (areaid < B_OK) { - TRACE("alloc_mem: couldn't allocate area %s\n", name); - return B_ERROR; - } - rv = get_memory_map(logadr, size, &pe, 1); - if (rv < B_OK) { - delete_area(areaid); - TRACE("alloc_mem: couldn't map %s\n",name); - return B_ERROR; - } - memset(logadr, 0, size); - if (log) - *log = logadr; - if (phy) - *phy = (void*)(addr_t)pe.address; - - return areaid; -} - - -static ali_mem -*ali_mem_new(ali_dev *card, size_t size) -{ - ali_mem *mem; - - if (!(mem = malloc(sizeof(*mem)))) - return NULL; - - mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "ali buffer"); - mem->size = size; - - if (mem->area < B_OK) { - free(mem); - return NULL; - } - - return mem; -} - - -static void -ali_mem_delete(ali_mem *mem) -{ - if (B_OK < mem->area) - delete_area(mem->area); - - free(mem); -} - - -void * -ali_mem_alloc(ali_dev *card, size_t size) -{ - ali_mem *mem; - - mem = ali_mem_new(card, size); - if (!mem) - return NULL; - - LIST_INSERT_HEAD(&(card->mems), mem, next); - - return mem; -} - - -void -ali_mem_free(ali_dev *card, void *ptr) -{ - ali_mem *mem; - - LIST_FOREACH(mem, &card->mems, next) { - if (mem->log_base != ptr) - continue; - - LIST_REMOVE(mem, next); - - ali_mem_delete(mem); - break; - } -} - - -/* misc utils */ - - -uint8 -util_format_to_sample_size(uint32 format) -{ - switch (format) { - case B_FMT_8BIT_U: - case B_FMT_8BIT_S: return 1; - - case B_FMT_16BIT: return 2; - - case B_FMT_18BIT: - case B_FMT_24BIT: - case B_FMT_32BIT: - case B_FMT_FLOAT: return 4; - - default: return 0; - } -} - - -bool -util_format_is_signed(uint32 format) -{ - return (format == B_FMT_8BIT_S || format == B_FMT_16BIT); -} - - -uint32 -util_get_buffer_length_for_rate(uint32 rate) -{ - // values are based on Haiku's hda driver - - switch (rate) { - case 8000: - case 11025: return 512; - - case 16000: - case 22050: return 1024; - - case 32000: - case 44100: - case 48000: return 2048; - } - - return 2048; -} - - -uint32 -util_sample_rate_in_bits(uint32 rate) -{ - switch (rate) { - case B_SR_8000: return 8000; - case B_SR_11025: return 11025; - case B_SR_12000: return 12000; - case B_SR_16000: return 16000; - case B_SR_22050: return 22050; - case B_SR_24000: return 24000; - case B_SR_32000: return 32000; - case B_SR_44100: return 44100; - case B_SR_48000: return 48000; - } - - return 0; -} diff --git a/src/add-ons/kernel/drivers/audio/ac97/ali5451/util.h b/src/add-ons/kernel/drivers/audio/ac97/ali5451/util.h deleted file mode 100644 index ec2fe57355..0000000000 --- a/src/add-ons/kernel/drivers/audio/ac97/ali5451/util.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). - * - * Original code for memory management is - * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr). - * - * All Rights Reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef _UTIL_H -#define _UTIL_H - - -void *ali_mem_alloc(ali_dev *card, size_t size); -void ali_mem_free(ali_dev *card, void *ptr); - -uint8 util_format_to_sample_size(uint32 format); -bool util_format_is_signed(uint32 format); -uint32 util_get_buffer_length_for_rate(uint32 rate); -uint32 util_sample_rate_in_bits(uint32 rate); - -#endif // _UTIL_H diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.cpp new file mode 100644 index 0000000000..6ba828766e --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.cpp @@ -0,0 +1,625 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + * Copyright for ali5451 support: + * (c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). + */ + + +#include "Device.h" + +#include + +#include "Settings.h" +#include "Registers.h" + + +Device::Device(Device::Info &DeviceInfo, pci_info &PCIInfo) + : + fStatus(B_ERROR), + fPCIInfo(PCIInfo), + fInfo(DeviceInfo), + fIOBase(0), + fHWSpinlock(0), + fInterruptsNest(0), + fBuffersReadySem(-1), + fMixer(this), + fPlaybackStream(this, false), + fRecordStream(this, true) +{ + fStatus = _ReserveDeviceOnBus(true); + if (fStatus != B_OK) + return; // InitCheck will handle the rest + + uint32 cmdRegister = gPCI->read_pci_config(PCIInfo.bus, + PCIInfo.device, PCIInfo.function, PCI_command, 2); + TRACE("cmdRegister:%#010x\n", cmdRegister); + cmdRegister |= PCI_command_io | PCI_command_memory | PCI_command_master; + gPCI->write_pci_config(PCIInfo.bus, PCIInfo.device, + PCIInfo.function, PCI_command, 2, cmdRegister); + + fIOBase = PCIInfo.u.h0.base_registers[0]; + TRACE("fIOBase:%#010x\n", fIOBase); + + fStatus = B_OK; +} + + +Device::~Device() +{ + fMixer.Free(); + _ReserveDeviceOnBus(false); + + if (fBuffersReadySem > B_OK) { + delete_sem(fBuffersReadySem); + } +} + + +void +Device::_ResetCard(uint32 resetMask, uint32 releaseMask) +{ + // disable Legacy Control + gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, 0x40, 4, 0); + uint32 cmdReg = gPCI->read_pci_config(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, 0x44, 4); + gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, 0x44, 4, cmdReg & 0xffff0000); + snooze(100); + + // audio engine reset + cmdReg = gPCI->read_pci_config(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, 0x44, 4); + gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, 0x44, 4, cmdReg | resetMask); + snooze(100); + + // release reset + cmdReg = gPCI->read_pci_config(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, 0x44, 4); + gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, 0x44, 4, cmdReg & ~releaseMask); + snooze(100); +} + + +status_t +Device::Setup() +{ + cpu_status cp = 0; + uint32 channelsIndex = ChIndexMidEna | ChIndexEndEna; + + switch (HardwareId()) { + case SiS7018: + _ResetCard(0x000c0000, 0x00040000); + + cp = Lock(); + + WritePCI32(RegSiSCodecGPIO, 0x00000000); + WritePCI32(RegSiSCodecStatus, SiSCodecResetOff); + channelsIndex |= ChIndexSiSEnaB; + + Unlock(cp); + break; + + case ALi5451: + _ResetCard(0x000c0000, 0x00040000); + + cp = Lock(); + WritePCI32(RegALiDigiMixer, ALiDigiMixerPCMIn); + WritePCI32(RegALiVolumeA, 0); + Unlock(cp); + break; + + case TridentNX: + _ResetCard(0x00010000, 0x00010000); + + cp = Lock(); + WritePCI32(RegNXCodecStatus, NXCodecStatusDAC1ON); + Unlock(cp); + break; + + case TridentDX: + _ResetCard(0x00040000, 0x00040000); + + cp = Lock(); + WritePCI32(RegCodecStatus, CodecStatusDACON); + Unlock(cp); + break; + } + + // clear channels status + WritePCI32(RegStopA, 0xffffffff); + WritePCI32(RegStopB, 0xffffffff); + + // disable channels interrupt + WritePCI32(RegEnaINTA, 0x00000000); + WritePCI32(RegEnaINTB, 0x00000000); + + // enable loop interrupts + WritePCI32(RegChIndex, channelsIndex); + + fRecordStream.Init(); + fPlaybackStream.Init(); + + fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready"); + + fMixer.Init(); + + return B_OK; +} + + +status_t +Device::Open(uint32 flags) +{ + TRACE("flags:%x\n", flags); + + if (atomic_add(&fInterruptsNest, 1) == 0) { + install_io_interrupt_handler(fPCIInfo.u.h0.interrupt_line, + InterruptHandler, this, 0); + TRACE("Interrupt handler installed at line %d.\n", + fPCIInfo.u.h0.interrupt_line); + } + + status_t status = fRecordStream.Start(); + if (status != B_OK) { + ERROR("Error of starting record stream:%#010x\n", status); + } + + status = fPlaybackStream.Start(); + if (status != B_OK) { + ERROR("Error of starting playback stream:%#010x\n", status); + } + + + return B_OK; +} + + +status_t +Device::Close() +{ + TRACE("closed!\n"); + + status_t status = fPlaybackStream.Stop(); + if (status != B_OK) { + ERROR("Error of stopping playback stream:%#010x\n", status); + } + + status = fRecordStream.Stop(); + if (status != B_OK) { + ERROR("Error of stopping record stream:%#010x\n", status); + } + + if (atomic_add(&fInterruptsNest, -1) == 1) { + remove_io_interrupt_handler(fPCIInfo.u.h0.interrupt_line, + InterruptHandler, this); + TRACE("Interrupt handler at line %d uninstalled.\n", + fPCIInfo.u.h0.interrupt_line); + } + + return B_OK; +} + + +status_t +Device::Free() +{ + TRACE("freed\n"); + return B_OK; +} + + +status_t +Device::Read(uint8 *buffer, size_t *numBytes) +{ + *numBytes = 0; + return B_IO_ERROR; +} + + +status_t +Device::Write(const uint8 *buffer, size_t *numBytes) +{ + *numBytes = 0; + return B_IO_ERROR; +} + + +status_t +Device::Control(uint32 op, void *buffer, size_t length) +{ + switch (op) { + case B_MULTI_GET_DESCRIPTION: + return _MultiGetDescription((multi_description*)buffer); + + case B_MULTI_GET_EVENT_INFO: + TRACE(("B_MULTI_GET_EVENT_INFO\n")); + return B_ERROR; + + case B_MULTI_SET_EVENT_INFO: + TRACE(("B_MULTI_SET_EVENT_INFO\n")); + return B_ERROR; + + case B_MULTI_GET_EVENT: + TRACE(("B_MULTI_GET_EVENT\n")); + return B_ERROR; + + case B_MULTI_GET_ENABLED_CHANNELS: + return _MultiGetEnabledChannels((multi_channel_enable*)buffer); + + case B_MULTI_SET_ENABLED_CHANNELS: + return _MultiSetEnabledChannels((multi_channel_enable*)buffer); + + case B_MULTI_GET_GLOBAL_FORMAT: + return _MultiGetGlobalFormat((multi_format_info*)buffer); + + case B_MULTI_SET_GLOBAL_FORMAT: + return _MultiSetGlobalFormat((multi_format_info*)buffer); + + case B_MULTI_GET_CHANNEL_FORMATS: + TRACE(("B_MULTI_GET_CHANNEL_FORMATS\n")); + return B_ERROR; + + case B_MULTI_SET_CHANNEL_FORMATS: + TRACE(("B_MULTI_SET_CHANNEL_FORMATS\n")); + return B_ERROR; + + case B_MULTI_GET_MIX: + return _MultiGetMix((multi_mix_value_info *)buffer); + + case B_MULTI_SET_MIX: + return _MultiSetMix((multi_mix_value_info *)buffer); + + case B_MULTI_LIST_MIX_CHANNELS: + TRACE(("B_MULTI_LIST_MIX_CHANNELS\n")); + return B_ERROR; + + case B_MULTI_LIST_MIX_CONTROLS: + return _MultiListMixControls((multi_mix_control_info*)buffer); + + case B_MULTI_LIST_MIX_CONNECTIONS: + TRACE(("B_MULTI_LIST_MIX_CONNECTIONS\n")); + return B_ERROR; + + case B_MULTI_GET_BUFFERS: + return _MultiGetBuffers((multi_buffer_list*)buffer); + + case B_MULTI_SET_BUFFERS: + TRACE(("B_MULTI_SET_BUFFERS\n")); + return B_ERROR; + + case B_MULTI_SET_START_TIME: + TRACE(("B_MULTI_SET_START_TIME\n")); + return B_ERROR; + + case B_MULTI_BUFFER_EXCHANGE: + return _MultiBufferExchange((multi_buffer_info*)buffer); + + case B_MULTI_BUFFER_FORCE_STOP: + TRACE(("B_MULTI_BUFFER_FORCE_STOP\n")); + return B_ERROR; + + default: + ERROR("Unhandled IOCTL catched: %#010x\n", op); + } + + return B_DEV_INVALID_IOCTL; +} + + +status_t +Device::_MultiGetDescription(multi_description *multiDescription) +{ + multi_channel_info channel_descriptions[] = { + { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, + { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, + { 2, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, + { 3, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, + { 4, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, + B_CHANNEL_MINI_JACK_STEREO }, + { 5, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, + B_CHANNEL_MINI_JACK_STEREO }, + { 6, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, + B_CHANNEL_MINI_JACK_STEREO }, + { 7, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, + B_CHANNEL_MINI_JACK_STEREO }, + }; + + multi_description Description; + if (user_memcpy(&Description, + multiDescription, sizeof(multi_description)) != B_OK) + return B_BAD_ADDRESS; + + Description.interface_version = B_CURRENT_INTERFACE_VERSION; + Description.interface_minimum = B_CURRENT_INTERFACE_VERSION; + + strncpy(Description.friendly_name, fInfo.Name(), + sizeof(Description.friendly_name)); + + strncpy(Description.vendor_info, "Haiku.Inc.", + sizeof(Description.vendor_info)); + + Description.output_channel_count = 2; + Description.input_channel_count = 2; + Description.output_bus_channel_count = 2; + Description.input_bus_channel_count = 2; + Description.aux_bus_channel_count = 0; + + Description.output_rates = fMixer.OutputRates(); + Description.input_rates = fMixer.InputRates(); + + Description.output_formats = fMixer.OutputFormats(); + Description.input_formats = fMixer.InputFormats(); + + Description.min_cvsr_rate = 0; + Description.max_cvsr_rate = 0; + + Description.lock_sources = B_MULTI_LOCK_INTERNAL; + Description.timecode_sources = 0; + Description.interface_flags + = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; + Description.start_latency = 3000; + + Description.control_panel[0] = '\0'; + + if (user_memcpy(multiDescription, + &Description, sizeof(multi_description)) != B_OK) + return B_BAD_ADDRESS; + + if (Description.request_channel_count + >= (int)(_countof(channel_descriptions))) { + if (user_memcpy(multiDescription->channels, + &channel_descriptions, sizeof(channel_descriptions)) != B_OK) + return B_BAD_ADDRESS; + } + + return B_OK; +} + + +status_t +Device::_MultiGetEnabledChannels(multi_channel_enable *Enable) +{ + B_SET_CHANNEL(Enable->enable_bits, 0, true); + B_SET_CHANNEL(Enable->enable_bits, 1, true); + B_SET_CHANNEL(Enable->enable_bits, 2, true); + B_SET_CHANNEL(Enable->enable_bits, 3, true); + Enable->lock_source = B_MULTI_LOCK_INTERNAL; + return B_OK; +} + + +status_t +Device::_MultiSetEnabledChannels(multi_channel_enable *Enable) +{ + TRACE("0:%s\n", B_TEST_CHANNEL(Enable->enable_bits, 0) ? "en" : "dis"); + TRACE("1:%s\n", B_TEST_CHANNEL(Enable->enable_bits, 1) ? "en" : "dis"); + TRACE("2:%s\n", B_TEST_CHANNEL(Enable->enable_bits, 2) ? "en" : "dis"); + TRACE("3:%s\n", B_TEST_CHANNEL(Enable->enable_bits, 3) ? "en" : "dis"); + return B_OK; +} + + +status_t +Device::_MultiGetGlobalFormat(multi_format_info *Format) +{ + fPlaybackStream.GetFormat(Format); + fRecordStream.GetFormat(Format); + + return B_OK; +} + + +status_t +Device::_MultiSetGlobalFormat(multi_format_info *Format) +{ + status_t status = fPlaybackStream.SetFormat(Format->output, + fMixer.OutputFormats(), fMixer.OutputRates()); + if (status != B_OK) + return status; + + return fRecordStream.SetFormat(Format->input, + fMixer.InputFormats(), fMixer.InputRates()); +} + + +status_t +Device::_MultiListMixControls(multi_mix_control_info* Info) +{ + return fMixer.ListMixControls(Info); +} + + +status_t +Device::_MultiGetMix(multi_mix_value_info *Info) +{ + return fMixer.GetMix(Info); +} + + +status_t +Device::_MultiSetMix(multi_mix_value_info *Info) +{ + return fMixer.SetMix(Info); +} + + +status_t +Device::_MultiGetBuffers(multi_buffer_list* List) +{ + fPlaybackStream.GetBuffers(List->flags, List->return_playback_buffers, + List->return_playback_channels, List->return_playback_buffer_size, + List->playback_buffers); + + fRecordStream.GetBuffers(List->flags, List->return_record_buffers, + List->return_record_channels, List->return_record_buffer_size, + List->record_buffers); + return B_OK; +} + + +status_t +Device::_MultiBufferExchange(multi_buffer_info* bufferInfo) +{ + multi_buffer_info BufferInfo; + if (user_memcpy(&BufferInfo, bufferInfo, sizeof(multi_buffer_info)) != B_OK) { + return B_BAD_ADDRESS; + } + + status_t status = B_NO_INIT; + + if (!fRecordStream.IsActive()) { + status = fRecordStream.Start(); + if (status != B_OK) { + ERROR("Error of starting record stream:%#010x\n", status); + return status; + } + } + + if (!fPlaybackStream.IsActive()) { + status = fPlaybackStream.Start(); + if (status != B_OK) { + ERROR("Error of starting playback stream:%#010x\n", status); + return status; + } + } + + status = acquire_sem_etc(fBuffersReadySem, 1, + B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000); + if (status == B_TIMED_OUT) { + ERROR("Timeout during buffers exchange.\n"); + } + + cpu_status cst = Lock(); + + fRecordStream.ExchangeBuffers(BufferInfo.recorded_real_time, + BufferInfo.recorded_frames_count, BufferInfo.record_buffer_cycle); + + fPlaybackStream.ExchangeBuffers(BufferInfo.played_real_time, + BufferInfo.played_frames_count, BufferInfo.playback_buffer_cycle); + + Unlock(cst); + + if (user_memcpy(bufferInfo, &BufferInfo, sizeof(multi_buffer_info)) != B_OK) { + return B_BAD_ADDRESS; + } + + return B_OK; +} + + +int32 +Device::InterruptHandler(void *interruptParam) +{ + Device *device = reinterpret_cast(interruptParam); + if (device == 0) { + ERROR("Invalid parameter in the interrupt handler.\n"); + return B_HANDLED_INTERRUPT; + } + + bool wasHandled = false; + + acquire_spinlock(&device->fHWSpinlock); + + uint32 mask = device->ReadPCI32(RegMiscINT); + if (mask & 0x00000020) { + wasHandled = device->fRecordStream.InterruptHandler(); + wasHandled = device->fPlaybackStream.InterruptHandler() || wasHandled; + } + + release_spinlock(&device->fHWSpinlock); + + return wasHandled ? B_INVOKE_SCHEDULER : B_UNHANDLED_INTERRUPT; +} + + +void +Device::SignalReadyBuffers() +{ + release_sem_etc(fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE); +} + + +status_t +Device::_ReserveDeviceOnBus(bool reserve) +{ + status_t result = B_NO_INIT; + if (reserve) { + result = gPCI->reserve_device(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, DRIVER_NAME, this); + if (result != B_OK) + ERROR("Unable to reserve PCI device %d:%d:%d on bus:%#010x\n", + fPCIInfo.bus, fPCIInfo.device, fPCIInfo.function, result); + } else { + result = gPCI->unreserve_device(fPCIInfo.bus, fPCIInfo.device, + fPCIInfo.function, DRIVER_NAME, this); + } + + return result; +} + + +uint8 +Device::ReadPCI8(int offset) +{ + return gPCI->read_io_8(fIOBase + offset); +} + + +uint16 +Device::ReadPCI16(int offset) +{ + return gPCI->read_io_16(fIOBase + offset); +} + + +uint32 +Device::ReadPCI32(int offset) +{ + return gPCI->read_io_32(fIOBase + offset); +} + + +void +Device::WritePCI8(int offset, uint8 value) +{ + gPCI->write_io_8(fIOBase + offset, value); +} + + +void +Device::WritePCI16(int offset, uint16 value) +{ + gPCI->write_io_16(fIOBase + offset, value); +} + + +void +Device::WritePCI32(int offset, uint32 value) +{ + gPCI->write_io_32(fIOBase + offset, value); +} + + +cpu_status +Device::Lock() +{ + cpu_status st = disable_interrupts(); + acquire_spinlock(&fHWSpinlock); + return st; +} + + +void +Device::Unlock(cpu_status st) +{ + release_spinlock(&fHWSpinlock); + restore_interrupts(st); +} + + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.h new file mode 100644 index 0000000000..fd18e7bb03 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.h @@ -0,0 +1,99 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ +#ifndef _SiS7018_DEVICE_H_ +#define _SiS7018_DEVICE_H_ + + +#include + +#include "Driver.h" +#include "Mixer.h" +#include "Registers.h" +#include "Settings.h" +#include "Stream.h" + + +// card ids for supported audio hardware +const uint32 SiS7018 = 0x70181039; +const uint32 ALi5451 = 0x545110b9; +const uint32 TridentDX = 0x20001023; +const uint32 TridentNX = 0x20011023; + + +class Device { + +public: + class Info { + public: + const uint32 fId; + const char* fName; + inline const char* Name() { return fName; } + inline uint16 DeviceId() { return (fId >> 16) & 0xffff; } + inline uint16 VendorId() { return (fId) & 0xffff; } + inline uint32 Id() { return fId; } + }; + + uint32 HardwareId() { return fInfo.Id(); } + pci_info& PCIInfo() { return fPCIInfo; } + + + Device(Info &DeviceInfo, pci_info &PCIInfo); + ~Device(); + + status_t Setup(); + status_t InitCheck() { return fStatus; }; + + status_t Open(uint32 flags); + status_t Read(uint8 *buffer, size_t *numBytes); + status_t Write(const uint8 *buffer, size_t *numBytes); + status_t Control(uint32 op, void *buffer, size_t length); + status_t Close(); + status_t Free(); + +static int32 InterruptHandler(void *interruptParam); + void SignalReadyBuffers(); + + cpu_status Lock(); + void Unlock(cpu_status st); + + uint8 ReadPCI8(int offset); + uint16 ReadPCI16(int offset); + uint32 ReadPCI32(int offset); + void WritePCI8(int offset, uint8 value); + void WritePCI16(int offset, uint16 value); + void WritePCI32(int offset, uint32 value); + +private: + status_t _ReserveDeviceOnBus(bool reserve); + void _ResetCard(uint32 resetMask, uint32 releaseMask); + + status_t _MultiGetDescription(multi_description *Description); + status_t _MultiGetEnabledChannels(multi_channel_enable *Enable); + status_t _MultiSetEnabledChannels(multi_channel_enable *Enable); + status_t _MultiGetBuffers(multi_buffer_list* List); + status_t _MultiGetGlobalFormat(multi_format_info *Format); + status_t _MultiSetGlobalFormat(multi_format_info *Format); + status_t _MultiGetMix(multi_mix_value_info *Info); + status_t _MultiSetMix(multi_mix_value_info *Info); + status_t _MultiListMixControls(multi_mix_control_info* Info); + status_t _MultiBufferExchange(multi_buffer_info* Info); + + status_t fStatus; + pci_info fPCIInfo; + Info& fInfo; + int fIOBase; + int32 fHWSpinlock; + int32 fInterruptsNest; + sem_id fBuffersReadySem; + + Mixer fMixer; + Stream fPlaybackStream; + Stream fRecordStream; +}; + +#endif // _SiS7018_DEVICE_H_ + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.cpp new file mode 100644 index 0000000000..9d14d8bd87 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.cpp @@ -0,0 +1,227 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ + + +#include "Driver.h" + +#include +#include + +#include "Device.h" +#include "Settings.h" + + +int32 api_version = B_CUR_DRIVER_API_VERSION; + +size_t gNumCards = 0; +Device *gDevices[MAX_DEVICES] = { 0 }; +char *gDeviceNames[MAX_DEVICES + 1] = { 0 }; +pci_module_info *gPCI = NULL; + + +static Device::Info cardInfos[] = { + { SiS7018, "SiS 7018" }, + { ALi5451, "ALi M5451" }, + { TridentDX, "Trident DX" }, + { TridentNX, "Trident NX" } +}; + + +status_t +init_hardware() +{ + dprintf("sis7018:init_hardware:ver:%s\n", kVersion); + status_t result = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); + if (result < B_OK) { + return ENOSYS; + } + + pci_info info = {0}; + for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) { + for (size_t idx = 0; idx < _countof(cardInfos); idx++) { + if (info.vendor_id == cardInfos[idx].VendorId() && + info.device_id == cardInfos[idx].DeviceId()) + { + put_module(B_PCI_MODULE_NAME); + return B_OK; + } + } + } + + put_module(B_PCI_MODULE_NAME); + return ENODEV; +} + + +status_t +init_driver() +{ + status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); + if (status < B_OK) { + return ENOSYS; + } + + load_settings(); + + pci_info info = { 0 }; + for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) { + for (size_t idx = 0; idx < _countof(cardInfos); idx++) { + if (info.vendor_id == cardInfos[idx].VendorId() && + info.device_id == cardInfos[idx].DeviceId()) + { + if (gNumCards == MAX_DEVICES) { + ERROR("Skipped:%s [%#06x:%#06x]\n", cardInfos[idx].Name(), + cardInfos[idx].VendorId(), cardInfos[idx].DeviceId()); + break; + } + + Device* device = new Device(cardInfos[idx], info); + if (device == 0) { + return ENODEV; + } + + status_t status = device->InitCheck(); + if (status < B_OK) { + delete device; + break; + } + + status = device->Setup(); + if (status < B_OK) { + delete device; + break; + } + + char name[32] = {0}; + sprintf(name, "audio/hmulti/%s/%ld", + cardInfos[idx].Name(), gNumCards); + gDeviceNames[gNumCards] = strdup(name); + gDevices[gNumCards++] = device; + + TRACE("Found:%s [%#06x:%#06x]\n", cardInfos[idx].Name(), + cardInfos[idx].VendorId(), cardInfos[idx].DeviceId()); + } + } + } + + if (gNumCards == 0) { + put_module(B_PCI_MODULE_NAME); + return ENODEV; + } + + return B_OK; +} + + +void +uninit_driver() +{ + for (size_t i = 0; i < MAX_DEVICES; i++) { + if (gDevices[i]) { + delete gDevices[i]; + gDevices[i] = NULL; + } + + free(gDeviceNames[i]); + gDeviceNames[i] = NULL; + } + + put_module(B_PCI_MODULE_NAME); + + release_settings(); +} + + +static status_t +SiS7018_open(const char *name, uint32 flags, void **cookie) +{ + status_t status = ENODEV; + *cookie = NULL; + for (size_t i = 0; i < MAX_DEVICES; i++) { + if (gDeviceNames[i] && !strcmp(gDeviceNames[i], name)) { + status = gDevices[i]->Open(flags); + *cookie = gDevices[i]; + } + } + + return status; +} + + +static status_t +SiS7018_read(void *cookie, off_t position, void *buffer, size_t *numBytes) +{ + Device *device = (Device *)cookie; + return device->Read((uint8 *)buffer, numBytes); +} + + +static status_t +SiS7018_write(void *cookie, off_t position, + const void *buffer, size_t *numBytes) +{ + Device *device = (Device *)cookie; + return device->Write((const uint8 *)buffer, numBytes); +} + + +static status_t +SiS7018_control(void *cookie, uint32 op, void *buffer, size_t length) +{ + Device *device = (Device *)cookie; + return device->Control(op, buffer, length); +} + + +static status_t +SiS7018_close(void *cookie) +{ + Device *device = (Device *)cookie; + return device->Close(); +} + + +static status_t +SiS7018_free(void *cookie) +{ + Device *device = (Device *)cookie; + return device->Free(); +} + + +const char ** +publish_devices() +{ + for (size_t i = 0; i < MAX_DEVICES; i++) { + if (gDevices[i] == NULL) + continue; + + if (gDeviceNames[i]) + TRACE("%s\n", gDeviceNames[i]); + } + + return (const char **)&gDeviceNames[0]; +} + + +device_hooks * +find_device(const char *name) +{ + static device_hooks deviceHooks = { + SiS7018_open, + SiS7018_close, + SiS7018_free, + SiS7018_control, + SiS7018_read, + SiS7018_write, + NULL, // select + NULL // deselect + }; + + return &deviceHooks; +} + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.h new file mode 100644 index 0000000000..1f4e9a16dd --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.h @@ -0,0 +1,35 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ +#ifndef _SiS7018_DRIVER_H_ +#define _SiS7018_DRIVER_H_ + + +#include +#include + + +#define DRIVER_NAME "sis7018" +#define MAX_DEVICES 3 + + +const char* const kVersion = "ver.2.0.0"; + +extern pci_module_info *gPCI; + +extern "C" { + +status_t init_hardware(); +status_t init_driver(); +void uninit_driver(); +const char** publish_devices(); +device_hooks* find_device(const char* name); + +} + + +#endif // _SiS7018_DRIVER_H_ + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Jamfile b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Jamfile new file mode 100644 index 0000000000..07ec2404b3 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Jamfile @@ -0,0 +1,18 @@ +SubDir HAIKU_TOP src add-ons kernel drivers audio ac97 sis7018 ; + + +UsePrivateHeaders kernel media ; + +UsePrivateHeaders [ FDirName kernel util ] ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) ] ; + +KernelAddon sis7018 : + Driver.cpp + Device.cpp + Mixer.cpp + Settings.cpp + Stream.cpp + ac97.c + ; diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.cpp new file mode 100644 index 0000000000..19566af5c2 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.cpp @@ -0,0 +1,685 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + * Copyright for ali5451 support: + * (c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). + */ + + +#include "Mixer.h" + +#include + +#include "Device.h" +#include "Registers.h" +#include "Settings.h" + + +Mixer::Mixer(Device *device) + : + fDevice(device), + fAC97Dev(NULL), + fReadPort(RegCodecRead), + fWritePort(RegCodecWrite), + fMaskRW(1 << 15), + fMaskRD(1 << 15), + fMaskWD(1 << 15), + fInputRates(0), + fOutputRates(0), + fInputFormats(0), + fOutputFormats(0) +{ + switch (device->HardwareId()) { + case ALi5451: + if (fDevice->PCIInfo().revision > 0x01) { + fReadPort = RegCodecWrite; + fMaskWD = 1 << 8; + } + case SiS7018: + break; + case TridentDX: + break; + case TridentNX: + fReadPort = RegNXCodecRead; + fWritePort = RegNXCodecWrite; + fMaskRW = 1 << 11; + fMaskRD = 1 << 10; + fMaskWD = 1 << 11; + break; + } + + TRACE("Regs:R:%#x;W:%#x;MRW:%#x;MRD:%#x;MWD:%#x\n", + fReadPort, fWritePort, fMaskRW, fMaskRD, fMaskWD); +} + + +void +Mixer::Init() +{ + ac97_attach(&fAC97Dev, _ReadAC97, _WriteAC97, this, + fDevice->PCIInfo().u.h0.subsystem_vendor_id, + fDevice->PCIInfo().u.h0.subsystem_id); + + _ReadSupportedFormats(); +} + + +void +Mixer::_ReadSupportedFormats() +{ + struct _Cap { + ac97_capability fCap; + uint32 fRate; + } caps[] = { + { CAP_PCM_RATE_8000, B_SR_8000 }, + { CAP_PCM_RATE_11025, B_SR_11025 }, + { CAP_PCM_RATE_12000, B_SR_12000 }, + { CAP_PCM_RATE_16000, B_SR_16000 }, + { CAP_PCM_RATE_22050, B_SR_22050 }, + { CAP_PCM_RATE_24000, B_SR_24000 }, + { CAP_PCM_RATE_32000, B_SR_32000 }, + { CAP_PCM_RATE_44100, B_SR_44100 }, + { CAP_PCM_RATE_48000, B_SR_48000 } + }; + + for (size_t i = 0; i < _countof(caps); i++) { + if (ac97_has_capability(fAC97Dev, caps[i].fCap)) + fOutputRates |= caps[i].fRate; + } + + fInputRates = B_SR_48000; + fInputFormats = B_FMT_16BIT; + fOutputFormats = B_FMT_16BIT; +} + + +void +Mixer::Free() +{ + ac97_detach(fAC97Dev); +} + + +uint16 +Mixer::_ReadAC97(void* cookie, uint8 reg) +{ + return reinterpret_cast(cookie)->_ReadAC97(reg); +} + + +void +Mixer::_WriteAC97(void* cookie, uint8 reg, uint16 data) +{ + return reinterpret_cast(cookie)->_WriteAC97(reg, data); +} + + +bool +Mixer::_WaitPortReady(uint8 reg, uint32 mask, uint32* result) +{ + int count = 200; + uint32 data = 0; + + while (count--) { + data = fDevice->ReadPCI32(reg); + if ((data & mask) == 0) { + if (result != NULL) + *result = data; + return true; + } + spin(1); + } + + ERROR("AC97 register %#04x is not ready.\n", reg); + return false; +} + + +bool +Mixer::_WaitSTimerReady() +{ + if (fDevice->HardwareId() != ALi5451) + return true; + + int count = 200; + uint32 time1 = fDevice->ReadPCI32(RegALiSTimer); + + while (count--) { + uint32 time2 = fDevice->ReadPCI32(RegALiSTimer); + if (time2 != time1) + return true; + spin(1); + } + + ERROR("AC97 STimer is not ready.\n"); + return false; +} + + +uint16 +Mixer::_ReadAC97(uint8 reg) +{ + uint32 result = 0; + + cpu_status cp = fDevice->Lock(); + + if (_WaitPortReady(fWritePort, fMaskRD) + && _WaitPortReady(fReadPort, fMaskRD) && _WaitSTimerReady()) { + + fDevice->WritePCI32(fReadPort, (reg & 0x7f) | fMaskRW); + + if (_WaitSTimerReady() && _WaitPortReady(fReadPort, fMaskRD, &result)) + result = (result >> 16) & 0xffff; + } + + fDevice->Unlock(cp); + + return result; +} + + +void +Mixer::_WriteAC97(uint8 reg, uint16 data) +{ + cpu_status cp = fDevice->Lock(); + + if (_WaitPortReady(fWritePort, fMaskRW) && _WaitSTimerReady()) { + + fDevice->WritePCI32(fWritePort, + (data << 16) | (reg & 0x7f) | fMaskRW | fMaskWD); + } + + fDevice->Unlock(cp); +} + + +// Control ids are encoded in the following way: +// GGBBRRTT -- +// GG - in gain controls: 10th of granularity. Signed! +// - in MUX controls: value of selector. +// BB - in gain controls: base level - correspond to 0 db. +// - mute, boost, enable controls: offset of "on/off" bit +// RR - AC97 Register handled by this control +// TT - MIXControlTypes bits + +const int stepShift = 24; // offset to GG +const int baseShift = 16; // offset to BB +const int regShift = 8; // offset to RR + +enum MIXControlTypes { + MIX_RGain = 0x01, + MIX_LGain = 0x10, + MIX_Mono = MIX_RGain, + MIX_Stereo = MIX_LGain | MIX_RGain, + MIX_Mute = 0x04, + MIX_Boost = 0x08, + MIX_MUX = 0x20, + MIX_Enable = 0x40, + MIX_Check = MIX_Mute | MIX_Boost | MIX_Enable +}; + + +struct GainInfo { + uint8 fOff; // offset of mask in register word + uint8 fBase; // base - default value of register + uint8 fMask; // mask - maximal value of register + float fMult; // multiplier - bits to dB recalculate + uint8 fEnaOff; // offset of "on/off" bit in register word +}; + + +GainInfo MixGain = { 0x00, 0x00, 0x3f, -1.5, 0x0f }; +GainInfo InGain = { 0x00, 0x08, 0x1f, -1.5, 0x0f }; +GainInfo RecGain = { 0x00, 0x00, 0x0f, 1.5, 0x0f }; +GainInfo BeepGain = { 0x01, 0x00, 0x1e, 3.0, 0x0f }; +GainInfo ToneGain = { 0x00, 0x07, 0x0f, -1.5, 0x10 }; // 0x10 - mean no "mute" +GainInfo D3DGain = { 0x00, 0x00, 0x0f, 1.0, 0x10 }; + + +struct MIXControlInfo { + uint8 fAC97Reg; + GainInfo* fInfo; + strind_id fNameId; + uint16 fType; +const char* fName; + + uint8 fExAC97Reg; + strind_id fExNameId; +const char* fExName; + uint8 fExOff; +}; + + +MIXControlInfo OutputControls[] = { + { AC97_MASTER_VOLUME, &MixGain, S_MASTER, + MIX_Stereo | MIX_Mute, NULL }, + { AC97_AUX_OUT_VOLUME, &MixGain, S_AUX, + MIX_Stereo | MIX_Mute, NULL }, + { AC97_MASTER_TONE, &ToneGain, S_OUTPUT_BASS, + MIX_LGain, NULL }, + { AC97_MASTER_TONE, &ToneGain, S_OUTPUT_TREBLE, + MIX_RGain, NULL }, + { AC97_3D_CONTROL, &D3DGain, S_OUTPUT_3D_DEPTH, + MIX_RGain | MIX_Enable, NULL, + AC97_GENERAL_PURPOSE, S_ENABLE, NULL, 0x0d }, + { AC97_3D_CONTROL, &D3DGain, S_OUTPUT_3D_CENTER, + MIX_LGain, NULL }, + { AC97_MONO_VOLUME, &MixGain, S_MONO_MIX, + MIX_Mono | MIX_Mute, NULL }, + { AC97_PC_BEEP_VOLUME, &BeepGain, S_BEEP, + MIX_Mono | MIX_Mute, NULL } +}; + + +MIXControlInfo InputControls[] = { + { AC97_PCM_OUT_VOLUME, &InGain, S_WAVE, + MIX_Stereo | MIX_Mute, NULL }, + { AC97_MIC_VOLUME, &InGain, S_MIC, + MIX_Mono | MIX_Mute | MIX_Boost, NULL, + AC97_MIC_VOLUME, S_null, "+ 20 dB", 0x06 }, + { AC97_LINE_IN_VOLUME, &InGain, S_LINE, + MIX_Stereo | MIX_Mute, NULL }, + { AC97_CD_VOLUME, &InGain, S_CD, + MIX_Stereo | MIX_Mute, NULL }, + { AC97_VIDEO_VOLUME, &InGain, S_VIDEO, + MIX_Stereo | MIX_Mute, NULL }, + { AC97_AUX_IN_VOLUME, &InGain, S_AUX, + MIX_Stereo | MIX_Mute, NULL }, + { AC97_PHONE_VOLUME, &InGain, S_PHONE, + MIX_Mono | MIX_Mute, NULL } +}; + + +strind_id RecordSources[] = { + S_MIC, + S_CD, + S_VIDEO, + S_AUX, + S_LINE, + S_STEREO_MIX, + S_MONO_MIX, + S_PHONE +}; + + +MIXControlInfo RecordControls[] = { + { AC97_RECORD_GAIN, &RecGain, S_null, + MIX_Stereo | MIX_Mute | MIX_MUX, "Record Gain", + AC97_RECORD_SELECT, S_null, "Source" }, + { AC97_RECORD_GAIN_MIC, &RecGain, S_MIC, + MIX_Mono | MIX_Mute, NULL } +}; + + +void +Mixer::_InitGainLimits(multi_mix_control& Control, GainInfo& Info) +{ + float base = Info.fBase >> Info.fOff; + float max = Info.fMask >> Info.fOff; + + float min_gain = Info.fMult * (0.0 - base); + float max_gain = Info.fMult * (max - base); + + Control.gain.min_gain = (Info.fMult > 0) ? min_gain : max_gain; + Control.gain.max_gain = (Info.fMult > 0) ? max_gain : min_gain; + Control.gain.granularity = Info.fMult; + + // encode gain granularity in the MSB of the control id. + uint8 gran = (uint8)(Info.fMult * 10.); + Control.id |= (gran << stepShift); + Control.id |= (Info.fBase << baseShift); + + TRACE("base:%#04x; mask:%#04x; mult:%f\n", + Info.fBase, Info.fMask, Info.fMult); + TRACE(" min:%f; max:%f; gran:%f -> %#010x\n", + Control.gain.min_gain, Control.gain.max_gain, + Control.gain.granularity, Control.id); +} + + +bool +Mixer::_CheckRegFeatures(uint8 AC97Reg, uint16& mask, uint16& result) +{ + uint16 backup = ac97_reg_cached_read(fAC97Dev, AC97Reg); + + ac97_reg_cached_write(fAC97Dev, AC97Reg, mask); + result = ac97_reg_cached_read(fAC97Dev, AC97Reg); + TRACE("Check for register %#02x: %#x -> %#x.\n", AC97Reg, mask, result); + + ac97_reg_cached_write(fAC97Dev, AC97Reg, backup); + + return mask != result; +} + + +bool +Mixer::_CorrectMIXControlInfo(MIXControlInfo& Info, GainInfo& gainInfo) +{ + uint16 newMask = gainInfo.fMask; + uint16 testMask = 0; + uint16 testResult = 0; + + switch (Info.fAC97Reg) { + case AC97_AUX_OUT_VOLUME: + if (ac97_has_capability(fAC97Dev, CAP_HEADPHONE_OUT)) { + Info.fNameId = S_HEADPHONE; + Info.fName = NULL; + } + case AC97_MASTER_VOLUME: + testMask = 0x2020; + newMask = 0x1f; + break; + case AC97_MASTER_TONE: + if (!ac97_has_capability(fAC97Dev, CAP_BASS_TREBLE_CTRL)) + return false; + testMask = 0x0f0f; + break; + case AC97_3D_CONTROL: + if (!ac97_has_capability(fAC97Dev, CAP_3D_ENHANCEMENT)) + return false; + testMask = 0x0f0f; + break; + case AC97_RECORD_GAIN_MIC: + if (!ac97_has_capability(fAC97Dev, CAP_PCM_MIC)) + return false; + testMask = 0x0f; + break; + case AC97_MONO_VOLUME: + testMask = 0x20; + newMask = 0x1f; + break; + case AC97_PC_BEEP_VOLUME: + testMask = 0x1e; + break; + case AC97_VIDEO_VOLUME: + case AC97_AUX_IN_VOLUME: + case AC97_PHONE_VOLUME: + testMask = 0x1f; + break; + default: + return true; + } + + if (_CheckRegFeatures(Info.fAC97Reg, testMask, testResult)) { + if (testResult == 0) + return false; + + gainInfo.fMask = newMask; + } + + return true; +} + + +int32 +Mixer::_CreateMIXControlGroup(multi_mix_control_info* MultiInfo, int32& index, + int32 parentIndex, MIXControlInfo& Info) +{ + // check the optional registers and features, + // correct the range if required and do not add if not supported + GainInfo gainInfo = *Info.fInfo; + if (!_CorrectMIXControlInfo(Info, gainInfo)) + return 0; + + int32 IdReg = Info.fAC97Reg << regShift; + multi_mix_control* Controls = MultiInfo->controls; + + int32 groupIndex + = Controls[index].id = IdReg | Info.fType; + Controls[index].flags = B_MULTI_MIX_GROUP; + Controls[index].parent = parentIndex; + Controls[index].string = Info.fNameId; + if (Info.fName != NULL) + strncpy(Controls[index].name, Info.fName, sizeof(Controls[index].name)); + index++; + + if (Info.fType & MIX_Mute) { + Controls[index].id = IdReg | MIX_Check; + Controls[index].id |= Info.fInfo->fEnaOff << baseShift; + Controls[index].flags = B_MULTI_MIX_ENABLE; + Controls[index].parent = groupIndex; + Controls[index].string = S_MUTE; + + TRACE("Mute:%#010x\n", Controls[index].id); + index++; + } + + if (Info.fType & MIX_Enable) { + int32 IdExReg = Info.fExAC97Reg << regShift; + Controls[index].id = IdExReg | MIX_Check; + Controls[index].id |= (Info.fExOff << baseShift); + Controls[index].flags = B_MULTI_MIX_ENABLE; + Controls[index].parent = groupIndex; + Controls[index].string = Info.fExNameId; + if (Info.fExName != NULL) + strncpy(Controls[index].name, Info.fExName, + sizeof(Controls[index].name)); + + TRACE("Enable:%#010x\n", Controls[index].id); + index++; + } + + int32 gainIndex = 0; + if (Info.fType & MIX_LGain) { + Controls[index].id = IdReg | MIX_LGain; + Controls[index].flags = B_MULTI_MIX_GAIN; + Controls[index].parent = groupIndex; + Controls[index].string = S_GAIN; + _InitGainLimits(Controls[index], gainInfo); + gainIndex = Controls[index].id; + index++; + } + + if (Info.fType & MIX_RGain) { + Controls[index].id = IdReg | MIX_RGain; + Controls[index].flags = B_MULTI_MIX_GAIN; + Controls[index].parent = groupIndex; + Controls[index].master = gainIndex; + Controls[index].string = S_GAIN; + _InitGainLimits(Controls[index], gainInfo); + index++; + } + + if (Info.fType & MIX_Boost) { + Controls[index].id = IdReg | MIX_Check; + Controls[index].id |= (Info.fExOff << baseShift); + Controls[index].flags = B_MULTI_MIX_ENABLE; + Controls[index].parent = groupIndex; + Controls[index].string = Info.fExNameId; + if (Info.fExName != NULL) + strncpy(Controls[index].name, Info.fExName, + sizeof(Controls[index].name)); + + TRACE("Boost:%#010x\n", Controls[index].id); + index++; + } + + if (Info.fType & MIX_MUX) { + int32 IdMUXReg = Info.fExAC97Reg << regShift; + int32 recordMUX + = Controls[index].id = IdMUXReg | MIX_MUX; + Controls[index].flags = B_MULTI_MIX_MUX; + Controls[index].parent = groupIndex; + Controls[index].string = S_null; + strncpy(Controls[index].name, Info.fExName, sizeof(Controls[index].name)); + + TRACE("MUX:%#010x\n", Controls[index].id); + index++; + + for (size_t i = 0; i < _countof(RecordSources); i++) { + Controls[index].id = IdMUXReg | (i << stepShift) | MIX_MUX; + Controls[index].flags = B_MULTI_MIX_MUX_VALUE; + Controls[index].master = 0; + Controls[index].string = RecordSources[i]; + Controls[index].parent = recordMUX; + + TRACE("MUX Item:%#010x\n", Controls[index].id); + + index++; + } + } + + return groupIndex; +} + + +status_t +Mixer::ListMixControls(multi_mix_control_info* Info) +{ + int32 index = 0; + multi_mix_control* Controls = Info->controls; + int32 mixerGroup + = Controls[index].id = 0x8000; // 0x80 - is not a valid AC97 register + Controls[index].flags = B_MULTI_MIX_GROUP; + Controls[index].parent = 0; + Controls[index].string = S_OUTPUT; + index++; + + for (size_t i = 0; i < _countof(OutputControls); i++) { + _CreateMIXControlGroup(Info, index, mixerGroup, OutputControls[i]); + } + + int32 inputGroup + = Controls[index].id = 0x8100; + Controls[index].flags = B_MULTI_MIX_GROUP; + Controls[index].parent = 0; + Controls[index].string = S_INPUT; + index++; + + for (size_t i = 0; i < _countof(InputControls); i++) { + _CreateMIXControlGroup(Info, index, inputGroup, InputControls[i]); + } + + int32 recordGroup + = Controls[index].id = 0x8200; + Controls[index].flags = B_MULTI_MIX_GROUP; + Controls[index].parent = 0; + Controls[index].string = S_null; + strncpy(Controls[index].name, "Record", sizeof(Controls[index].name)); + index++; + + for (size_t i = 0; i < _countof(RecordControls); i++) { + _CreateMIXControlGroup(Info, index, recordGroup, RecordControls[i]); + } + + return B_OK; +} + + +status_t +Mixer::GetMix(multi_mix_value_info *Info) +{ + for (int32 i = 0; i < Info->item_count; i++) { + + int32 Id= Info->values[i].id; + uint8 Reg = (Id >> regShift) & 0xFF; + + if ((Reg & 0x01) || Reg > 0x7e) { + ERROR("Invalid AC97 register:%#04x.Bypass it.\n", Reg); + continue; + } + + uint16 RegValue = ac97_reg_cached_read(fAC97Dev, Reg); + + if ((Id & MIX_Check) == MIX_Check) { + uint16 mask = 1 << ((Id >> baseShift) & 0xff); + Info->values[i].enable = (RegValue & mask) == mask; + TRACE("%#04x Mute|Enable|Boost:%d [data:%#04x]\n", + Reg, Info->values[i].enable, RegValue); + continue; + } + + if ((Id & MIX_MUX) == MIX_MUX) { + Info->values[i].mux = (RegValue | (RegValue >> 8)) & 0x7; + TRACE("%#04x MUX:%d [data:%#04x]\n", + Reg, Info->values[i].mux, RegValue); + continue; + } + + float mult = 0.1 * (int8)(Id >> stepShift); + float base = mult * ((Id >> baseShift) & 0xff); + + if ((Id & MIX_RGain) == MIX_RGain) { + uint8 gain = RegValue & 0x3f; + Info->values[i].gain = mult * gain - base; + TRACE("%#04x for RGain:%f [mult:%f base:%f] <- %#04x\n", + Reg, Info->values[i].gain, mult, base, gain); + continue; + } + + if ((Id & MIX_LGain) == MIX_LGain) { + uint8 gain = (RegValue >> 8) & 0x3f; + Info->values[i].gain = mult * gain - base; + TRACE("%#04x for LGain:%f [mult:%f base:%f] <- %#04x\n", + Reg, Info->values[i].gain, mult, base, gain); + } + } + + return B_OK; +} + + +status_t +Mixer::SetMix(multi_mix_value_info *Info) +{ + for (int32 i = 0; i < Info->item_count; i++) { + + int32 Id = Info->values[i].id; + uint8 Reg = (Id >> regShift) & 0xFF; + + if ((Reg & 0x01) || Reg > 0x7e) { + ERROR("Invalid AC97 register:%#04x.Bypass it.\n", Reg); + continue; + } + + uint16 RegValue = ac97_reg_cached_read(fAC97Dev, Reg); + + if ((Id & MIX_Check) == MIX_Check) { + uint16 mask = 1 << ((Id >> baseShift) & 0xff); + if (Info->values[i].enable) + RegValue |= mask; + else + RegValue &= ~mask; + TRACE("%#04x Mute/Enable:%d -> data:%#04x\n", + Reg, Info->values[i].enable, RegValue); + } + + if ((Id & MIX_MUX) == MIX_MUX) { + uint8 mux = Info->values[i].mux & 0x7; + RegValue = mux | (mux << 8); + TRACE("%#04x MUX:%d -> data:%#04x\n", + Reg, Info->values[i].mux, RegValue); + } + + float mult = 0.1 * (int8)(Id >> stepShift); + float base = mult * ((Id >> baseShift) & 0xff); + + float gain = (Info->values[i].gain + base) / mult; + gain += (gain > 0.) ? 0.5 : -0.5; + uint8 gainValue = (uint8)gain; + + if ((Id & MIX_RGain) == MIX_RGain) { + RegValue &= 0xffc0; + RegValue |= gainValue; + + TRACE("%#04x for RGain:%f [mult:%f base:%f] -> %#04x\n", + Reg, Info->values[i].gain, mult, base, gainValue); + } + + if ((Id & MIX_LGain) == MIX_LGain) { + RegValue &= 0xc0ff; + RegValue |= (gainValue << 8); + TRACE("%#04x for LGain:%f [mult:%f base:%f] -> %#04x\n", + Reg, Info->values[i].gain, mult, base, gainValue); + } + + TRACE("%#04x Write:%#06x\n", Reg, RegValue); + + ac97_reg_cached_write(fAC97Dev, Reg, RegValue); + } + + return B_OK; +} + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.h new file mode 100644 index 0000000000..559a0b689f --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.h @@ -0,0 +1,68 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ +#ifndef _SiS7018_MIXER_H_ +#define _SiS7018_MIXER_H_ + + +#include + +#include "ac97.h" +#include "hmulti_audio.h" + + +class Device; +struct GainInfo; +struct MIXControlInfo; + +class Mixer { + +public: + Mixer(Device *cdc); + + void Init(); + void Free(); + + status_t GetMix(multi_mix_value_info *Info); + status_t SetMix(multi_mix_value_info *Info); + status_t ListMixControls(multi_mix_control_info* Info); + + uint32 InputRates() { return fInputRates; } + uint32 OutputRates() { return fOutputRates; } + uint32 InputFormats() { return fInputFormats; } + uint32 OutputFormats() { return fOutputFormats; } + +private: + void _ReadSupportedFormats(); + bool _WaitPortReady(uint8 reg, uint32 mask, uint32* result = NULL); + bool _WaitSTimerReady(); + uint16 _ReadAC97(uint8 reg); + void _WriteAC97(uint8 reg, uint16 date); +static uint16 _ReadAC97(void* cookie, uint8 reg); +static void _WriteAC97(void* cookie, uint8 reg, uint16 data); + bool _CheckRegFeatures(uint8 AC97Reg, uint16& mask, uint16& result); + bool _CorrectMIXControlInfo(MIXControlInfo& info, GainInfo& gainInfo); + void _InitGainLimits(multi_mix_control& Control, GainInfo& Info); + int32 _CreateMIXControlGroup(multi_mix_control_info* MultiInfo, + int32& index, int32 parentIndex, MIXControlInfo& Info); + + Device* fDevice; + ac97_dev* fAC97Dev; + uint8 fReadPort; + uint8 fWritePort; + uint32 fMaskRW; + uint32 fMaskRD; + uint32 fMaskWD; + + uint32 fInputRates; + uint32 fOutputRates; + uint32 fInputFormats; + uint32 fOutputFormats; +}; + + +#endif // _SiS7018_MIXER_H_ + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Registers.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Registers.h new file mode 100644 index 0000000000..bb86e87fca --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Registers.h @@ -0,0 +1,82 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + * Copyright for ali5451 support: + * (c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). + */ +#ifndef _SiS7018_REGISTERS_H_ +#define _SiS7018_REGISTERS_H_ + + +enum Registers { + // shared registers + RegCodecWrite = 0x40, + RegCodecRead = 0x44, + RegCodecStatus = 0x48, + CodecStatusSBCtrl = 0x40, + CodecStatusActive = 0x20, + CodecStatusReady = 0x10, + CodecStatusADCON = 0x08, + CodecStatusDACON = 0x02, + CodecStatusReset = 0x01, + CodecTimeout = 0xffff, + + RegRecChannel = 0x70, + RegStartA = 0x80, + RegStopA = 0x84, + RegCurSPFA = 0x90, + RegAddrINTA = 0x98, + RegChIndex = 0xa0, + ChIndexMask = 0x0000003f, + ChIndexEndEna = 0x00001000, + ChIndexMidEna = 0x00002000, + RegEnaINTA = 0xa4, + RegMiscINT = 0xb0, + RegStartB = 0xb4, + RegStopB = 0xb8, + RegCurSPFB = 0xbc, + RegAddrINTB = 0xd8, + RegEnaINTB = 0xdc, + RegCSOAlphaFMS = 0xe0, + RegLBA_PPTR = 0xe4, + RegDeltaESO = 0xe8, + RegRVolCVolFMC = 0xec, + RegGVSelVolCtrl = 0xf0, + RegEBuf1 = 0xf4, + RegEBuf2 = 0xf8, + + + // SiS7018 specific registers + RegSiSCodecWrite = RegCodecWrite, + RegSiSCodecRead = RegCodecRead, + RegSiSCodecStatus = RegCodecStatus, + SiSCodecResetOff = 0x000f0000, + RegSiSCodecGPIO = 0x4c, + ChIndexSiSEnaB = 0x00010000, + + // ALi5451 registers + RegALiVolumeA = 0xa8, + RegALiMPUR2 = 0x22, + RegALiSTimer = 0xc8, + RegALiDigiMixer = 0xd4, + ALiDigiMixerPCMIn = 0x80000000, + + // Trident NX specific registers + RegNXCodecStatus = 0x40, + NXCodecStatusReady2 = 0x40, + NXCodecStatusADC2ON = 0x20, + NXCodecStatusDAC2ON = 0x10, + NXCodecStatusReady1 = 0x08, + NXCodecStatusADC1ON = 0x04, + NXCodecStatusDAC1ON = 0x02, + NXCodecStatusReset = 0x01, + RegNXCodecWrite = 0x44, + RegNXCodecRead = 0x48, + RegNXCodecRead2 = 0x4c +}; + + +#endif // _SIS7018_REGISTERS_H_ + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Settings.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Settings.cpp new file mode 100644 index 0000000000..ef02f6b996 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Settings.cpp @@ -0,0 +1,113 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ + + +#include "Settings.h" + +#include +#include +#include +#include + + +bool gTraceOn = false; +bool gTruncateLogFile = false; +bool gAddTimeStamp = true; +static char *gLogFilePath = NULL; +mutex gLogLock; + + +static +void create_log() +{ + if (gLogFilePath == NULL) + return; + + int flags = O_WRONLY | O_CREAT | ((gTruncateLogFile) ? O_TRUNC : 0); + close(open(gLogFilePath, flags, 0666)); + + mutex_init(&gLogLock, DRIVER_NAME"-logging"); +} + + +void load_settings() +{ + void *handle = load_driver_settings(DRIVER_NAME); + if (handle == 0) + return; + + gTraceOn = get_driver_boolean_parameter(handle, "trace", gTraceOn, true); + gTruncateLogFile = get_driver_boolean_parameter(handle, "truncate_logfile", + gTruncateLogFile, true); + gAddTimeStamp = get_driver_boolean_parameter(handle, "add_timestamp", + gAddTimeStamp, true); + const char * logFilePath = get_driver_parameter(handle, "logfile", + NULL, "/var/log/"DRIVER_NAME".log"); + if (logFilePath != NULL) { + gLogFilePath = strdup(logFilePath); + } + + unload_driver_settings(handle); + + create_log(); +} + + +void release_settings() +{ + if (gLogFilePath != NULL) { + mutex_destroy(&gLogLock); + free(gLogFilePath); + } +} + + +void SiS7018_trace(bool force, const char* func, const char *fmt, ...) +{ + if (!(force || gTraceOn)) { + return; + } + + va_list arg_list; + static const char *prefix = DRIVER_NAME":"; + static char buffer[1024]; + char *buf_ptr = buffer; + if (gLogFilePath == NULL) { + strcpy(buffer, prefix); + buf_ptr += strlen(prefix); + } + + if (gAddTimeStamp) { + bigtime_t time = system_time(); + uint32 msec = time / 1000; + uint32 sec = msec / 1000; + sprintf(buf_ptr, "%02ld.%02ld.%03ld:", + sec / 60, sec % 60, msec % 1000); + buf_ptr += strlen(buf_ptr); + } + + if (func != NULL) { + sprintf(buf_ptr, "%s::", func); + buf_ptr += strlen(buf_ptr); + } + + va_start(arg_list, fmt); + vsprintf(buf_ptr, fmt, arg_list); + va_end(arg_list); + + if (gLogFilePath == NULL) { + dprintf(buffer); + return; + } + + mutex_lock(&gLogLock); + int fd = open(gLogFilePath, O_WRONLY | O_APPEND); + write(fd, buffer, strlen(buffer)); + close(fd); + mutex_unlock(&gLogLock); +} + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Settings.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Settings.h new file mode 100644 index 0000000000..4a9daa5649 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Settings.h @@ -0,0 +1,40 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ +#ifndef _SiS7018_SETTINGS_H_ +#define _SiS7018_SETTINGS_H_ + + +#include + +#include "Driver.h" + + +#ifdef _countof +#warning "_countof(...) WAS ALREADY DEFINED!!! Remove local definition!" +#undef _countof +#endif +#define _countof(array)(sizeof(array) / sizeof(array[0])) + + +void load_settings(); +void release_settings(); + +void SiS7018_trace(bool force, const char *func, const char *fmt, ...); + +#ifdef TRACE +#undef TRACE +#endif +#define TRACE(x...) SiS7018_trace(false, __func__, x) + +#ifdef ERROR +#undef ERROR +#endif +#define ERROR(x...) SiS7018_trace(true, __func__, x) + + +#endif //_SiS7018_SETTINGS_H_ + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp new file mode 100644 index 0000000000..f4064a8d92 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp @@ -0,0 +1,362 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + * Copyright for ali5451 support: + * (c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com). + */ + + +#include "Stream.h" + +#include "Device.h" +#include "Registers.h" +#include "Settings.h" + + +Stream::Stream(Device *device, bool isInput) + : + fDevice(device), + fStatus(B_NO_INIT), + fIsInput(isInput), + fIsActive(false), + fHWChannel(isInput ? 0 : 1), + fBuffersArea(-1), + fBuffersAreaSize(0), + fBufferSamplesCount(0), + fBuffersAddress(0), + fBuffersPhysAddress(0), + fRealTime(0), + fFramesCount(0), + fBufferCycle(fIsInput ? 1 :0) +{ + fFormat.format = B_FMT_16BIT; + fFormat.rate = B_SR_48000; + fFormat.cvsr = _DecodeRate(fFormat.rate); +} + + +Stream::~Stream() +{ + Free(); +} + + +uint32 +Stream::_HWId() +{ + return fDevice->HardwareId(); +} + + +status_t +Stream::Init() +{ + if (fStatus == B_OK) + Free(); + + fHWChannel = fIsInput ? 0 : 1; + + if (_HWId() == SiS7018) + fHWChannel += 0x20; // bank B optimized for PCM + else if (_HWId() == ALi5451 && fIsInput) + fHWChannel = 31; + + // assume maximal possible buffers size + fBuffersAreaSize = 1024; // samples + fBuffersAreaSize *= 2 * 2 * 2; // stereo + 16-bit samples + 2 buffers + fBuffersAreaSize = (fBuffersAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1); + fBuffersArea = create_area( + (fIsInput) ? DRIVER_NAME "_record_area" : DRIVER_NAME "_playback_area", + &fBuffersAddress, B_ANY_KERNEL_ADDRESS, fBuffersAreaSize, + B_32_BIT_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); + if (fBuffersArea < 0) { + ERROR("Error of creating %#lx-bytes size buffer area:%#010x\n", + fBuffersAreaSize, fBuffersArea); + fStatus = fBuffersArea; + return fStatus; + } + + physical_entry PhysEntry; + get_memory_map(fBuffersAddress, fBuffersAreaSize, &PhysEntry, 1); + + fBuffersPhysAddress = PhysEntry.address; + + TRACE("Created area id %d with size: %#x at address %#x[phys:%#lx]\n", + fBuffersArea, fBuffersAreaSize, fBuffersAddress, fBuffersPhysAddress); + + // back to samples - half of buffer for 16-bit stereo data + fBufferSamplesCount = fBuffersAreaSize / (2 * 2 * 2); + + fStatus = B_OK; + return fStatus; +} + + +void +Stream::Free() +{ + delete_area(fBuffersArea); + fStatus = B_NO_INIT; +} + + +uint32 +Stream::_DecodeRate(uint32 rate) +{ + switch(rate) { + case B_SR_8000: return 8000; + case B_SR_11025: return 11025; + case B_SR_12000: return 12000; + case B_SR_16000: return 16000; + case B_SR_22050: return 22050; + case B_SR_24000: return 24000; + case B_SR_32000: return 32000; + case B_SR_44100: return 44100; + case B_SR_48000: return 48000; + } + + ERROR("Rate:%x is not supported. Fall to default 48000\n", rate); + return 48000; +} + + +void +Stream::GetFormat(multi_format_info *Format) +{ + if (fIsInput) { + Format->input_latency = 0; + Format->input = fFormat; + } else { + Format->output_latency = 0; + Format->output = fFormat; + } +} + + +status_t +Stream::SetFormat(_multi_format& format, uint32 formats, uint32 rates) +{ + if (fFormat.rate == format.rate && fFormat.format == format.format) + return B_OK; + + if ((format.rate & rates) == 0 || (format.format & formats) == 0) { + ERROR("Unsupported data format:%x or rate:%x. Ignore.\n", + format.format, format.rate); + return B_ERROR; + } + + fFormat = format; + fFormat.cvsr = _DecodeRate(fFormat.rate); + + fBufferSamplesCount = fBuffersAreaSize / (2 * 2); + switch (fFormat.format) { + default: + ERROR("Unsupported data format:%x. 16 bit assumed.\n", fFormat.format); + case B_FMT_16BIT: + fBufferSamplesCount /= 2; + break; + case B_FMT_8BIT_S: + case B_FMT_8BIT_U: + break; + } + + TRACE("Format:%#x;Rate:%#x;cvsr:%.2f\n", + fFormat.format, fFormat.rate, fFormat.cvsr); + + // stop the stream - it will be rewaked during next exchnage buffers call + Stop(); + + return B_OK; +} + + +void +Stream::GetBuffers(uint32& Flags, int32& BuffersCount, int32& ChannelsCount, + uint32& BufferSize, buffer_desc** Buffers) +{ + Flags |= fIsInput ? B_MULTI_BUFFER_RECORD : B_MULTI_BUFFER_PLAYBACK; + BuffersCount = 2; + ChannelsCount = 2; + BufferSize = fBufferSamplesCount; + + uint32 stride = 4; + if (fFormat.format == B_FMT_8BIT_S || fFormat.format == B_FMT_8BIT_U) { + stride = 2; + } + // [b][c] init buffers + Buffers[0][0].base + = Buffers[1][0].base + = Buffers[0][1].base + = Buffers[1][1].base = (char*)fBuffersAddress; + + Buffers[0][0].stride + = Buffers[1][0].stride + = Buffers[0][1].stride + = Buffers[1][1].stride = stride; + + // shift pair of second part of buffers + Buffers[1][0].base += BufferSize * stride; + Buffers[1][1].base += BufferSize * stride; + + // shift right channel buffers + Buffers[0][1].base += stride / 2; + Buffers[1][1].base += stride / 2; + + TRACE("%s buffers:\n", fIsInput ? "input" : "output"); + TRACE("1: %#010x %#010x\n", Buffers[0][0].base, Buffers[0][1].base); + TRACE("2: %#010x %#010x\n", Buffers[1][0].base, Buffers[1][1].base); +} + + +status_t +Stream::Start() +{ + uint32 CSO = 0; + uint32 LBA = uint32(fBuffersPhysAddress) & 0x3fffffff; + uint32 ESO = ((fBufferSamplesCount * 2) - 1) & 0xffff; + uint32 Delta = fIsInput ? ((48000 << 12) / uint32(fFormat.cvsr)) & 0xffff + : ((uint32(fFormat.cvsr) << 12) / 48000) & 0xffff; + uint32 DeltaESO = (ESO << 16) | Delta; + uint32 FMControlEtc = fIsInput ? 0 : (0x03 << 14); + uint32 ControlEtc = 1 << 14 | 1 << 12; // stereo data + loop enabled + + switch (fFormat.format) { + case B_FMT_16BIT: + ControlEtc |= (1 << 15); // 16 bit + case B_FMT_8BIT_S: + ControlEtc |= (1 << 13); // signed + break; + } + + switch (_HWId()) { + case TridentDX: + FMControlEtc |= (0x7f << 7) < 0x7f; + break; + case TridentNX: + CSO = Delta << 24; + DeltaESO = ((Delta << 16) & 0xff000000) | (ESO & 0x00ffffff); + FMControlEtc |= (0x7f << 7) < 0x7f; + break; + case SiS7018: + FMControlEtc = fIsInput ? (0x8a80 << 16) : FMControlEtc; + break; + } + + cpu_status cst = fDevice->Lock(); + + // select used channel + uint32 ChIntReg = fDevice->ReadPCI32(RegChIndex) & ~0x3f; + ChIntReg |= (fHWChannel & 0x3f); + fDevice->WritePCI32(RegChIndex, ChIntReg); + + fDevice->WritePCI32(RegCSOAlphaFMS, CSO); + fDevice->WritePCI32(RegLBA_PPTR, LBA); + fDevice->WritePCI32(RegDeltaESO, DeltaESO); + fDevice->WritePCI32(RegRVolCVolFMC, FMControlEtc); + fDevice->WritePCI32(RegGVSelVolCtrl, ControlEtc); + fDevice->WritePCI32(RegEBuf1, 0); + fDevice->WritePCI32(RegEBuf2, 0); + + if (fIsInput) { + uint32 reg = 0; + switch (_HWId()) { + case ALi5451: + reg = fDevice->ReadPCI32(RegALiDigiMixer); + fDevice->WritePCI32(RegALiDigiMixer, reg | (1 << _HWVoice())); + break; + case TridentDX: + reg = fDevice->ReadPCI8(RegCodecStatus); + fDevice->WritePCI8(RegCodecStatus, + reg | CodecStatusADCON | CodecStatusSBCtrl); + // enable and set record channel + fDevice->WritePCI8(RegRecChannel, 0x80 | _HWVoice()); + break; + case TridentNX: + reg = fDevice->ReadPCI16(RegMiscINT); + fDevice->WritePCI8(RegMiscINT, reg | 0x1000); + // enable and set record channel + fDevice->WritePCI8(RegRecChannel, 0x80 | _HWVoice()); + break; + } + } + + // enable INT for current channel + uint32 ChIntMask = fDevice->ReadPCI32(_UseBankB() ? RegEnaINTB : RegEnaINTA); + ChIntMask |= 1 << _HWVoice(); + fDevice->WritePCI32(_UseBankB() ? RegAddrINTB : RegAddrINTA, 1 << _HWVoice()); + fDevice->WritePCI32(_UseBankB() ? RegEnaINTB : RegEnaINTA, ChIntMask); + + // start current channel + fDevice->WritePCI32(_UseBankB() ? RegStartB : RegStartA, 1 << _HWVoice()); + + fDevice->Unlock(cst); + + TRACE("%s:CSO:%#x;LBA:%#x;ESO:%#x;Delta:%#x;FM:%#x:Ctrl:%#x;CIR:%#x\n", + fIsInput ? "Rec" : "Play", CSO, LBA, ESO, Delta, FMControlEtc, + ControlEtc, ChIntReg); + + fIsActive = true; + + return B_OK; +} + + +status_t +Stream::Stop() +{ + cpu_status cst = fDevice->Lock(); + + // stop current channel + fDevice->WritePCI32(_UseBankB() ? RegStopB : RegStopA, 1 << _HWVoice()); + + if (_HWId() == ALi5451 && fIsInput) { + uint32 reg = fDevice->ReadPCI32(RegALiDigiMixer); + fDevice->WritePCI32(RegALiDigiMixer, reg & ~(1 << _HWVoice())); + } + + fDevice->Unlock(cst); + + TRACE("%s:OK\n", fIsInput ? "Rec" : "Play"); + + fIsActive = false; + + fBufferCycle = fIsInput ? 1 : 0; + + return B_OK; +} + + +bool +Stream::InterruptHandler() +{ + uint32 SignaledMask = fDevice->ReadPCI32( + _UseBankB() ? RegAddrINTB : RegAddrINTA); + uint32 ChannelMask = 1 << _HWVoice(); + if ((SignaledMask & ChannelMask) == 0) { + return false; + } + + // first clear signalled channel bit + fDevice->WritePCI32(_UseBankB() ? RegAddrINTB : RegAddrINTA, ChannelMask); + + fRealTime = system_time(); + fFramesCount += fBufferSamplesCount; + fBufferCycle = (fBufferCycle + 1) % 2; + + fDevice->SignalReadyBuffers(); + + return true; +} + + +void +Stream::ExchangeBuffers(bigtime_t& RealTime, + bigtime_t& FramesCount, int32& BufferCycle) +{ + RealTime = fRealTime; + FramesCount = fFramesCount; + BufferCycle = fBufferCycle; +} + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.h new file mode 100644 index 0000000000..50257a120c --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.h @@ -0,0 +1,71 @@ +/* + * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. + * Copyright (c) 2002, 2008-2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ +#ifndef _SiS7018_STREAM_H_ +#define _SiS7018_STREAM_H_ + + +#include "hmulti_audio.h" + + +class Device; + +class Stream { +public: + Stream(Device* device, bool isInput); + ~Stream(); + + status_t Init(); + void Free(); + status_t InitCheck() { return fStatus; } + + status_t Start(); + status_t Stop(); + bool IsActive() { return fIsActive; } + + void GetBuffers(uint32& Flags, + int32& BuffersCount, + int32& ChannelsCount, + uint32& BufferSize, + buffer_desc** Buffers); + + void ExchangeBuffers(bigtime_t& RealTime, + bigtime_t& FramesCount, + int32& BufferCycle); + void GetFormat(multi_format_info *Format); + status_t SetFormat(_multi_format& format, + uint32 formats, uint32 rates); + + bool InterruptHandler(); + +private: + + uint32 _DecodeRate(uint32 rate); +inline bool _UseBankB() { return (fHWChannel & 0x20) == 0x20; } +inline uint32 _HWVoice() { return fHWChannel & 0x1f; } +inline uint32 _HWId(); + + Device* fDevice; + status_t fStatus; + bool fIsInput; + bool fIsActive; + uint32 fHWChannel; + + area_id fBuffersArea; + size_t fBuffersAreaSize; + size_t fBufferSamplesCount; + void* fBuffersAddress; + phys_addr_t fBuffersPhysAddress; + + _multi_format fFormat; + bigtime_t fRealTime; + bigtime_t fFramesCount; + int32 fBufferCycle; +}; + + +#endif // _SiS7018_STREAM_H_ + diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/makefile b/src/add-ons/kernel/drivers/audio/ac97/sis7018/makefile new file mode 100644 index 0000000000..29d3e2d764 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/makefile @@ -0,0 +1,127 @@ +## BeOS Generic Makefile v2.2 ## + +## Fill in this file to specify the project being created, and the referenced +## makefile-engine will do all of the hard work for you. This handles both +## Intel and PowerPC builds of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME=sis7018 + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE=DRIVER + +# add support for new Pe and Eddie features +# to fill in generic makefile + +#%{ +# @src->@ + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS=Driver.cpp\ + Device.cpp\ + Mixer.cpp\ + Stream.cpp\ + Settings.cpp\ + ../ac97.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +# @<-src@ +#%} + +# end support for Pe and Eddie + +# specify additional libraries to link against +# there are two acceptable forms of library specifications +# - if your library follows the naming pattern of: +# libXXX.so or libXXX.a you can simply specify XXX +# library: libbe.so entry: be +# +# - if your library does not follow the standard library +# naming scheme you need to specify the path to the library +# and it's name +# library: my_lib.a entry: my_lib.a or path/my_lib.a +LIBS= + +# specify additional paths to directories following the standard +# libXXX.so or libXXX.a naming scheme. You can specify full paths +# or paths relative to the makefile. The paths included may not +# be recursive, so include all of the paths where libraries can +# be found. Directories where source files are found are +# automatically included. +LIBPATHS= + +# additional paths to look for system headers +# thes use the form: #include
+# source file directories are NOT auto-included here +SYSTEM_INCLUDE_PATHS=../../../../trunk/headers/private/kernel \ + ../../../../trunk/headers/private/kernel/util + +# additional paths to look for local headers +# thes use the form: #include "header" +# source file directories are automatically included +LOCAL_INCLUDE_PATHS=../../../../trunk/build/config_headers \ + ../../../../trunk/headers/private/media + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= + +# specify any preprocessor symbols to be defined. The symbols will not +# have their values set automatically; you must supply the value (if any) +# to use. For example, setting DEFINES to "DEBUG=1" will cause the +# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" +# would pass "-DDEBUG" on the compiler's command line. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS=ALL + +# specify whether image symbols will be created +# so that stack crawls in the debugger are meaningful +# if TRUE symbols will be created +SYMBOLS= + +# specify debug settings +# if TRUE will allow application to be run from a source-level +# debugger. Note that this will disable all optimzation. +DEBUGGER= + +# specify additional compiler flags for all files +COMPILER_FLAGS= + +# specify additional linker flags +LINKER_FLAGS= + +# specify the version of this particular item +# (for example, -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL") +# This may also be specified in a resource. +APP_VERSION= + +# (for TYPE == DRIVER only) Specify desired location of driver in the /dev +# hierarchy. Used by the driverinstall rule. E.g., DRIVER_PATH = video/usb will +# instruct the driverinstall rule to place a symlink to your driver's binary in +# ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will appear at +# /dev/video/usb when loaded. Default is "misc". +DRIVER_PATH=audio/hmulti + +## include the makefile-engine +include $(BUILDHOME)/etc/makefile-engine diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/sis7018.settings.sample b/src/add-ons/kernel/drivers/audio/ac97/sis7018/sis7018.settings.sample new file mode 100644 index 0000000000..bb587a47fd --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/sis7018.settings.sample @@ -0,0 +1,29 @@ +# +# The sample sis7018 driver settings file +# +# Rename it to sis7018 and put into +# /boot/home/config/settings/kernel/drivers/ +# After restarting Media Services the new settings will works. + +## trace [on|off] - activate additional tracing. +## default value: off + +trace on + +## logfile [full path to private log file] +## default path value: /var/log/sis7018.log +## if disabled - all output goes to syslog + +logfile /var/log/sis7018.log + +## reset_logfile [on|off] - truncate private log file on driver/system restart +## default value: off +## + +# reset_logfile off + +## add_timestamp [on|off] - add time of writing the string in private log file. +## default value: on +## + +# add_timestamp off diff --git a/src/add-ons/kernel/drivers/audio/sis7018/Jamfile b/src/add-ons/kernel/drivers/audio/sis7018/Jamfile deleted file mode 100644 index 250cf780c6..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/Jamfile +++ /dev/null @@ -1,25 +0,0 @@ -SubDir HAIKU_TOP src add-ons kernel drivers audio sis7018 ; - -SetSubDirSupportedPlatformsBeOSCompatible ; - -UsePrivateHeaders audio ; - -KernelAddon sis7018 : - ac97.c - midi.c - pcm.c - sis7018.c - sis7018hw.c -; - -AddResources sis7018 : vsis7018.rdef ; - -Package haiku-sis7018-cvs - : - sis7018 - : - boot home config add-ons kernel drivers bin ; - -PackageDriverSymLink haiku-sis7018-cvs : audio sis7018 ; -Package haiku-sis7018-cvs : sis7018.settings.sample - : boot home config settings kernel drivers sample ; diff --git a/src/add-ons/kernel/drivers/audio/sis7018/ReadMe b/src/add-ons/kernel/drivers/audio/sis7018/ReadMe deleted file mode 100644 index a0a5b5bdbe..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/ReadMe +++ /dev/null @@ -1,84 +0,0 @@ -BeOS sound driver for SiS 7018 PCI Audio Accelerator - -This driver is designed to supports following chipsets: -SiS 7018 (vendor:1039 card:7018) -Trident 4D Wave DX (vendor:1023 card:2000) -Trident 4D Wave NX (vendor:1023 card:2001) - not tested -Acer Lab's M5451 (vendor:10b9 card:5451) - -What's new: ------------------------------------------------------------------------------------------------ -version 0.1.0-dev-8 -* The AC'97 codec id checking restored. -- to be continued! - -version 0.1.0-dev-7 - * Added use_io_registers to settings file. Just for testers. - * The AC'97 codec id checking bypassed - for testing purposes only - -version 0.1.0-dev-6 - * Fixed problem with "Real-time Audio". Currently works in this mode too. - -version 0.1.0-dev-5 - * Fixed AC'97 codec handling - 6bit master gain codecs schould be supported correctly - + For testing purposes added Trident DX with vendorID : 0x03 - such card found - by one tester. - -version 0.1.0-dev-4 -+ Finished some codec manipulations - mio volumes, mio mutes etc. - -version 0.1.0-dev-3 -* Fixed "last thrashed" sample problem -+ makefile and install script are fixed. - -version 0.1.0-dev-2 -* changed AC'97 initialization -+ Added settings file -+ Added possibility to write into private log file -+ More complicated AC'97 tracing possible ... - -version 0.1.0-dev-1 -* changed AC'97 initialization - -version 0.1.0-dev-0 - initial build. ------------------------------------------------------------------------------------------------ - -!!! WANTED !!! -Wanted testers with Trident NX sound hardware. Current driver is not tested on such hardware. It'll be good to asure that it work with that cards too! - -Installation -Run install.sh - -Uninstallation -Run uninstall.sh - -Problems solving -If this driver crash your system - reboot and press "Space" during load. In boot menu select "Disable user add-ons" and continue boot. Uninstall driver and reboot again into normal mode. Write me a e-mail about this problem. - -Professional testing: -If you found a problem with this driver and want to help me in development of this software make the following things (Assume that driver is already installed): - -1) Open the file /boot/home/config/settings/kernel/drivers/sis7018 and set following parameters: - -debug_output true -debug_output_in_file true - -if you have a problems with mixer - it's not work, or settings is not saved on reboot - activate this one too: - -debug_trace_ac97 true - -2) Reboot your system and try to play something. - -3) After that get the file /boot/home/sis7018.log and send it to me. - -4) It'll be good on your first bug report to me send also hardware configuration of your system. To get it go into Terminal and run following commands - -listdev - -Get all that it say to you and send me too, please ... - -Thank you !!! - -Siarzuk Zharski -http://www.zharik.host.sk/ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/ac97.c b/src/add-ons/kernel/drivers/audio/sis7018/ac97.c deleted file mode 100644 index d6dd6a7dae..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/ac97.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright (c) 2002-2003 by Siarzuk Zharski - * Portional Copyright (c) 1999 Cameron Grant - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ -#include "sis7018.h" -#include "sis7018hw.h" -#include "t4dwave.h" -#include "ac97.h" -//#include "pcm.h" - -#define TR_TIMEOUT_CDC 0xffff - -//typedef bool (*ac97init_proc)(sis7018_dev *dev, bool bOn); -/* init functions*/ -status_t ac97init_CS4299(sis7018_dev *dev, bool bOn); -status_t ac97init_default(sis7018_dev *dev, bool bOn); - -static struct ac97_codecid -{ - uint32 id; - int noext; - char *name; - status_t (*ac97init)(sis7018_dev *dev, bool bOn); -} ac97codecid[] = { - { 0x41445303, 0, "Analog Devices AD1819", NULL }, - { 0x41445340, 0, "Analog Devices AD1881", NULL }, - { 0x41445348, 0, "Analog Devices AD1881A", NULL }, - { 0x41445360, 0, "Analog Devices AD1885", NULL }, - { 0x414b4d00, 1, "Asahi Kasei AK4540", NULL }, - { 0x414b4d01, 1, "Asahi Kasei AK4542", NULL }, - { 0x414b4d02, 1, "Asahi Kasei AK4543", NULL }, - { 0x414c4710, 0, "Avance Logic ALC200/200P", NULL }, - { 0x43525900, 0, "Cirrus Logic CS4297", NULL }, - { 0x43525903, 0, "Cirrus Logic CS4297", NULL }, - { 0x43525913, 0, "Cirrus Logic CS4297A", NULL }, - { 0x43525914, 0, "Cirrus Logic CS4297B", NULL }, - { 0x43525923, 0, "Cirrus Logic CS4294C", NULL }, - { 0x4352592b, 0, "Cirrus Logic CS4298C", NULL }, - { 0x43525931, 0, "Cirrus Logic CS4299A", ac97init_CS4299 }, - { 0x43525933, 0, "Cirrus Logic CS4299C", ac97init_CS4299 }, - { 0x43525934, 0, "Cirrus Logic CS4299D", ac97init_CS4299 }, - { 0x43525941, 0, "Cirrus Logic CS4201A", NULL }, - { 0x43525951, 0, "Cirrus Logic CS4205A", NULL }, - { 0x43525961, 0, "Cirrus Logic CS4291A", NULL }, - { 0x45838308, 0, "ESS Technology ES1921", NULL }, - { 0x49434511, 0, "ICEnsemble ICE1232", NULL }, - { 0x4e534331, 0, "National Semiconductor LM4549", NULL }, - { 0x83847600, 0, "SigmaTel STAC9700/9783/9784", NULL }, - { 0x83847604, 0, "SigmaTel STAC9701/9703/9704/9705", NULL }, - { 0x83847605, 0, "SigmaTel STAC9704", NULL }, - { 0x83847608, 0, "SigmaTel STAC9708/9711", NULL }, - { 0x83847609, 0, "SigmaTel STAC9721/9723", NULL }, - { 0x83847644, 0, "SigmaTel STAC9744", NULL }, - { 0x83847656, 0, "SigmaTel STAC9756/9757", NULL }, - { 0x53494c22, 0, "Silicon Laboratory Si3036", NULL }, - { 0x53494c23, 0, "Silicon Laboratory Si3038", NULL }, - { 0x54524103, 0, "TriTech TR?????", NULL }, - { 0x54524106, 0, "TriTech TR28026", NULL }, - { 0x54524108, 0, "TriTech TR28028", NULL }, - { 0x54524123, 0, "TriTech TR28602", NULL }, - { 0x574d4c00, 0, "Wolfson WM9701A", NULL }, - { 0x574d4c03, 0, "Wolfson WM9703/9704", NULL }, - { 0x574d4c04, 0, "Wolfson WM9704 (quad)", NULL }, - { 0, 0, NULL } -}; - -static char *ac97enhancement[] = { - "No 3D Stereo Enhancement", - "Analog Devices Phat Stereo", - "Creative Stereo Enhancement", - "National Semi 3D Stereo Enhancement", - "Yamaha Ymersion", - "BBE 3D Stereo Enhancement", - "Crystal Semi 3D Stereo Enhancement", - "Qsound QXpander", - "Spatializer 3D Stereo Enhancement", - "SRS 3D Stereo Enhancement", - "Platform Tech 3D Stereo Enhancement", - "AKM 3D Audio", - "Aureal Stereo Enhancement", - "Aztech 3D Enhancement", - "Binaura 3D Audio Enhancement", - "ESS Technology Stereo Enhancement", - "Harman International VMAx", - "Nvidea 3D Stereo Enhancement", - "Philips Incredible Sound", - "Texas Instruments 3D Stereo Enhancement", - "VLSI Technology 3D Stereo Enhancement", - "TriTech 3D Stereo Enhancement", - "Realtek 3D Stereo Enhancement", - "Samsung 3D Stereo Enhancement", - "Wolfson Microelectronics 3D Enhancement", - "Delta Integration 3D Enhancement", - "SigmaTel 3D Enhancement", - "KS Waves", - "Rockwell 3D Stereo Enhancement", - "Reserved 29", - "Reserved 30", - "Reserved 31" -}; - -static char *ac97feature[] = { - "mic channel", - "reserved", - "tone", - "simulated stereo", - "headphone", - "bass boost", - "18 bit DAC", - "20 bit DAC", - "18 bit ADC", - "20 bit ADC" -}; - -static char *ac97extfeature[] = { - "variable rate PCM", - "double rate PCM", - "reserved 1", - "variable rate mic", - "reserved 2", - "reserved 3", - "center DAC", - "surround DAC", - "LFE DAC", - "AMAP", - "reserved 4", - "reserved 5", - "reserved 6", - "reserved 7", -}; - -int ac97read(sis7018_dev *dev, int regno) -{ - cpu_status cp; - int i, j, reg, rw; - if(b_trace_ac97) - TRACE(" ac97read: regno=%x\n", regno); - - switch (dev->type->ids.chip_id){ - case SPA_PCI_ID: - reg=SPA_REG_CODECRD; - rw=SPA_CDC_RWSTAT; - break; - case ALI_PCI_ID: - if(dev->info.revision > 0x01) - reg=TDX_REG_CODECWR; - else - reg=TDX_REG_CODECRD; - rw=TDX_CDC_RWSTAT; - break; - case TDX_PCI_ID: - case xDX_PCI_ID: - reg=TDX_REG_CODECRD; - rw=TDX_CDC_RWSTAT; - break; - case TNX_PCI_ID: - reg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD; - rw=TNX_CDC_RWSTAT; - break; - default: - TRACE("ac97read defaulted !!!\n"); - return ENODEV; - } - - cp = disable_interrupts(); - acquire_spinlock(&dev->hardware); - - regno &= 0x7f; - - if(dev->type->ids.chip_id == ALI_PCI_ID){ - j = rw; - for (i=TR_TIMEOUT_CDC; (i > 0) && (j & rw); i--){ - j = hw_read(dev, reg, 4); - } - if(i > 0){ - uint32 c1 = hw_read(dev, 0xc8, 4); - uint32 c2 = hw_read(dev, 0xc8, 4); - for(i=TR_TIMEOUT_CDC; (i > 0) && (c1 == c2); i--){ - c2 = hw_read(dev, 0xc8, 4); - } - } - } - if(dev->type->ids.chip_id != ALI_PCI_ID || i > 0){ - hw_write(dev, reg, regno | rw, 4); - j=rw; - for (i=TR_TIMEOUT_CDC; (i > 0) && (j & rw); i--){ - j=hw_read(dev, reg, 4); - } - } - - release_spinlock(&dev->hardware); - restore_interrupts(cp); - - if (i == 0) - TRACE_ALWAYS("ac97 codec timeout during read of register %x\n", regno); - if(b_trace_ac97) - TRACE(" ac97read: regno=%x ret = %x\n", regno, j); - return (j >> TR_CDC_DATA) & 0xffff; -} - -status_t ac97write(sis7018_dev *dev, int regno, uint32 data) -{ - cpu_status cp; - int i, j, reg, rw; - - if(b_trace_ac97) - TRACE("\nac97write: regno=%x, data=%lx\n", regno, data); - - switch (dev->type->ids.chip_id){ - case SPA_PCI_ID: - reg=SPA_REG_CODECWR; - rw=SPA_CDC_RWSTAT; - break; - case ALI_PCI_ID: - case TDX_PCI_ID: - case xDX_PCI_ID: - reg=TDX_REG_CODECWR; - rw=TDX_CDC_RWSTAT; - break; - case TNX_PCI_ID: - reg=TNX_REG_CODECWR; - rw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0); - break; - default: - TRACE("ac97write defaulted !!!"); - return ENODEV; - } - - regno &= 0x7f; - if(b_trace_ac97) - TRACE("ac97write: reg %x was %x\n", regno, ac97read(dev, regno)); - - cp = disable_interrupts(); - acquire_spinlock(&dev->hardware); - j=rw; - - if(dev->type->ids.chip_id == ALI_PCI_ID){ - for(i = TR_TIMEOUT_CDC; (i > 0) && (j & rw); i--){ - j = hw_read(dev, reg, 4); - } - if(i > 0) { - uint32 c1 = hw_read(dev, 0xc8, 4); - uint32 c2 = hw_read(dev, 0xc8, 4); - for (i = TR_TIMEOUT_CDC; (i > 0) && (c1 == c2); i--) - c2 = hw_read(dev, 0xc8, 4); - } - } - if(dev->type->ids.chip_id != ALI_PCI_ID || i > 0){ - for(i=TR_TIMEOUT_CDC; (i>0) && (j & rw); i--){ - j=hw_read(dev, reg, 4); - } - if(dev->type->ids.chip_id == ALI_PCI_ID && dev->info.revision > 0x01) - rw |= 0x0100; - hw_write(dev, reg, (data << TR_CDC_DATA) | regno | rw, 4); - } - - release_spinlock(&dev->hardware); - restore_interrupts(cp); - - if(b_trace_ac97) - TRACE("ac97write: wrote %x, now %x\n", data, ac97read(dev, regno)); - if (i==0) - TRACE_ALWAYS("ac97 codec timeout writing %x, data %lx\n", regno, data); - if(b_trace_ac97) - TRACE("ac97write: ret = %x\n\n", i); - return (i > 0)? B_OK : B_TIMED_OUT; -} - -status_t ac97init(sis7018_dev *card) -{ -// cpu_status cp; - status_t err=B_OK; - int i, /*j,*/ caps, se, noext, extcaps, extid, extstat, reg=0; - int32 id; -/* old manner - err |= ac97write(card, AC97_REG_POWER, 0); - err |= ac97write(card, AC97_REG_RESET, 0); - - err |= ac97write(card, AC97_MIX_PCM, 0x707); - err |= ac97write(card, AC97_MIX_BEEP, 0x06); - err |= ac97write(card, AC97_MIX_MIC, 0x8000); - err |= ac97write(card, AC97_MIX_PHONE, 0x707); - err |= ac97write(card, AC97_MIX_PHONES, 0x707); -*/ - - //BSD init manner - err |= ac97write(card, AC97_REG_POWER, 0x0000); - err |= ac97write(card, AC97_REG_RESET, 0); - snooze(100000); - //snooze(50000); - err |= ac97write(card, AC97_REG_POWER, 0x0000); - err |= ac97write(card, AC97_REG_GEN, 0x0000); - -/* Marcus's init manner*/ -// err |= ac97write(card, AC97_REG_RESET, 0); -// snooze(50000); // 50 ms - - if (err != B_OK){ - TRACE("ac97 codec resetting failed: %lx\n", err); - return ENODEV; - } - -// cp = disable_interrupts(); -// acquire_spinlock(&card->hardware); - - i = ac97read(card, AC97_REG_RESET); - caps = i & 0x03ff; - se = (i & 0x7c00) >> 10; - - id = (ac97read(card, AC97_REG_ID1) << 16) | ac97read(card, AC97_REG_ID2); -// codec->rev = id & 0x000000ff; - -// release_spinlock(&card->hardware); -// restore_interrupts(cp); -#if 1 - if (id == 0 || id == 0xffffffff){ - TRACE("ac97 codec invalid or not present (id == %lx)\n", id); - return ENODEV; - } -#endif - noext = 0; - for (i = 0; ac97codecid[i].id; i++){ - if (ac97codecid[i].id == id){ - status_t err = B_OK; - noext = ac97codecid[i].noext; - if (ac97codecid[i].name) - TRACE("\nac97 codec id 0x%08lx (%s)\n", id, ac97codecid[i].name); - if(ac97codecid[i].ac97init) - err |= (*ac97codecid[i].ac97init)(card, true); - else - err |= ac97init_default(card, true); - if(err != B_OK) - TRACE("ac97 codec initializatin error\n"); - } - } - - TRACE("ac97 codec features:\n"); - - for (i = 0; i < 10; i++) - if (caps & (1 << i)) - TRACE("> %s\n", ac97feature[i]); - TRACE("> %s\n", ac97enhancement[se]); - TRACE("\n"); - - extcaps = 0; - extid = 0; - extstat = 0; - if (!noext){ - i = ac97read(card, AC97_REGEXT_ID); - if (i != 0xffff){ - extcaps = i & 0x3fff; - extid = (i & 0xc000) >> 14; - extstat = ac97read(card, AC97_REGEXT_STAT) & AC97_EXTCAPS; - } - } - - if (extcaps != 0 || extid){ - TRACE("\nac97 %s codec %s:\n", extid? "secondary" : "primary", - extcaps? "extended features":""); - for (i = 0; i < 14; i++) - if (extcaps & (1 << i)) - TRACE("> %s\n", ac97extfeature[i]); - TRACE("\n"); - } - - if ((ac97read(card, AC97_REG_POWER) & 2) == 0) - TRACE("ac97 codec reports dac not ready\n"); - -// some addition - - reg = ac97read(card, AC97_MIX_MASTER); - err |= ac97write(card, AC97_MIX_MASTER, 0x3f3f); - if(0x3f3f == ac97read(card, AC97_MIX_MASTER)){ - TRACE("AC97 master gain is wide!\n"); - card->ac97.wide_main_gain = true; - } - err |= ac97write(card, AC97_MIX_MASTER, reg); - -// BSD manner - err |= ac97write(card, AC97_MIX_PCM, 0x707); -// err |= ac97write(card, AC97_MIX_BEEP, 0x06); -// err |= ac97write(card, AC97_MIX_MIC, 0x8000); -// err |= ac97write(card, AC97_MIX_PHONE, 0x707); -// err |= ac97write(card, AC97_MIX_PHONES, 0x707); - -/*Marcus's manner*/ - // err |= ac97write(card, AC97_MIX_MASTER, 0x00); - // err |= ac97write(card, AC97_MIX_PCM, 0x404); - - return err; -} - -status_t ac97get_params(sis7018_dev *dev, sound_setup *sound) -{ - uint16 reg = 0; - int main_gain_multiplier = dev->ac97.wide_main_gain ? 1 : 2; - - sound->sample_rate = kHz_48_0; - sound->dither_enable = false; - sound->output_boost = 0; - sound->highpass_enable = 0; - - reg=ac97read(dev, AC97_MIX_MONO); - sound->mono_gain = (char)reg; - sound->mono_mute = (char)(reg & AC97_MUTE) ? 1 : 0; - - reg=ac97read(dev, AC97_REG_RECSEL); - switch (reg&0x07){ - case 4: sound->right.adc_source = line; break; - case 3: sound->right.adc_source = aux1; break; - case 0: sound->right.adc_source = mic; break; - default: sound->right.adc_source = loopback; break; - } - - switch ((reg >> 8) & 0x07){ - case 4: sound->left.adc_source = line; break; - case 3: sound->left.adc_source = aux1; break; - case 0: sound->left.adc_source = mic; break; - default: sound->left.adc_source = loopback; break; - } - - reg = ac97read(dev, AC97_MIX_MIC); - sound->loop_attn = (reg & 0x1f)*2; - sound->loop_enable = (reg & AC97_MUTE) ? 0 : 1; - sound->left.mic_gain_enable = - sound->right.mic_gain_enable = (reg >> 6) & 0x01; - - reg = ac97read(dev, AC97_MIX_RGAIN); - sound->left.adc_gain = (reg >> 0x8) & 0xf; - sound->right.adc_gain = reg & 0xf; - - reg = ac97read(dev, AC97_MIX_CD); - sound->left.aux1_mix_gain = ((reg >> 8) & 0x1f); - sound->right.aux1_mix_gain = (reg & 0x1f); - sound->left.aux1_mix_mute = - sound->right.aux1_mix_mute = (reg & AC97_MUTE) ? 1 : 0; - - reg = ac97read(dev, AC97_MIX_AUX); - sound->left.aux2_mix_gain = ((reg >> 8) & 0x1f); - sound->right.aux2_mix_gain = (reg & 0x1f); - sound->left.aux2_mix_mute = - sound->right.aux2_mix_mute = (reg & AC97_MUTE) ? 1 : 0; - - - reg = ac97read(dev, AC97_MIX_LINE); - sound->left.line_mix_gain = ((reg >> 8) & 0x1f); - sound->right.line_mix_gain = (reg & 0x1f); - sound->left.line_mix_mute = - sound->right.line_mix_mute = (reg & AC97_MUTE) ? 1 : 0; - - reg = ac97read(dev, AC97_MIX_MASTER); - sound->left.dac_attn = ((reg >> 8) & 0x1f) * main_gain_multiplier; - sound->right.dac_attn = (reg & 0x1f) * main_gain_multiplier; - sound->left.dac_mute = - sound->right.dac_mute = (reg & AC97_MUTE) ? 1 : 0; - - return B_OK; -} - -status_t ac97set_params(sis7018_dev *dev, sound_setup * sound) -{ - status_t err = B_OK; - uint16 reg = 0; - int main_gain_divider = dev->ac97.wide_main_gain ? 1 : 2; - -#if 0 //DEBUG - TRACE("\nsound setup (left/right)\n"); - TRACE("adc_source %x/%x\n", sound->left.adc_source, sound->right.adc_source); - TRACE("adc_gain %x/%x\n", sound->left.adc_gain, sound->right.adc_gain); - TRACE("mic_gain_enable %x/%x\n", sound->left.mic_gain_enable, sound->right.mic_gain_enable); - TRACE("aux1_mix_gain %x/%x\n", sound->left.aux1_mix_gain, sound->right.aux1_mix_gain); - TRACE("aux1_mix_mute %x/%x\n", sound->left.aux1_mix_mute, sound->right.aux1_mix_mute); - TRACE("aux2_mix_gain %x/%x\n", sound->left.aux2_mix_gain, sound->right.aux2_mix_gain); - TRACE("aux2_mix_mute %x/%x\n", sound->left.aux2_mix_mute, sound->right.aux2_mix_mute); - TRACE("line_mix_gain %x/%x\n", sound->left.line_mix_gain, sound->right.line_mix_gain); - TRACE("line_mix_mute %x/%x\n", sound->left.line_mix_mute, sound->right.line_mix_mute); - TRACE("dac_attn %x/%x\n", sound->left.dac_attn, sound->right.dac_attn); - TRACE("dac_mute %x/%x\n", sound->left.dac_mute, sound->right.dac_mute); - TRACE("sound setup\n"); - TRACE("sample_rate %x\n", sound->sample_rate); - TRACE("playback_format %x\n", sound->playback_format); - TRACE("capture_format %x\n", sound->capture_format); - TRACE("dither_enable %x\n", sound->dither_enable); - TRACE("loop_attn %x\n", sound->loop_attn); - TRACE("loop_enable %x\n", sound->loop_enable); - TRACE("output_boost %x\n", sound->output_boost); - TRACE("highpass_enable %x\n", sound->highpass_enable); - TRACE("mono_gain %x\n", sound->mono_gain); - TRACE("mono_mute %x\n", sound->mono_mute); -#endif -//TRACE("sample-rate:%d\n", sound->sample_rate); - sound->sample_rate = kHz_48_0; - sound->dither_enable = false; - sound->output_boost = 0; - sound->highpass_enable = 0; - - reg = sound->mono_gain | ((sound->mono_mute) ? AC97_MUTE : 0); - err |= ac97write(dev, AC97_MIX_MONO, reg); - - reg = sound->loop_attn / 2; - reg |= ((sound->left.mic_gain_enable || sound->right.mic_gain_enable) ? 0x01 : 0x00) << 6; - reg |= (sound->loop_enable) ? 0 : AC97_MUTE; - err |= ac97write(dev, AC97_MIX_MIC, reg); - - reg = 0; - switch(sound->left.adc_source){ - case line: reg = 4; break; - case aux1: reg = 3; break; - case mic: reg = 0; break; - default: reg = 0; break; - } - - reg <<= 8; - switch(sound->right.adc_source){ - case line: reg |= 4; break; - case aux1: reg |= 3; break; - case mic: reg |= 0; break; - default: reg |= 0; break; - } - - err |= ac97write(dev, AC97_REG_RECSEL, reg); - - reg = (sound->left.adc_gain) << 8; - reg |= sound->right.adc_gain; - err |= ac97write(dev, AC97_MIX_RGAIN, reg); - - reg = (sound->left.aux1_mix_gain) << 0x08; - reg |= sound->right.aux1_mix_gain; - reg |= (sound->left.aux1_mix_mute || sound->right.aux1_mix_mute) ? AC97_MUTE : 0 ; - err |= ac97write(dev, AC97_MIX_CD, reg); - - reg = (sound->left.aux2_mix_gain) << 0x08; - reg |= sound->right.aux2_mix_gain; - reg |= (sound->left.aux2_mix_mute || sound->right.aux2_mix_mute) ? AC97_MUTE : 0 ; - err |= ac97write(dev, AC97_MIX_AUX, reg); - - reg = (sound->left.line_mix_gain) << 0x08; - reg |= sound->right.line_mix_gain; - reg |= (sound->left.line_mix_mute || sound->right.line_mix_mute) ? AC97_MUTE : 0 ; - err |= ac97write(dev, AC97_MIX_LINE, reg); - - reg = ((sound->left.dac_attn) / main_gain_divider) << 0x08; - reg |= (sound->right.dac_attn) / main_gain_divider; - reg |= (sound->left.dac_mute || sound->right.dac_mute) ? AC97_MUTE : 0 ; - err |= ac97write(dev, AC97_MIX_MASTER, reg); - - return err; -} - -status_t ac97init_default(sis7018_dev *dev, bool bOn) -{ - status_t err = B_OK; - //TRACE("powerdown register was = %#04x\n",ich_codec_read(AC97_POWERDOWN))); -// if (bOn) -// ac97write(dev, AC97_REG_POWER, ac97read(dev, AC97_REG_POWER) & ~0x8000); /* switch on (low active) */ -// else -// ac97write(dev, AC97_REG_POWER, ac97read(dev, AC97_REG_POWER) | 0x8000); /* switch off */ - //LOG(("powerdown register is = %#04x\n",ich_codec_read(AC97_POWERDOWN))); - return err; -} - -status_t ac97init_CS4299(sis7018_dev *dev, bool bOn) -{ - status_t err = B_OK; - TRACE("Use CS4299 init\n"); - // if (bOn) -// err |= ac97write(dev, 0x68, 0x8004); -// else -// err |= ac97write(dev, 0x68, 0); - return err; -} - -#if DEBUG -static struct -{ - int16 reg; - char name[DEVNAME]; -} ac97_regs[]= -{ - {AC97_REG_RESET, "Reset"}, {AC97_MIX_MASTER, "Master volume"}, - {AC97_MIX_PHONES, "AUX out volume"}, {AC97_MIX_MONO, "Mono volume"}, - {AC97_MIX_TONE, "Master tone"}, {AC97_MIX_BEEP, "PC beep"}, - {AC97_MIX_PHONE, "Phone volume"}, {AC97_MIX_MIC, "Mic volume"}, - {AC97_MIX_LINE, "Line in volume"}, {AC97_MIX_CD, "CD volume"}, - {AC97_MIX_VIDEO, "Video volume"}, {AC97_MIX_AUX, "AUX in volume"}, - {AC97_MIX_PCM, "PCM out volume"}, {AC97_REG_RECSEL, "Record select"}, - {AC97_MIX_RGAIN, "Record gain"}, {AC97_MIX_MGAIN, "Record gain Mic"}, - {AC97_REG_GEN, "General purpose"}, {AC97_REG_3D, "3D control"}, - {0x24, "Audio int & paging"}, {AC97_REG_POWER, "Powerdown ctrl/stat"}, - {AC97_REG_ID1, "VendorID 1"}, {AC97_REG_ID2, "VendorID 2"}, -}; - -void ac97dump(int card_id) -{ - int i; - for(i=0; i < sizeof(ac97_regs)/sizeof(ac97_regs[0]); i++) - kprintf("%s : %x\n", ac97_regs[i].name, ac97read(&cards[card_id], ac97_regs[i].reg)); -} - -#endif //DEBUG - diff --git a/src/add-ons/kernel/drivers/audio/sis7018/ac97.h b/src/add-ons/kernel/drivers/audio/sis7018/ac97.h deleted file mode 100644 index efad1729a2..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/ac97.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 AUTHOR 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 AUTHOR 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. - * - * $FreeBSD: src/sys/dev/sound/pcm/ac97.h,v 1.3.2.5 2001/08/01 03:41:03 cg Exp $ - */ - -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright permissions see above. - * - * Portion copyright (c) 2002-2003 by Siarzuk Zharski - * - * $Source: /cvsroot/sis4be/sis7018/ac97.h,v $ - * $Author: zharik $ - * $Revision: 1.4 $ - * $Date: 2003/04/08 19:18:37 $ - */ - -#define AC97_MUTE 0x8000 - -#define AC97_REG_RESET 0x00 -#define AC97_MIX_MASTER 0x02 -#define AC97_MIX_PHONES 0x04 -#define AC97_MIX_MONO 0x06 -#define AC97_MIX_TONE 0x08 -#define AC97_MIX_BEEP 0x0a -#define AC97_MIX_PHONE 0x0c -#define AC97_MIX_MIC 0x0e -#define AC97_MIX_LINE 0x10 -#define AC97_MIX_CD 0x12 -#define AC97_MIX_VIDEO 0x14 -#define AC97_MIX_AUX 0x16 -#define AC97_MIX_PCM 0x18 -#define AC97_REG_RECSEL 0x1a -#define AC97_MIX_RGAIN 0x1c -#define AC97_MIX_MGAIN 0x1e -#define AC97_REG_GEN 0x20 -#define AC97_REG_3D 0x22 -#define AC97_REG_POWER 0x26 -#define AC97_REGEXT_ID 0x28 -#define AC97_EXTCAP_VRA (1 << 0) -#define AC97_EXTCAP_DRA (1 << 1) -#define AC97_EXTCAP_VRM (1 << 3) -#define AC97_EXTCAPS (AC97_EXTCAP_VRA | AC97_EXTCAP_DRA | AC97_EXTCAP_VRM) -#define AC97_REGEXT_STAT 0x2a -#define AC97_REGEXT_FDACRATE 0x2c -#define AC97_REGEXT_SDACRATE 0x2e -#define AC97_REGEXT_LDACRATE 0x30 -#define AC97_REGEXT_LADCRATE 0x32 -#define AC97_REGEXT_MADCRATE 0x34 -#define AC97_MIXEXT_CLFE 0x36 -#define AC97_MIXEXT_SURROUND 0x38 -#define AC97_REG_ID1 0x7c -#define AC97_REG_ID2 0x7e - -/* Added by S.Zharski*/ - -status_t ac97init(sis7018_dev *dev); - -int ac97read(sis7018_dev *dev, int regno); -status_t ac97write(sis7018_dev *dev, int regno, uint32 data); - -status_t ac97get_params(sis7018_dev *dev, sound_setup *sound); -status_t ac97set_params(sis7018_dev *dev, sound_setup *sound); - -void ac97dump(int card_id); - -/* -Siarzhuk Zharski: Following not needed in BeOS build. =-) -*/ -/*#define AC97_F_EAPD_INV 0x00000001 - -#define AC97_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj)) -#define AC97_CREATE(dev, devinfo, cls) ac97_create(dev, devinfo, &cls ## _class) - -struct ac97_info; - -#include "ac97_if.h" - -extern kobj_class_t ac97_getmixerclass(void); - -struct ac97_info *ac97_create(device_t dev, void *devinfo, kobj_class_t cls); -void ac97_destroy(struct ac97_info *codec); -void ac97_setflags(struct ac97_info *codec, u_int32_t val); -u_int32_t ac97_getflags(struct ac97_info *codec); -int ac97_setrate(struct ac97_info *codec, int which, int rate); -int ac97_setextmode(struct ac97_info *codec, u_int16_t mode); -u_int16_t ac97_getextmode(struct ac97_info *codec); -u_int16_t ac97_getextcaps(struct ac97_info *codec); -*/ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/install.sh b/src/add-ons/kernel/drivers/audio/sis7018/install.sh deleted file mode 100644 index 901616bdb7..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/install.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -answer=`alert "Do you really want to install the SiS 7018 driver?" "No" "Yes"` -if [ $answer == "No" ]; then - exit -fi - -/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/bin/ -/boot/beos/bin/install -d ~/config/settings/kernel/drivers/ -/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/dev/audio/old/ -/boot/beos/bin/install `dirname $0`/sis7018 ~/config/add-ons/kernel/drivers/bin/ -/boot/beos/bin/cp `dirname $0`/sis7018.settings.sample ~/config/settings/kernel/drivers/sis7018 - -mimeset ~/config/add-ons/kernel/drivers/bin/sis7018 -mimeset ~/config/settings/kernel/drivers/sis7018 - -ln -sf ../../../bin/sis7018 ~/config/add-ons/kernel/drivers/dev/audio/old/sis7018 - -alert "The SiS 7018 driver is installed in your system. - -Go to Preferences->Media and restart media services to activate driver." diff --git a/src/add-ons/kernel/drivers/audio/sis7018/midi.c b/src/add-ons/kernel/drivers/audio/sis7018/midi.c deleted file mode 100644 index 1e3a79d042..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/midi.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright permissions see above. - * - * Portion copyright (c) 2002-2003 by Siarzuk Zharski - */ - -//#include -//#include -//#include - -#include "sis7018.h" -#include "sis7018hw.h" -#include "midi_driver.h" -#include "midi.h" - -generic_mpu401_module *mpu401; - -//extern void dump_card(sonic_vibes_dev * card); - -#if !defined(_KERNEL_EXPORT_H) -#include -#endif /* _KERNEL_EXPORT_H */ - -//#define MIDI_ACTIVE_SENSE 0xfe -//#define SNOOZE_GRANULARITY 500 - -//extern generic_mpu401_module * mpu401; - -void midi_interrupt_op(int32 op, void * data) -{ - midi_dev * port = (midi_dev *)data; - TRACE("port = %p\n", port); - if (op == B_MPU_401_ENABLE_CARD_INT) - { - cpu_status cp; - TRACE("B_MPU_401_ENABLE_CARD_INT\n"); - cp = disable_interrupts(); - acquire_spinlock(&port->card->hardware); - hw_increment_interrupt_handler(port->card); - //set_direct(port->card, 0x01, 0x00, 0x80); - //set_indirect(port->card, 0x2A, 0x04, 0xff); - release_spinlock(&port->card->hardware); - restore_interrupts(cp); - } - else if (op == B_MPU_401_DISABLE_CARD_INT) - { - /* turn off MPU interrupts */ - cpu_status cp; - TRACE("B_MPU_401_DISABLE_CARD_INT\n"); - cp = disable_interrupts(); - acquire_spinlock(&port->card->hardware); - //set_direct(port->card, 0x01, 0x80, 0x80); - /* remove interrupt handler if necessary */ - hw_decrement_interrupt_handler(port->card); - release_spinlock(&port->card->hardware); - restore_interrupts(cp); - } - TRACE("midi_interrupt_op() done\n"); -} - -static status_t midi_open(const char *name, uint32 flags, void **cookie); -static status_t midi_close(void *cookie); -static status_t midi_free(void *cookie); -static status_t midi_control(void *cookie, uint32 op, void *data, size_t len); -static status_t midi_read(void *cookie, off_t pos, void *data, size_t *len); -static status_t midi_write(void *cookie, off_t pos, const void *data, size_t *len); - - -device_hooks midi_hooks = { - &midi_open, - &midi_close, - &midi_free, - &midi_control, - &midi_read, - &midi_write, - NULL, /* select */ - NULL, /* deselect */ - NULL, /* readv */ - NULL /* writev */ -}; - -static status_t midi_open(const char * name, uint32 flags, void ** cookie) -{ - int ix; - int ret; - - TRACE("midi_open()\n"); - - *cookie = NULL; - for (ix=0; ix= num_cards) - { - TRACE("bad device\n"); - return ENODEV; - } - - TRACE("mpu401: %p open(): %p driver: %p\n", mpu401, mpu401->open_hook, cards[ix].midi.driver); - ret = (*mpu401->open_hook)(cards[ix].midi.driver, flags, cookie); - if (ret >= B_OK) - { - cards[ix].midi.cookie = *cookie; - atomic_add(&cards[ix].midi.count, 1); - } - TRACE("mpu401: open returns %x / %p\n", ret, *cookie); - return ret; -} - -static status_t midi_close(void * cookie) -{ - TRACE("midi_close()\n"); - return (*mpu401->close_hook)(cookie); -} - -static status_t midi_free(void * cookie) -{ - int ix; - status_t f; - TRACE("midi_free()\n"); - f = (*mpu401->free_hook)(cookie); - for (ix=0; ixcontrol_hook)(cookie, iop, data, len); -} - -static status_t midi_read( void * cookie, off_t pos, void * ptr, size_t * nread) -{ - TRACE("midi_read\n"); - return (*mpu401->read_hook)(cookie, pos, ptr, nread); -} - -static status_t midi_write(void * cookie, off_t pos, const void * ptr, size_t * nwritten) -{ - TRACE("midi_write\n"); - return (*mpu401->write_hook)(cookie, pos, ptr, nwritten); -} - -bool midi_interrupt( sis7018_dev * dev) -{ - if (!dev->midi.driver) - { -// kprintf("aiigh\n"); - return false; - } - kprintf("midi_interrupt\n"); - return (*mpu401->interrupt_hook)(dev->midi.driver); -} - diff --git a/src/add-ons/kernel/drivers/audio/sis7018/midi.h b/src/add-ons/kernel/drivers/audio/sis7018/midi.h deleted file mode 100644 index 6ee6616bdd..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/midi.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright (c) 2002-2003 by Siarzuk Zharski - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ - -#ifndef _MIDI_H_ - #define _MIDI_H_ - -#ifndef _DRIVERS_H - #include -#endif //_DRIVERS_H - -extern device_hooks midi_hooks; -void midi_interrupt_op(int32 op, void * data); -extern generic_mpu401_module *mpu401; -#endif //_MIDI_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/midi_driver.h b/src/add-ons/kernel/drivers/audio/sis7018/midi_driver.h deleted file mode 100644 index 2d0eff4355..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/midi_driver.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright permissions see above. - * - * Portion copyright (c) 2002-2003 by Siarzuk Zharski - */ - -#ifndef _MIDI_DRIVER_H -#define _MIDI_DRIVER_H - -#include -#include - -/* ----- - ioctl codes ------ */ - -/* the old opcodes are deprecated, and may or may not work - in newer drivers */ -enum { - B_MIDI_GET_READ_TIMEOUT = B_MIDI_DRIVER_BASE, - B_MIDI_SET_READ_TIMEOUT, - B_MIDI_TIMED_READ, - B_MIDI_TIMED_WRITE, - B_MIDI_WRITE_SYNC, - B_MIDI_WRITE_CLEAR, - B_MIDI_GET_READ_TIMEOUT_OLD = B_DEVICE_OP_CODES_END + 1, - B_MIDI_SET_READ_TIMEOUT_OLD -}; - -/* the default timeout when you open a midi driver */ -#define B_MIDI_DEFAULT_TIMEOUT 1000000000000000LL - -/* Usage: - To read, set "data" to a pointer to your buffer, and "size" to the - maximum size of this buffer. On return, "when" will contain the time - at which the data was received (first byte) and "size" will contain - the actual amount of data read. - Call ioctl(fd, B_MIDI_TIMED_READ, &midi_timed_data, sizeof(midi_timed_data)); - To write, set "when" to when you want the first byte to go out the - wire, set "data" to point to your data, and set "size" to the size - of your data. - Call ioctl(fd, B_MIDI_TIMED_WRITE, &midi_timed_data, sizeof(midi_timed_data)); -*/ -typedef struct { - bigtime_t when; - size_t size; - unsigned char * data; -} midi_timed_data; - - -/* The MIDI parser returns the number of bytes that a message contains, given the */ -/* initial byte. For some messages, this is not known until the second byte is seen. */ -/* For such messages, a state > 0 is returned as well as some count > 0. When state */ -/* is > 0, you should call (*parse) for the next byte as well, which might modify */ -/* the returned message size. Message size will always be returned with the current */ -/* byte being counted as byte 1. A return of 0 means that the byte initiates a new */ -/* message. SysX is handled by returning max_size until the end or next initial message */ -/* is seen. So your loop looks something like: */ -/* - uint32 state = 0; // Only set this to 0 the first time you call the parser. - // preserve the 'state' between invocations of your read() hook. - int todo = 0; - unsigned char * end = in_buf+buf_size - unsigned char * out_buf = in_buf; - while (true) { - uchar byte = read_midi(); - if (!todo || state) { - todo = (*parser->parse)(&state, byte, end-out_buf); - } - if (todo < 1) { - unput_midi(byte); - } else { - *(out_buf++) = byte; - todo--; - } - if (todo < 1 || out_buf >= end) { - received_midi_message(in_buf, out_buf-in_buf); - todo = 0; - } - } - */ - -#define B_MIDI_PARSER_MODULE_NAME "media/midiparser/v1" - -typedef struct _midi_parser_module_info { - module_info minfo; - int (*parse)(uint32 * state, uchar byte, size_t max_size); - int _reserved_; -} midi_parser_module_info; - -#define B_MPU_401_MODULE_NAME "generic/mpu401/v1" - -enum { - B_MPU_401_ENABLE_CARD_INT = 1, - B_MPU_401_DISABLE_CARD_INT -}; -typedef struct _generic_mpu401_module { - module_info minfo; - status_t (*create_device)(int port, void ** out_storage, uint32 workarounds, void (*interrupt_op)(int32 op, void * card), void * card); - status_t (*delete_device)(void * storage); - status_t (*open_hook)(void * storage, uint32 flags, void ** out_cookie); - status_t (*close_hook)(void * cookie); - status_t (*free_hook)(void * cookie); - status_t (*control_hook)(void * cookie, uint32 op, void * data, size_t len); - status_t (*read_hook)(void * cookie, off_t pos, void * data, size_t * len); - status_t (*write_hook)(void * cookie, off_t pos, const void * data, size_t * len); - bool (*interrupt_hook)(void * cookie); - int _reserved_; -} generic_mpu401_module; - -#endif diff --git a/src/add-ons/kernel/drivers/audio/sis7018/pcm.c b/src/add-ons/kernel/drivers/audio/sis7018/pcm.c deleted file mode 100644 index b9378b87e2..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/pcm.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright (c) 2002-2003 by Siarzuk Zharski - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ -#include "pcm.h" -#include "sis7018.h" -#include "sis7018hw.h" // ioctl definitions -#include "sound.h" -#include "ac97.h" -#include "R3MediaDefs.h" // sound_buffer definition -#include "t4dwave.h" - -#if DEBUG -int32 int_cnt; -int32 put_cnt; -bigtime_t the_time; -#endif - -/* pcm_open - handle open() calls */ -static status_t pcm_open (const char *name, uint32 flags, void** cookie) -{ - int ix; - pcm_dev *port = NULL; - - TRACE("pcm_open(%s, %lx)\n", name, flags); - - *cookie = NULL; - for (ix=0; ixinit_sem); - - if (atomic_add(&port->open_count, 1) == 0) - { - TRACE("pcm_open: first open\n"); - port->card = &cards[ix]; - - port->open_mode = (flags & O_RWMASK); - if (port->open_mode != O_RDONLY) - ;// TODO start playback "dma" - - if (port->open_mode != O_WRONLY) - ;//TODO start record "dma" - - port->old_cap_sem = -1; - port->old_play_sem = -1; - - hw_pchannel_init(port); - hw_increment_interrupt_handler(port->card); - } - else - { - if ((flags & O_RWMASK) == O_RDWR) - { - if (port->open_mode == O_RDONLY) - ; //TODO start playback "dma" - else - if (port->open_mode == O_WRONLY) - ; //TODO start record "dma" - port->open_mode = O_RDWR; - } - TRACE("pcm_open: next opens\n"); - } - - hw_start(port); - - release_sem(port->init_sem); - - return B_OK; -} - -/* pcm_read - handle read() calls */ -static status_t pcm_read (void* cookie, off_t position, void *buf, size_t* num_bytes) -{ - pcm_dev * port = (pcm_dev *)cookie; - - if (port->open_mode == O_WRONLY) - return EPERM; - -// TRACE("pcm_read(%p, %d, %p, %d)\n", cookie, position, buf, *num_bytes); - *num_bytes = 0; /* tell caller nothing was read */ - return B_IO_ERROR; -} - -extern int intrs; - -static status_t pcm_write(void * cookie, off_t pos, const void * data, size_t * nwritten) -{ - pcm_dev * port = (pcm_dev *)cookie; - sis7018_ch *ch = &((pcm_dev *)cookie)->play_channel; - status_t err; - cpu_status cp; - int written = 0; - int to_write = *nwritten; /* in play bytes, not input bytes! */ - int block; - int bytes_xferred; - - if (port->open_mode == O_RDONLY) - return EPERM; - - *nwritten = 0; - - if ((err = acquire_sem_etc(ch->wr_entry, 1, B_CAN_INTERRUPT, 0)) < B_OK) - { - TRACE("wr_entry acquisition failed\n"); - return err; - } - atomic_add(&ch->write_waiting, 1); - - while (to_write > 0) - { - /* wait to write */ - if ((err = acquire_sem_etc(ch->write_sem, 1, B_CAN_INTERRUPT, 0)) < B_OK) - { - TRACE("write_sem acquisition failed\n"); - release_sem(ch->wr_entry); - return err; - } - -#if DEBUG - put_cnt++; - { - bigtime_t delta = system_time() - the_time; - if (delta < 1) { - TRACE("delta %Ld (low!) #%ld\n", delta, put_cnt); - } - else if (delta > 2000) { - TRACE("delta %Ld (high!) #%ld\n", delta, put_cnt); - } - } - if (put_cnt != int_cnt) { - static int last; - if (last != int_cnt-put_cnt) - TRACE("%ld mismatch\n", int_cnt-put_cnt); - last = int_cnt-put_cnt; - } -#endif /* DEBUG */ - - // KTRACE(); - cp = disable_interrupts(); - acquire_spinlock(&ch->wr_lock); - - block = ch->wr_size-ch->was_written; - if (block > to_write) - { - /* must let next guy in */ - if (atomic_add(&ch->write_waiting, -1) > 0) - release_sem_etc(ch->write_sem, 1, B_DO_NOT_RESCHEDULE); - else - atomic_add(&ch->write_waiting, 1); /* undo damage */ - - block = to_write; - } - else - if (block < to_write) - atomic_add(&ch->write_waiting, 1); /* we will loop back */ - - /* switch (port->config.format) - {*/ - // case 0x24: /* floats */ - /* copy_float_to_short((short *)(port->wr_cur+port->was_written), (const float *)data, - block, !B_HOST_IS_LENDIAN == !port->config.big_endian); - bytes_xferred = block * 2; - break; */ - // case 0x02: /* shorts */ - // if (!B_HOST_IS_LENDIAN == !port->config.big_endian) { - /* we need to swap */ - /* swap_copy((short *)(port->wr_cur+port->was_written), (const short *)data, block); - bytes_xferred = block; - break; - } - */ /* else fall through to default case */ - // case 0x11: /* bytes */ - // default: -// my_copy((short *)(ch->wr_cur+ch->was_written), (const short *)data, block); - memcpy((void *)(ch->wr_cur+ch->was_written), data, block); - bytes_xferred = block; - /* break; - }*/ - ch->was_written += block; - ch->wr_silence = 0; - - release_spinlock(&ch->wr_lock); - restore_interrupts(cp); - -#if DEBUG - if(ch->wr_cur == ch->wr_cur_prv) - { - int tt = (system_time() - ch->time_prv)/1000; - TRACE("%d ms block - %x, to_write: %x ,size: %x,was_written: %x\n", tt, block, to_write, ch->wr_size, ch->was_written); - ch->time_prv = system_time(); - } - - ch->wr_cur_prv = ch->wr_cur; -#endif - - data = ((char *)data)+bytes_xferred; - written += bytes_xferred; - to_write -= block; - } - - *nwritten = written; - release_sem(ch->wr_entry); - - return B_OK; -} - -bool playback_interrupt(sis7018_ch * ch, bool bHalf) -{ - bool ret = false; -// pcm_dev * port = &dev->pcm; -// sis7018_ch *ch = &dev->pcm.play_channel; - volatile uchar * ptr; -// uint32 addr; - uint32 offs; - bigtime_t st = system_time(); -// int32 ww; -// sis7018_ch ch2 = *ch; - -#if 0 -ddprintf(("sonic_vibes: dma_a 0x%x+0x%x\n", PCI_IO_RD_32((int)port->dma_c), PCI_IO_RD_32((int)port->dma_c+4))); -#endif -// KTRACE(); /* */ - acquire_spinlock(&ch->wr_lock); - - if (ch->write_sem < 0) - { - dprintf("spurious play interrupt!\n"); - release_spinlock(&ch->wr_lock); - return false; - } - /* copy possible silence into playback buffer */ - - if (ch->was_written > 0 && ch->was_written < ch->wr_size) - // { -/* if (port->config.format == 0x11) - { - memset((void *)(port->wr_cur+port->was_written), 0x80, port->wr_size-port->was_written); - } - else {*/ - memset((void *)(ch->wr_cur+ch->was_written), 0, ch->wr_size-ch->was_written); - // } -// } - - /* because the system may be lacking and not hand us the */ - /* interrupt in time, we check which half is currently being */ - /* played, and set the pointer to the other half */ - -// addr = PCI_IO_RD_32((uint32)port->dma_a); -// if ((offs = addr-(uint32)port->card->low_phys) < port->wr_size) -// hw_rdch(&ch2); - - // select channel ... - offs = hw_read(ch->card, TR_REG_CIR, 4); - offs &= ~TR_CIR_MASK; - offs |= ch->index & 0x3f; - hw_write(ch->card, TR_REG_CIR, offs, 4); - - // read current cso - switch(ch->card->type->ids.chip_id) - { - case SPA_PCI_ID: - case ALI_PCI_ID: - case TDX_PCI_ID: - case xDX_PCI_ID: - offs=((hw_read(ch->card, TR_REG_CHNBASE, 4) & 0xffff0000) >> 16) * 4; - break; - case TNX_PCI_ID: - offs=(hw_read(ch->card, TR_REG_CHNBASE, 4) & 0x00ffffff) * 4; - break; - } - - if (offs < ch->wr_size) - ptr = ch->wr_2; - else - ptr = ch->wr_1; - - ch->wr_total += ch->mem_size/2; - /* compensate for interrupt latency */ - /* assuming 4 byte frames */ - ch->wr_time = st-(offs&(ch->mem_size/2-1))*250000LL/(int64)48000; - -/* if ((ww = atomic_add(&ch->wr_time_wait, -1)) > 0) - { - release_sem_etc(ch->wr_time_sem, 1, B_DO_NOT_RESCHEDULE); - ret = true; - } - else - { -*/// atomic_add(&ch->wr_time_wait, 1); /* re-set to 0 */ -// } - - if (ch->wr_cur == ptr) - { - ch->wr_skipped++; - dprintf("write skipped %ld\n", ch->wr_skipped); - } - - ch->wr_cur = ptr; - ch->was_written = 0; - - /* check for client there to write into buffer */ - - if (atomic_add(&ch->write_waiting, -1) > 0) - { -#if DEBUG - int_cnt++; - the_time = st; -#endif - release_sem_etc(ch->write_sem, 1, B_DO_NOT_RESCHEDULE); - ret = true; - } - else - { - atomic_add(&ch->write_waiting, 1); - /* if none there, fill with silence */ - if (ch->wr_silence < ch->mem_size) - { - /* if (port->config.format == 0x11) { - memset((void *)ptr, 0x80, port->wr_size); - } - else {*/ - memset((void *)ptr, 0, ch->wr_size); - //} - ch->wr_silence += ch->wr_size; - } - } - /* copying will be done in user thread */ - - release_spinlock(&ch->wr_lock); - return ret; -} - -/* pcm_control - handle ioctl calls */ -static status_t pcm_control (void* cookie, uint32 op, void* arg, size_t len) -{ - status_t err = B_BAD_VALUE; - pcm_dev * port = (pcm_dev *)cookie; -// TRACE("pcm_control(%p, %lx)\n", cookie, op); - switch (op) - { - case SOUND_GET_PARAMS: - // TRACE("SOUND_GET_PARAMS\n"); - err = ac97get_params(port->card, (sound_setup *)arg); - break; - case SOUND_SET_PARAMS: - // TRACE("SOUND_SET_PARAMS\n"); - err = ac97set_params(port->card, (sound_setup *)arg); - break; - case SOUND_SET_PLAYBACK_COMPLETION_SEM: - // TRACE("SOUND_SET_PLAYBACK_COMPLETION_SEM\n"); - port->old_play_sem = *(sem_id *)arg; - err = B_OK; - break; - case SOUND_SET_CAPTURE_COMPLETION_SEM: - // TRACE("SOUND_SET_CAPTURE_COMPLETION_SEM\n"); - port->old_cap_sem = *(sem_id *)arg; - err = B_OK; - break; - case SOUND_UNSAFE_WRITE: - { - sis7018_ch *ch = &((sis7018_dev *)cookie)->pcm.play_channel; - audio_buffer_header * buf = (audio_buffer_header *)arg; - size_t n = buf->reserved_1-sizeof(*buf); - //TRACE("%ld %ld %ld %ld\n", buf->reserved_1, buf->reserved_2, buf->sample_clock, buf->time ); - //TRACE("SOUND_UNSAFE_WRITE %d\n", n); - err = pcm_write(cookie, 0, buf+1, &n); - buf->time = ch->wr_time; - buf->sample_clock = ch->wr_total/4 * 1000 / 48; - err |= release_sem(port->old_play_sem); - // err = B_OK; - } - break; - case SOUND_UNSAFE_READ: - TRACE("SOUND_UNSAFE_READ\n"); - // ASSERT(0); - err = release_sem(port->old_cap_sem); - err = B_IO_ERROR; - break; - case SOUND_LOCK_FOR_DMA: - TRACE("SOUND_LOCK_FOR_DMA\n"); - err = B_OK; - break; - case SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE: - { - int32 new_size = (int32)arg; - TRACE("SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE: 0x%x\n", new_size); - hw_pchannel_setblocksize(port, new_size); - err = B_OK; - } - break; - case SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE: - // TRACE("SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE\n"); - // config.rec_buf_size = (int32)data; - // configure = true; - err = B_OK; - break; - case SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE: - TRACE("SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE\n"); - *(int32*)arg = port->play_channel.mem_size/2; - err = B_OK; - break; - case SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE: - // TRACE("SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE\n"); - // *(int32*)data = config.rec_buf_size; - err = B_OK; - break; - default: - TRACE("pcm_control : unknown code %ld\n", op); - err = B_BAD_VALUE; - break; - } - return err; -} - -/* pcm_close - handle close() calls */ -static status_t pcm_close (void* cookie) -{ - pcm_dev * port = (pcm_dev *)cookie; - TRACE("pcm_close(%p)\n", cookie); - - acquire_sem(port->init_sem); - - if (atomic_add(&port->open_count, -1) == 1) - { - TRACE("pcm_close: last close\n"); - hw_stop(port); - hw_pchannel_free(port); - } - else - { - TRACE("pcm_close: previous closes\n"); - } - - release_sem(port->init_sem); - return B_OK; -} - - -/* pcm_free - called after the last device is closed, and after all i/o is complete. */ -static status_t pcm_free (void* cookie) -{ - pcm_dev *port = (pcm_dev *)cookie; - TRACE("pcm_free(%p)\n", cookie); - - acquire_sem(port->init_sem); - - if (port->open_count == 0) - { - hw_decrement_interrupt_handler(port->card); - } - - release_sem(port->init_sem); - return B_OK; -} - -/* function pointers for the device hooks entry points */ -device_hooks pcm_hooks = -{ - pcm_open, /* -> open entry point */ - pcm_close, /* -> close entry point */ - pcm_free, /* -> free cookie */ - pcm_control, /* -> control entry point */ - pcm_read, /* -> read entry point */ - pcm_write /* -> write entry point */ -}; diff --git a/src/add-ons/kernel/drivers/audio/sis7018/pcm.h b/src/add-ons/kernel/drivers/audio/sis7018/pcm.h deleted file mode 100644 index 6e034e71e8..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/pcm.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright (c) 2002-2003 by Siarzuk Zharski - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ -#ifndef _PCM_H_ - #define _PCM_H_ - -#ifndef _DRIVERS_H - #include -#endif //_DRIVERS_H - -#ifndef _SIS7018_H_ - #include "sis7018.h" -#endif //_SIS7018_H_ - -extern device_hooks pcm_hooks; - -bool playback_interrupt(sis7018_ch *ch, bool bHalf); - -/* secret handshake ioctl()s */ -/*#define SV_SECRET_HANDSHAKE 10100 -typedef struct { - bigtime_t wr_time; - bigtime_t rd_time; - uint32 wr_skipped; - uint32 rd_skipped; - uint64 wr_total; - uint64 rd_total; - uint32 _reserved_[6]; -} sv_handshake; -#define SV_RD_TIME_WAIT 10101 -#define SV_WR_TIME_WAIT 10102 -typedef struct { - bigtime_t time; - bigtime_t bytes; - uint32 skipped; - uint32 _reserved_[3]; -} sv_timing; -*/ -#endif //_PCM_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.c b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.c deleted file mode 100644 index edcfaacb2f..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright (c) 2002-2003 by Siarzuk Zharski - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ -#include //sprintf -#include -#include //posix file i/o - create, write, close -#include -#include "sis7018.h" -#include "sis7018hw.h" -#include "ac97.h" - -#if DO_PCM -#include "pcm.h" -#endif - -#if DO_MIDI -#include "midi_driver.h" -#include "midi.h" -#endif - -#define NUM_CARDS 3 - -int32 num_cards; -sis7018_dev cards[NUM_CARDS]; -int num_names; -char * names[NUM_CARDS*7+1]; - -#if DEBUG -bool b_log = true; -#else -bool b_log = false; -#endif -bool b_log_file = false; -bool b_log_append = false; -bool b_trace_ac97 = false; -bool use_io_regs = false; - -static const char *private_log_path="/boot/home/sis7018.log"; -static sem_id loglock; - -static void reload_sis7018_setting() -{ - void *settingshandle; - settingshandle = load_driver_settings(CHIPNAME); -#if !DEBUG - b_log = get_driver_boolean_parameter(settingshandle, "debug_output", b_log, true); -#endif - b_log_file = get_driver_boolean_parameter(settingshandle, "debug_output_in_file", b_log_file, true); - b_log_append = ! get_driver_boolean_parameter(settingshandle, "debug_output_file_rewrite", !b_log_append, true); - b_trace_ac97 = get_driver_boolean_parameter(settingshandle, "debug_trace_ac97", b_trace_ac97, true); - use_io_regs = get_driver_boolean_parameter(settingshandle, "use_io_registers", use_io_regs, true); - unload_driver_settings(settingshandle); -} - -void create_log() -{ - int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0); - if(!b_log_file) - return; - close(open(private_log_path, flags, 0666)); - loglock = create_sem(1,"sis7018 logfile"); -} - -void sis7018_trace(bool b_force, char *fmt, ...) -{ - if(!(b_force || b_log)) - return; - { - va_list arg_list; - static char *prefix = "\33[32m"CHIPNAME":\33[0m"; - static char buf[1024]; - char *buf_ptr = buf; - if(!b_log_file) - { - strcpy(buf, prefix); - buf_ptr += strlen(prefix); - } - - va_start(arg_list, fmt); - vsprintf(buf_ptr, fmt, arg_list); - va_end(arg_list); - - if(b_log_file) - { - int fd; - if(!b_trace_ac97) - acquire_sem(loglock); - fd = open(private_log_path, O_WRONLY | O_APPEND); - write(fd, buf, strlen(buf)); - close(fd); - if(!b_trace_ac97) - release_sem(loglock); - } - else - dprintf(buf); - } -} - -card_type card_types[]= -{ - {{TDX_PCI_ID}, "Trident DX"}, - {{xDX_PCI_ID}, "Trident XX"}, - {{TNX_PCI_ID}, "Trident NX"}, - {{ALI_PCI_ID}, "ALi 5451"}, - {{SPA_PCI_ID}, "SiS 7018"}, -}; - -#ifdef DEBUG -int _assert_(char *a, int b, char *c) -{ - char sz[1024]; - sprintf(sz, CHIPNAME":tripped assertion in %s/%d (%s)", a, b, c); - TRACE("tripped assertion in %s/%d (%s)\n", a, b, c); - kernel_debugger(sz); - return 0; -} -#endif - -static void make_device_names(sis7018_dev * card) -{ - char * name = card->name; - sprintf(name, "%s/%ld", card->type->chip_name, card-cards+1); - -#if DO_MIDI - sprintf(card->midi.name, "midi/%s", name); - names[num_names++] = card->midi.name; -#endif //DO_MIDI - -#if DO_PCM -// sprintf(card->pcm.name, "audio/raw/%s", name); -// names[num_names++] = card->pcm.name; - sprintf(card->pcm.oldname, "audio/old/%s", name); - names[num_names++] = card->pcm.oldname; -#endif //DO_PCM - - names[num_names] = NULL; -} - -static status_t setup_hardware( sis7018_dev * card) -{ - status_t err = B_OK; - int32 command_reg; - - TRACE("setup_hardware(%p)\n", card); - - if ((card->pcm.init_sem = create_sem(1, "sis7018 pcm init")) < B_OK) - goto bail; - -#if DO_MIDI //TODO: below? - if ((*mpu401->create_device)(card->info.u.h0.base_registers[3], &card->midi.driver, - 0, midi_interrupt_op, &card->midi) < B_OK) - goto bail3; - TRACE("midi %p\n", card->midi.driver); - card->midi.card = card; -#endif //DO_MIDI - - make_device_names(card); - - command_reg = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, - PCI_command, 2); -// TRACE("PCI command config was: %lx\n", command_reg); - command_reg |= PCI_command_io | PCI_command_memory | PCI_command_master; - (*pci->write_pci_config)(card->info.bus, card->info.device, card->info.function, - PCI_command, 2, command_reg); -// TRACE("PCI command config set to: %lx\n", command_reg); - - if(use_io_regs) - { - card->io_base = card->info.u.h0.base_registers[0]; - TRACE("%s base at %x\n", card->name, card->io_base); - } - else // USE_IO_RANGE - { - TRACE("%s memory %lx length %lx\n", card->name, card->info.u.h0.base_registers[1], card->info.u.h0.base_register_sizes[1]); - card->regs_area = map_physical_memory("Regs sis7018", - card->info.u.h0.base_registers[1], - card->info.u.h0.base_register_sizes[1], - B_ANY_KERNEL_ADDRESS, - B_READ_AREA + B_WRITE_AREA, - &card->regs_mem_base); - - TRACE("%s registers memory base at 0x%p\n", card->name, card->regs_mem_base); - }// USE_IO_RANGE - - err = hw_initialize(card); - return err; - -#if DO_MIDI -bail3: -#endif //DO_MIDI - delete_sem(card->pcm.init_sem); -bail: - return err < B_OK ? err : B_ERROR; -} - -#if DEBUG -static int debug_sis7018(int argc, char * argv[]) -{ - int err = (argc < 2 || argc > 3); - int card_id = 0; - - if(!err) - { - if(argc == 3) - card_id = parse_expression(argv[2]); - - if(card_id < 0 || card_id > num_cards-1) - { - kprintf("ERROR: Wrong card_id: %d\n", card_id); - kprintf("\n"); - err = 1; - } - else - { - switch((char)*(argv[1])) - { - case 'd': hw_dump_device(card_id); break; - case 'i': hw_dump_pci_info(card_id); break; - case 'p': hw_dump_pcm_device(card_id); break; - case 'm': hw_dump_midi_device(card_id); break; - case 'c': hw_dump_play_channel(card_id); break; - case 'a': ac97dump(card_id); break; - default: - kprintf("ERROR: Wrong command: %s\n",argv[1]); - kprintf("\n"); - err=1; - break; - } - } - } - - if (err) - { - kprintf("Syntax: "CHIPNAME" < command > [card id]\n"); - kprintf(" - where commands is:\n"); - kprintf(" d - dump device info\n"); - kprintf(" i - dump pci_info\n"); - kprintf(" p - dump pcm info\n"); - kprintf(" m - dump midi info\n"); - kprintf(" c - dump playback channel info\n"); - kprintf(" a - dump AC'97 registers info\n"); - kprintf(" - and card id is zero-based id of card to be investigated\n"); - kprintf(" default card id is 0\n"); - kprintf(" current cards count is %ld\n", num_cards); - kprintf("\n"); - } - - return 0; -} -#endif /* DEBUG */ - -/************** SYSTEM CALLBACKS ************************************/ - -int32 api_version = B_CUR_DRIVER_API_VERSION; - -/* init_hardware - called once the first time the driver is loaded */ -status_t init_hardware (void) -{ - int ix = 0, jx = 0; - pci_info info; - status_t err = ENODEV; - - TRACE("init_hardware()\n"); - - if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci)) - return ENOSYS; - - while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) - { - for(jx = 0; jx < sizeof(card_types)/sizeof(card_types[0]); jx++) - if (info.vendor_id == card_types[jx].ids.ids.vendor_id - && info.device_id == card_types[jx].ids.ids.card_id) - { - err = B_OK; - } - ix++; - } - - put_module(B_PCI_MODULE_NAME); - return err; -} - - -status_t -init_driver(void) -{ - int ix = 0, jx = 0; - pci_info info; - num_cards = 0; - - reload_sis7018_setting(); - create_log(); - - TRACE("\n>>> init_driver()\n"); - - if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) - return ENOSYS; - -#if DO_MIDI - TRACE("MPU\n"); - if (get_module(B_MPU_401_MODULE_NAME, (module_info **) &mpu401)) - { - put_module(B_PCI_MODULE_NAME); - return ENOSYS; - } - TRACE("MPU: %p\n", mpu401); -#endif //DO_MIDI - - while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) - { - for(jx = 0; jx < sizeof(card_types)/sizeof(card_types[0]); jx++) - if (info.vendor_id == card_types[jx].ids.ids.vendor_id - && info.device_id == card_types[jx].ids.ids.card_id) - { - if (num_cards == NUM_CARDS) - { - TRACE_ALWAYS("Too many cards installed! Only %d will be used.\n", NUM_CARDS); - break; - } - - memset(&cards[num_cards], 0, sizeof(sis7018_dev)); - cards[num_cards].info = info; - cards[num_cards].type = &card_types[jx]; - if (setup_hardware(&cards[num_cards])) - { - TRACE_ALWAYS("Setup of %s driver for %ld-th card failed\n", CHIPNAME, num_cards+1); - } - else - num_cards++; - - TRACE_ALWAYS("%s found.\n", - card_types[jx].chip_name, - card_types[jx].ids.ids.vendor_id, - card_types[jx].ids.ids.card_id); - } - ix++; - } - - if (!num_cards) - { -#if DO_MIDI - put_module(B_MPU_401_MODULE_NAME); -#endif //DO_MIDI - put_module(B_PCI_MODULE_NAME); - TRACE("No suitable cards found\n"); - return ENODEV; - } - -#if DEBUG - add_debugger_command(CHIPNAME, debug_sis7018, CHIPNAME" driver info."); -#endif - return B_OK; -} - -static void teardown_card(sis7018_dev *card) -{ - /* remove created devices */ -#if DO_MIDI - (*mpu401->delete_device)(card->midi.driver); -#endif //DO_MIDI - - if(!use_io_regs) - delete_area(card->regs_area); - - delete_sem(card->pcm.init_sem); -} - -/* uninit_driver - optional function - called every time the driver is unloaded */ -void uninit_driver (void) -{ - int ix, cnt = num_cards; - num_cards = 0; - - TRACE("<<< uninit_driver()\n\n"); - -#if DEBUG - remove_debugger_command(CHIPNAME, debug_sis7018); -#endif - - for (ix=0; ix - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ -#ifndef _SIS7018_H_ - #define _SIS7018_H_ - -#include -#include -#include -#include - -#define CHIPNAME "sis7018" - -void sis7018_trace(bool b_force, char *fmt, ...); - -//#define TRACE_ALWAYS(x...) dprintf("\33[32m"CHIPNAME":\33[0m"x); -#define TRACE_ALWAYS(x...) sis7018_trace(true, x); -#define TRACE(x...) sis7018_trace(false, x); - -extern bool b_trace_ac97; - -#if DEBUG -//#define TRACE(x...) TRACE_ALWAYS(x) -int _assert_(char *,int,char *); -#define ASSERT(c) (!(c) ? _assert_(__FILE__, __LINE__, #c) : 0) -#else -//#define TRACE(x...) -#define ASSERT(c) -#endif - -#define DEVNAME 32 - -#define TDX_PCI_ID 0x20001023 // Trident 4D Wave/DX -#define xDX_PCI_ID 0x20000003 // Hypotese? -#define TNX_PCI_ID 0x20011023 // Trident 4D Wave/NX -#define ALI_PCI_ID 0x545110b9 // Acer Labs 5451 Audio -#define SPA_PCI_ID 0x70181039 // SiS PCI Audio - -typedef struct _card_type -{ - union _ids - { - uint32 chip_id; - struct { - uint16 vendor_id; - uint16 card_id; - } ids; - } ids; - char chip_name[DEVNAME]; -} card_type; - -#define DO_PCM 1 -#define DO_MIDI 0 - -//#define USE_IO_REGS 0 -extern bool use_io_regs; - -typedef struct _midi_dev { - struct _sis7018_dev *card; - void * driver; - void * cookie; - int32 count; - char name[64]; -} midi_dev; - -/* channel registers */ -typedef struct _sis7018_ch { - int32 cso, alpha, fms, fmc, ec; - int32 lba; - int32 eso, delta; - int32 rvol, cvol; - int32 gvsel, pan, vol, ctrl; - int32 active/*:1, was_active:1*/; - int index/*, bufhalf*/; - struct _sis7018_dev *card; - size_t mem_size; /* size of low memory */ - vuchar * mem_ptr; - vuchar * mem_phys; /* physical address */ - area_id areaid; /* area pointing to low memory */ - - vuchar * wr_1; - vuchar * wr_2; - vuchar * wr_cur; -#if DEBUG - vuchar * wr_cur_prv; - bigtime_t time_prv; - bool prevInt; -#endif - size_t wr_size; - - int32 wr_lock; - int wr_silence; - int32 write_waiting; - sem_id write_sem; - size_t was_written; - uint32 wr_skipped; - sem_id wr_entry; - bigtime_t wr_time; - uint64 wr_total; -// sem_id wr_time_sem; -// int32 wr_time_wait; -} sis7018_ch; - -typedef struct { - struct _sis7018_dev * card; - char name[DEVNAME]; - int32 open_count; - int32 open_mode; - sem_id init_sem; - - sem_id old_cap_sem; - sem_id old_play_sem; - - char oldname[DEVNAME]; - struct _sis7018_ch play_channel; -} pcm_dev; - -typedef struct _ac97_codec -{ - bool wide_main_gain; -} ac97_codec; - -typedef struct _sis7018_dev -{ - char name[DEVNAME]; /* used for resources */ - int32 hardware; /* spinlock */ -//#if(USE_IO_REGS) - int io_base; /* offset to port */ -//#else - void *regs_mem_base; -//#endif - int32 inth_count; -/* int dma_base; - size_t low_size;*/ /* size of low memory */ -/* vuchar * low_mem; - vuchar * low_phys;*/ /* physical address */ -// area_id map_low; /* area pointing to low memory */ -//#if(!USE_IO_REGS) - area_id regs_area; -//#endif - pci_info info; - midi_dev midi; -/* joy_dev joy;*/ - pcm_dev pcm; -/* mux_dev mux; - mixer_dev mixer;*/ - card_type *type; - ac97_codec ac97; -} sis7018_dev; - -extern int32 num_cards; -extern sis7018_dev cards[]; - -/*uint32 io_rd(sis7018_dev *dev, int offset, int size); -void io_wr(sis7018_dev *dev, int offset, uint32 value, int size); -int rd_cd(sis7018_dev *dev, int regno); -int wr_cd(sis7018_dev *dev, int regno, uint32 data); - -void increment_interrupt_handler(sis7018_dev * card); -void decrement_interrupt_handler(sis7018_dev * card); -*/ -#endif //_SIS7018_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.rdef b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.rdef deleted file mode 100644 index dda3560e09..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.rdef +++ /dev/null @@ -1,54 +0,0 @@ - -resource(101, "BEOS:L:STD_ICON") #'ICON' array { - $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF3F7E3DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E28FFFFFFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E28FFFFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E27FFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3DFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3E5FDFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3E5F3E9301FFFFFFFFFFFFFFFFFF" - $"FFFFFF3F3F3F3F3F3F7E3E5F3E5F3F3F3F3E937E3E5F403F3F3F3F3FFFFFFFFF" - $"FFFF3FFAFAFAFAFAFA3F7E3E5F1FFAFAFA3F3E5F3E3FFCFAFAFAFAFA1FFFFFFF" - $"FF3FFAFAFAFAFAFAFAFA3F7E3E3FFBFAFA3F257E3FFAFAFAFAFAFAFAFA3FFFFF" - $"3FFAFAFA3F3F3F3FFAFAFA3F7E1FFAFAFA1FDD3FFAFAFA3F3F3F3FFAFAFA3FFF" - $"3FFAFA3F252525253F3F3F3F24253F3F3F25253FFAFA3F252525253F3F3F3F25" - $"3FFAFA3F257E3E5FDD242525257E252525253E3FFCFA1F257F3E5EDD25242525" - $"3FFAFAFA3F3F7E3E5F3E5F3E93403F3F3F3F7E1FFAFAFA3F3F3E937E3E28FFFF" - $"253FFAFAFAFA3F3F7E3E5F3E5F3FFAFAFA3FDC263FFAFAFAFA3F3F7E3E5F3DFF" - $"FF253F3FFAFAFAFA3F3F7E3E5F3FFAFAFA3FDD7E253F3FFAFAFAFA3F3F3E5F3D" - $"FFFF25253F3FFAFAFAFA3F7E3E3FFBFAFA3F247F3E21253F3FFAFAFAFA3F01FF" - $"FFFFFF3F25253F3FFAFAFA3F7E1FFAFAFA3FDD7E3E5F3E21253F3FFAFAFA3FFF" - $"FFFFFFFF3F7E26253FFAFA3F253FFAFAFA3F243E5F3E5F3E93242540FAFA3F25" - $"3F3F3F3FFF3F7E3E3FFBFA3F253FFAFAFA3F241F3F3F3F3E5F3E5F3FFAFA3FDC" - $"3FFAFAFA3F3F3F3FFAFAFA3F253FFAFAFA3F253FFAFAFA3F3F3F3FFAFAFA3F25" - $"253FFAFAFAFAFAFAFAFA3F25253FFAFAFA3F25241FFAFAFAFAFAFAFAFA3F2525" - $"FF253FFAFAFAFAFA3F3F25257E1FFAFAFA3FDC7F253FFAFAFAFAFA3F3F2524FF" - $"FFFF253F3F3F3F3F2525257E3E3F3F3F3F3F227E3E221F3F3F3F3F252525FFFF" - $"FFFFFF252525252425FF3F3F7F2425252525243E5F3E222524252525FFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3DE0FFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E27FFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E28FFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E28FFFFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F7E3DFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" -}; - -resource(101, "BEOS:M:STD_ICON") #'MICN' array { - $"FFFFFFFFFFFFFFB500FFFFFFFFFFFFFF" - $"FFFFFFFFFFFF19947F01FFFFFFFFFFFF" - $"FFFFFFFFFF19943E5F7F01FFFFFFFFFF" - $"FFFFFFFF18947E3E5F3E7E3DFFFFFFFF" - $"FF63FCFD687E6EFC687E74FCFDFC07FF" - $"63FAFDFCFA6867FAFCB4E5FBFDFBFB07" - $"FCFDDDDCAD12248DD487FA10DCB310D3" - $"17FAFC687E3E6CFDFED4FBFB42947F00" - $"29ADFCFAFD9468FAFDDDB418FBFB4229" - $"B807B410E5FD8DFAFC7E7F7EAE15FA10" - $"FEFC186DFBFCA7FAFD8EFD626E19FA11" - $"D4FBFAFAFCB487FAFC2468FAFAFB6226" - $"FFB5A78D278DB4A78EDC7E11ADCE27FF" - $"FFFFFFFFFF07417E7F3EDCFFFFFFFFFF" - $"FFFFFFFFFFFF07617E3BFFFFFFFFFFFF" - $"FFFFFFFFFFFFFFD6DEFFFFFFFFFFFFFF" -}; diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.settings.sample b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.settings.sample deleted file mode 100644 index 5e2c792449..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.settings.sample +++ /dev/null @@ -1,37 +0,0 @@ -# -# The sample sis7018 driver settings file -# -# Rename it to sis7018 and put into -# /boot/home/config/settings/kernel/drivers/ -# After restarting Media Services the new settings will works. - -# Debug output - this is a possibility to view some kind of development related -# information - error and warning messages etc. - -# debug_output - activates debug output. The debug builds has debug output -# activated by default and this key has no effect on it. The release builds requires -# to activate this if you want to see debug messages in syslog or in private log file. -# -# debug_output true - -# debug_output_in_file - activates writing of debug messages into private log file. -# The name of this file is /boot/home/sis7018.log. If this key is set to true - no messages -# will be written into syslog. -# -# debug_output_in_file true - -# debug_output_file_rewrite - activates rewriting of private log file on -# calling driver_init() syscall. By default this set in false. -# -# debug_output_file_rewrite false - -# debug_trace_ac97 - activates more detailed logging of AC'97 operations. -# Do not use it with syslog output - you'll get only messages -# because BeOS's syslog daemon don't like a lot of messages in short time -# -# debug_trace_ac97 true - -# use_io_registers - switches driver from "memory" scheme to "io registers" -# scheme. This key is usefull for testers. Don't use it if you don't need it. -# -# use_io_registers true diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.c b/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.c deleted file mode 100644 index 816206512c..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright (c) 2002-2003 by Siarzuk Zharski - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ -#include //sprintf -#include - -#include "sis7018.h" -#include "sis7018hw.h" -#include "t4dwave.h" -#include "ac97.h" -#include "pcm.h" - -pci_module_info* pci; - -#define MIN_MEMORY_SIZE 0x2000 -#define PCHANNEL_ID 0x00 - -int intrs; - -uint32 hw_read(sis7018_dev *dev, int offset, int size) -{ - uint32 ret = 0xffffffff; - if(use_io_regs){ - switch(size){ - case 1: ret = (*pci->read_io_8)(dev->io_base + offset); break; - case 2: ret = (*pci->read_io_16)(dev->io_base + offset); break; - case 4: ret = (*pci->read_io_32)(dev->io_base + offset); break; - default: break; - } - } - else{ - switch(size){ - case 1: ret = *(int8 *)((char *)dev->regs_mem_base + offset); break; - case 2: ret = *(int16 *)((char *)dev->regs_mem_base + offset); break; - case 4: ret = *(int32 *)((char *)dev->regs_mem_base + offset); break; - default: break; - } - } - // TRACE("tr_rd off=%x ret=%lx\n", offset, ret); - return ret; -} - -void hw_write(sis7018_dev *dev, int offset, uint32 value, int size) -{ - //TRACE("tr_wr off=%x value = %lx\n", offset, value); - if(use_io_regs){ - switch(size){ - case 1: (*pci->write_io_8)(dev->io_base + offset, (uint8) value); break; - case 2: (*pci->write_io_16)(dev->io_base + offset, (uint16) value); break; - case 4: (*pci->write_io_32)(dev->io_base + offset, value); break; - default: break; - } - } - else{ - switch(size){ - case 1: *(int8 *)((char *)dev->regs_mem_base + offset) = (int8)value; break; - case 2: *(int16 *)((char *)dev->regs_mem_base + offset) = (int16)value; break; - case 4: *(int32 *)((char *)dev->regs_mem_base + offset) = (int32)value; break; - default: break; - } - } -} - -static void hw_clrint(sis7018_ch *ch) -{ - sis7018_dev *dev = ch->card; - int bank, chan; - - bank = (ch->index & 0x20) ? 1 : 0; - chan = ch->index & 0x1f; - hw_write(dev, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 1 << chan, 4); -} - -static void hw_enaint(sis7018_ch *ch, int enable) -{ - sis7018_dev *dev = ch->card; - int32 i, reg; - int bank, chan; - cpu_status cp; - - cp = disable_interrupts(); - acquire_spinlock(&dev->hardware); - - bank = (ch->index & 0x20) ? 1 : 0; - chan = ch->index & 0x1f; - reg = bank? TR_REG_INTENB : TR_REG_INTENA; - - i = hw_read(dev, reg, 4); - i &= ~(1 << chan); - i |= (enable? 1 : 0) << chan; - - hw_clrint(ch); - hw_write(dev, reg, i, 4); - - release_spinlock(&dev->hardware); - restore_interrupts(cp); -} - -static void hw_selch(sis7018_ch *ch) -{ - sis7018_dev *dev = ch->card; - int32 i; - - i = hw_read(dev, TR_REG_CIR, 4); - i &= ~TR_CIR_MASK; - i |= ch->index & 0x3f; - hw_write(dev, TR_REG_CIR, i, 4); -} - -static void hw_startch(sis7018_ch *ch) -{ - sis7018_dev *dev = ch->card; - int bank, chan; - - bank = (ch->index & 0x20) ? 1 : 0; - chan = ch->index & 0x1f; - hw_write(dev, bank? TR_REG_STARTB : TR_REG_STARTA, 1 << chan, 4); -} - -static void hw_stopch(sis7018_ch *ch) -{ - sis7018_dev *dev = ch->card; - int bank, chan; - - bank = (ch->index & 0x20) ? 1 : 0; - chan = ch->index & 0x1f; - hw_write(dev, bank? TR_REG_STOPB : TR_REG_STOPA, 1 << chan, 4); -} - -static void hw_wrch(sis7018_ch *ch) -{ - sis7018_dev *dev = ch->card; - int32 cr[TR_CHN_REGS], i; - cpu_status cp; - - ch->gvsel &= 0x00000001; - ch->fmc &= 0x00000003; - ch->fms &= 0x0000000f; - ch->ctrl &= 0x0000000f; - ch->pan &= 0x0000007f; - ch->rvol &= 0x0000007f; - ch->cvol &= 0x0000007f; - ch->vol &= 0x000000ff; - ch->ec &= 0x00000fff; - ch->alpha &= 0x00000fff; - ch->delta &= 0x0000ffff; - ch->lba &= 0x3fffffff; - - cr[1]=ch->lba; - cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol); - cr[4]=(ch->gvsel<<31) | (ch->pan<<24) | (ch->vol<<16) | (ch->ctrl<<12) | (ch->ec); - - switch (ch->card->type->ids.chip_id) - { - case SPA_PCI_ID: - case ALI_PCI_ID: - case TDX_PCI_ID: - case xDX_PCI_ID: - ch->cso &= 0x0000ffff; - ch->eso &= 0x0000ffff; - cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms); - cr[2]=(ch->eso<<16) | (ch->delta); - break; - case TNX_PCI_ID: - ch->cso &= 0x00ffffff; - ch->eso &= 0x00ffffff; - cr[0]=((ch->delta & 0xff)<<24) | (ch->cso); - cr[2]=((ch->delta>>8)<<24) | (ch->eso); - cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14); - break; - } - cp = disable_interrupts(); - acquire_spinlock(&dev->hardware); - - hw_selch(ch); - for (i=0; ihardware); - restore_interrupts(cp); -} - -void hw_rdch(sis7018_ch *ch) -{ - sis7018_dev *dev = ch->card; - int32 cr[5], i; - cpu_status cp; - - cp = disable_interrupts(); - acquire_spinlock(&dev->hardware); - - hw_selch(ch); - for (i=0; i<5; i++) - cr[i]=hw_read(dev, TR_REG_CHNBASE+(i<<2), 4); - - release_spinlock(&dev->hardware); - restore_interrupts(cp); - - ch->lba= (cr[1] & 0x3fffffff); - ch->fmc= (cr[3] & 0x0000c000) >> 14; - ch->rvol= (cr[3] & 0x00003f80) >> 7; - ch->cvol= (cr[3] & 0x0000007f); - ch->gvsel= (cr[4] & 0x80000000) >> 31; - ch->pan= (cr[4] & 0x7f000000) >> 24; - ch->vol= (cr[4] & 0x00ff0000) >> 16; - ch->ctrl= (cr[4] & 0x0000f000) >> 12; - ch->ec= (cr[4] & 0x00000fff); - - switch(ch->card->type->ids.chip_id) - { - case SPA_PCI_ID: - case ALI_PCI_ID: - case TDX_PCI_ID: - case xDX_PCI_ID: - ch->cso= (cr[0] & 0xffff0000) >> 16; - ch->alpha= (cr[0] & 0x0000fff0) >> 4; - ch->fms= (cr[0] & 0x0000000f); - ch->eso= (cr[2] & 0xffff0000) >> 16; - ch->delta= (cr[2] & 0x0000ffff); - break; - case TNX_PCI_ID: - ch->cso= (cr[0] & 0x00ffffff); - ch->eso= (cr[2] & 0x00ffffff); - ch->delta= ((cr[2] & 0xff000000) >> 16) | ((cr[0] & 0xff000000) >> 24); - ch->alpha= (cr[3] & 0xfff00000) >> 20; - ch->fms= (cr[3] & 0x000f0000) >> 16; - break; - } -} - -status_t hw_pchannel_init(pcm_dev *dev) -{ - char name_buf[256]; - sis7018_ch *ch = &dev->play_channel; - ch->index = PCHANNEL_ID; - hw_pchannel_setblocksize(dev, 8192); - ch->ctrl = 0x0f; // 16-bit stereo signed + loop mode enabled - ch->delta = (48000 << 12 ) / 48000; - ch->card = dev->card; - ch->areaid=-1; - - ch->wr_lock = 0; - ch->write_waiting = 0; - sprintf(name_buf, "WS:%s", dev->name); - name_buf[B_OS_NAME_LENGTH-1] = 0; - ch->write_sem = create_sem(0, name_buf); - if (ch->write_sem < B_OK) - return ch->write_sem; - - set_sem_owner(ch->write_sem, B_SYSTEM_TEAM); - name_buf[0] = 'W'; name_buf[1] = 'E'; - ch->wr_entry = create_sem(1, name_buf); - if (ch->wr_entry < B_OK){ - delete_sem(ch->write_sem); - return ch->wr_entry; - } - set_sem_owner(ch->wr_entry, B_SYSTEM_TEAM); - ch->wr_time = 0; - return B_OK; -} - -void hw_pchannel_free(pcm_dev *dev) -{ - sis7018_ch *ch = &dev->play_channel; - if(ch->areaid >= 0){ - delete_area(ch->areaid); - ch->areaid = -1; - - delete_sem(ch->write_sem); - delete_sem(ch->wr_entry); - ch->write_sem = -1; - ch->wr_entry = -1; - } -} - -void hw_start(pcm_dev *dev) -{ - sis7018_ch *ch = &dev->play_channel; - - if(ch->active) - return; - - /* start out with a clean slate */ - TRACE("hw_start()\n"); -/* if (port->config.format == 0x11) - { - memset((void*)port->card->low_mem, 0x80, port->config.play_buf_size + - port->config.rec_buf_size); - } - else {*/ - - // TODO? - // memset((void *)port->card->low_mem, 0, port->config.play_buf_size + - // port->config.rec_buf_size); - //} - - ch->wr_cur = ch->wr_2; - ch->wr_silence = ch->mem_size; - ch->was_written = 0; - ch->wr_total = 0; - - ch->fmc = 3; - ch->fms = 0; - ch->ec = 0; - ch->alpha = 0; - ch->lba = (int32)ch->mem_phys; - ch->cso = 0; - ch->eso = ch->mem_size/(sizeof(int16)*2)-1; - ch->rvol = ch->cvol = 0x7f; - ch->gvsel = 0; - ch->pan = 0; - ch->vol = 0; - - hw_wrch(ch); - hw_enaint(ch, 1); - hw_startch(ch); - - ch->active = 1; -} - -void hw_stop(pcm_dev *dev) -{ - sis7018_ch *ch = &dev->play_channel; - if(!ch->active) - return; - - hw_stopch(ch); - ch->active = 0; -} - -static int32 hw_interrupt_handler(void * data) -{ - int32 active, mask, bufhalf, chnum, intsrc; - sis7018_dev *card = (sis7018_dev *)data; - sis7018_ch *ch; - int32 handled = B_UNHANDLED_INTERRUPT; - intrs++; - - acquire_spinlock(&card->hardware); - intsrc = hw_read(card, TR_REG_MISCINT, 4); - -#if DO_PCM - if (intsrc & TR_INT_ADDR){ - chnum = PCHANNEL_ID; - mask = 0x00000001 << PCHANNEL_ID; - active = hw_read(card, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4); - bufhalf = hw_read(card, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4); - if (active & mask){ - ch = &card->pcm.play_channel; - if(playback_interrupt(ch, (bufhalf & mask))) - handled = B_INVOKE_SCHEDULER; - else - handled = B_HANDLED_INTERRUPT; - } - hw_write(card, (chnum <= 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, active, 4); - } -#endif -#if DO_MIDI - ssssssss - /*if (status & 0x80) { - if (midi_interrupt(card)) { - handled = B_INVOKE_SCHEDULER; - } else { - handled = B_HANDLED_INTERRUPT; - } - }*/ - handled = B_HANDLED_INTERRUPT; -#endif - - release_spinlock(&card->hardware); - return handled; -} - -void hw_increment_interrupt_handler(sis7018_dev * card) -{ - TRACE("hw_increment_interrupt_handler()\n"); - if (atomic_add(&card->inth_count, 1) == 0){ - TRACE("intline %d int %p\n", card->info.u.h0.interrupt_line, hw_interrupt_handler); - install_io_interrupt_handler(card->info.u.h0.interrupt_line, hw_interrupt_handler, card, 0); - } -} - -void hw_decrement_interrupt_handler(sis7018_dev * card) -{ - TRACE("hw_decrement_interrupt_handler()\n"); - if (atomic_add(&card->inth_count, -1) == 1){ - TRACE("remove_io_interrupt_handler()\n"); - remove_io_interrupt_handler(card->info.u.h0.interrupt_line, hw_interrupt_handler, card); - } -} - -status_t hw_initialize(sis7018_dev *card) -{ - status_t err = B_OK; - - cpu_status cp = disable_interrupts(); - acquire_spinlock(&card->hardware); - - switch (card->type->ids.chip_id){ - case SPA_PCI_ID: - hw_write(card, SPA_REG_GPIO, 0, 4); - hw_write(card, SPA_REG_CODECST, SPA_RST_OFF, 4); - break; - case TDX_PCI_ID: - case xDX_PCI_ID: - hw_write(card, TDX_REG_CODECST, TDX_CDC_ON, 4); - break; - case TNX_PCI_ID: - hw_write(card, TNX_REG_CODECST, TNX_CDC_ON, 4); - break; - } - - hw_write(card, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4); - - release_spinlock(&card->hardware); - restore_interrupts(cp); - - err |= ac97init(card); - - return err; -} - -void hw_dump_device(int card_id) -{ - kprintf("interrupt handler called: %d\n", intrs); -} - -void hw_dump_pci_info(int card_id) -{ - kprintf("dump_pci_info is not yet implemented.\n"); -} - -void hw_dump_pcm_device(int card_id) -{ - kprintf("dump_pcm_device is not yet implemented.\n"); -} - -void hw_dump_midi_device(int card_id) -{ - kprintf("dump_midi_device is not yet implemented.\n"); -} - -static void hw_dump_channel(sis7018_ch *ch) -{ - kprintf("Pointer : %p\n", ch); - kprintf(" cso:%8lx, alpha:%8lx, fms:%8lx, fmc:%8lx, ec:%lx\n", - ch->cso, ch->alpha, ch->fms, ch->fmc, ch->ec); - kprintf(" lba:%8lx, eso:%8lx, delta:%8lx, rvol:%8lx, cvol:%lx\n", - ch->lba, ch->eso, ch->delta, ch->rvol, ch->cvol); - kprintf("gvsel:%8lx, pan:%8lx, vol:%8lx, ctrl:%8lx, active:%x\n", - ch->gvsel, ch->pan, ch->vol, ch->ctrl, (int)ch->active); - kprintf("index:%8x, card:0x%8p, mem_ptr:0x%8p, mem_size:%8lx, mem_phys:0x%8p\n", - ch->index, ch->card, ch->mem_ptr, ch->mem_size, ch->mem_phys); - kprintf("\n"); -} - -void hw_dump_play_channel(int card_id) -{ - sis7018_ch ch; - memcpy(&ch, &cards[card_id].pcm.play_channel, sizeof(sis7018_ch)); - kprintf("Dumping play channel information:\n"); - kprintf(" - cached:\n"); - hw_dump_channel(&ch); - kprintf(" - readed from hardware:\n"); - hw_rdch(&ch); - hw_dump_channel(&ch); -} - -static status_t hw_find_memory(sis7018_ch *ch, size_t blocksize) -{ - size_t low_size = (blocksize * 2+(B_PAGE_SIZE-1))&~(B_PAGE_SIZE-1); - physical_entry where; - size_t trysize; - area_id curarea; - void * addr; - char name[DEVNAME]; - - sprintf(name, "%s_area", ch->card->name); - if (low_size < MIN_MEMORY_SIZE) - low_size = MIN_MEMORY_SIZE; - trysize = low_size; - - curarea = find_area(name); - if (curarea != B_NAME_NOT_FOUND){ - TRACE("delete previously allocated area\n"); - delete_area(curarea); - curarea = -1; - } - - TRACE("allocating new area\n"); - - curarea = create_area(name, &addr, B_ANY_KERNEL_ADDRESS, - trysize, B_LOMEM, B_READ_AREA | B_WRITE_AREA); - TRACE("create_area(%lx) returned %lx logical %p\n", trysize, curarea, addr); - - if (curarea < 0) - goto oops; - - if (get_memory_map(addr, low_size, &where, 1) < 0){ - delete_area(curarea); - curarea = B_ERROR; - goto oops; - } - TRACE("physical %#" B_PRIxPHYSADDR "\n", where.address); - if ((where.address & ~(phys_addr_t)0xffffff) != 0){ - delete_area(curarea); - curarea = B_ERROR; - goto oops; - } - if (((where.address + low_size) & ~(phys_addr_t)0xffffff) != 0){ - delete_area(curarea); - curarea = B_ERROR; - goto oops; - } - /* hey, it worked! */ - if (trysize > low_size) /* don't waste */ - resize_area(curarea, low_size); - -oops: - if (curarea < 0){ - TRACE("failed to create area\n"); - return curarea; - } -//a_o_k: - TRACE("successfully created area!\n"); - - ch->mem_size = low_size; - ch->mem_ptr = addr; - ch->mem_phys = (vuchar *)(addr_t)where.address; - - ch->wr_1 = ch->mem_ptr; - ch->wr_2 = ch->wr_1+ch->mem_size/2; - ch->wr_size = ch->mem_size/2; - - ch->areaid = curarea; - - if(ch->active){ - hw_stop(&ch->card->pcm); - hw_start(&ch->card->pcm); - } - - return B_OK; -} - -size_t hw_pchannel_setblocksize(pcm_dev *dev, size_t blocksize) -{ - sis7018_ch *ch = &dev->play_channel; - - if(ch->mem_size/2 != blocksize){ - if(ch->areaid >= 0){ - TRACE("delete area on resize\n"); - delete_area(ch->areaid); - ch->areaid = -1; - } - //TODO : error cheking. - hw_find_memory(ch, blocksize); - } - return blocksize; -} diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.h b/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.h deleted file mode 100644 index a192488396..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright (c) 2002-2003 by Siarzuk Zharski - * - * This file may be used under the terms of the BSD License - * See the file "License" for details. - */ -#ifndef _SIS7018HW_H_ -#define _SIS7018HW_H_ - -#ifndef _SOUND_H -#include "sound.h" -#endif - -extern pci_module_info* pci; - -uint32 hw_read(sis7018_dev *dev, int offset, int size); -void hw_write(sis7018_dev *dev, int offset, uint32 value, int size); -status_t hw_pchannel_init(pcm_dev *dev); -void hw_pchannel_free(pcm_dev *dev); -size_t hw_pchannel_setblocksize(pcm_dev *dev, size_t blocksize); -void hw_start(pcm_dev *dev); -void hw_stop(pcm_dev *dev); -void hw_increment_interrupt_handler(sis7018_dev * card); -void hw_decrement_interrupt_handler(sis7018_dev * card); -status_t hw_initialize(sis7018_dev *card); -void hw_rdch(sis7018_ch *ch); - -void hw_dump_device(int card_id); -void hw_dump_pci_info(int card_id); -void hw_dump_pcm_device(int card_id); -void hw_dump_midi_device(int card_id); -void hw_dump_play_channel(int card_id); - -#endif //_SIS7018HW_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sound.h b/src/add-ons/kernel/drivers/audio/sis7018/sound.h deleted file mode 100644 index 4f6b192f8b..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/sound.h +++ /dev/null @@ -1,94 +0,0 @@ -/* ++++++++++ - Data structures and control calls for using the sound driver -+++++ */ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright permissions see above. - * - * Portion copyright (c) 2002-2003 by Siarzuk Zharski - */ -#ifndef _SOUND_H -#define _SOUND_H - -#ifndef _DRIVERS_H -#include -#endif - -enum adc_source { - line=0, aux1, mic, loopback -}; - -enum sample_rate { - kHz_8_0 = 0, kHz_5_51, kHz_16_0, kHz_11_025, kHz_27_42, kHz_18_9, - kHz_32_0, kHz_22_05, kHz_37_8 = 9, kHz_44_1 = 11, kHz_48_0, kHz_33_075, - kHz_9_6, kHz_6_62 -}; - -enum sample_format { - linear_8bit_unsigned_mono = 0, linear_8bit_unsigned_stereo, - ulaw_8bit_companded_mono, ulaw_8bit_companded_stereo, - linear_16bit_little_endian_mono, linear_16bit_little_endian_stereo, - alaw_8bit_companded_mono, alaw_8bit_companded_stereo, - sample_format_reserved_1, sample_format_reserved_2, - adpcm_4bit_mono, adpcm_4bit_stereo, - linear_16bit_big_endian_mono, linear_16bit_big_endian_stereo, - sample_format_reserved_3, sample_format_reserved_4 -}; - -struct channel { - enum adc_source adc_source; /* adc input source */ - char adc_gain; /* 0..15 adc gain, in 1.5 dB steps */ - char mic_gain_enable; /* non-zero enables 20 dB MIC input gain */ - char aux1_mix_gain; /* 0..31 aux1 mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */ - char aux1_mix_mute; /* non-zero mutes aux1 mix */ - char aux2_mix_gain; /* 0..31 aux2 mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */ - char aux2_mix_mute; /* non-zero mutes aux2 mix */ - char line_mix_gain; /* 0..31 line mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */ - char line_mix_mute; /* non-zero mutes line mix */ - char dac_attn; /* 0..61 dac attenuation, in -1.5 dB steps */ - char dac_mute; /* non-zero mutes dac output */ -}; - -typedef struct sound_setup { - struct channel left; /* left channel setup */ - struct channel right; /* right channel setup */ - enum sample_rate sample_rate; /* sample rate */ - enum sample_format playback_format; /* sample format for playback */ - enum sample_format capture_format; /* sample format for capture */ - char dither_enable; /* non-zero enables dither on 16 => 8 bit */ - char loop_attn; /* 0..64 adc to dac loopback attenuation, in -1.5 dB steps */ - char loop_enable; /* non-zero enables loopback */ - char output_boost; /* zero (2.0 Vpp) non-zero (2.8 Vpp) output level boost */ - char highpass_enable;/* non-zero enables highpass filter in adc */ - char mono_gain; /* 0..64 mono speaker gain */ - char mono_mute; /* non-zero mutes speaker */ -} sound_setup; - - -/* ----- - control opcodes for sound driver ------ */ - -enum { - SOUND_GET_PARAMS = B_DEVICE_OP_CODES_END, - SOUND_SET_PARAMS, /* 10000 */ - SOUND_SET_PLAYBACK_COMPLETION_SEM, - SOUND_SET_CAPTURE_COMPLETION_SEM, - SOUND_GET_PLAYBACK_TIMESTAMP, /* 10003 */ - SOUND_GET_CAPTURE_TIMESTAMP, - SOUND_DEBUG_ON, - SOUND_DEBUG_OFF, /* 10006 */ - SOUND_UNSAFE_WRITE, - SOUND_UNSAFE_READ, - SOUND_LOCK_FOR_DMA, /* 10009 */ - SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE, - SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE, - SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE, /* 10012 */ - SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE -}; - -#endif diff --git a/src/add-ons/kernel/drivers/audio/sis7018/t4dwave.h b/src/add-ons/kernel/drivers/audio/sis7018/t4dwave.h deleted file mode 100644 index 4dc4e78064..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/t4dwave.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 1999 Cameron Grant - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 AUTHOR 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 AUTHOR 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. - * - * $FreeBSD: src/sys/dev/sound/pci/t4dwave.h,v 1.3.2.3 2001/08/30 23:10:50 greid Exp $ - */ -/* - * This file is a part of SiS 7018 BeOS driver project. - * Copyright permissions see above. - * - * Portion copyright (c) 2002 by Siarzuk Zharski - * - * $Source: /cvsroot/sis4be/sis7018/t4dwave.h,v $ - * $Author: zharik $ - * $Revision: 1.4 $ - * $Date: 2004/06/24 15:47:40 $ - */ -#ifndef _T4DWAVE_REG_H -#define _T4DWAVE_REG_H - -#define TR_REG_CIR 0xa0 -#define TR_CIR_MASK 0x0000003f -#define TR_CIR_ADDRENA 0x00001000 -#define TR_CIR_MIDENA 0x00002000 -#define TR_REG_MISCINT 0xb0 -#define TR_INT_ADDR 0x00000020 -#define TR_INT_SB 0x00000004 - -#define TR_REG_DMAR0 0x00 -#define TR_REG_DMAR4 0x04 -#define TR_REG_DMAR11 0x0b -#define TR_REG_DMAR15 0x0f -#define TR_REG_SBR4 0x14 -#define TR_REG_SBR5 0x15 -#define TR_SB_INTSTATUS 0x82 -#define TR_REG_SBR9 0x1e -#define TR_REG_SBR10 0x1f -#define TR_REG_SBBL 0xc0 -#define TR_REG_SBCTRL 0xc4 -#define TR_REG_SBDELTA 0xac - -#define TR_CDC_DATA 16 -#define TDX_REG_CODECWR 0x40 -#define TDX_REG_CODECRD 0x44 -#define TDX_CDC_RWSTAT 0x00008000 -#define TDX_REG_CODECST 0x48 -#define TDX_CDC_SBCTRL 0x40 -#define TDX_CDC_ACTIVE 0x20 -#define TDX_CDC_READY 0x10 -#define TDX_CDC_ADCON 0x08 -#define TDX_CDC_DACON 0x02 -#define TDX_CDC_RESET 0x01 -#define TDX_CDC_ON (TDX_CDC_ADCON|TDX_CDC_DACON) - -#define SPA_REG_CODECRD 0x44 -#define SPA_REG_CODECWR 0x40 -#define SPA_REG_CODECST 0x48 -#define SPA_RST_OFF 0x0f0000 -#define SPA_REG_GPIO 0x48 -#define SPA_CDC_RWSTAT 0x00008000 - -#define TNX_REG_CODECWR 0x44 -#define TNX_REG_CODEC1RD 0x48 -#define TNX_REG_CODEC2RD 0x4c -#define TNX_CDC_RWSTAT 0x00000c00 -#define TNX_CDC_SEC 0x00000100 -#define TNX_REG_CODECST 0x40 -#define TNX_CDC_READY2 0x40 -#define TNX_CDC_ADC2ON 0x20 -#define TNX_CDC_DAC2ON 0x10 -#define TNX_CDC_READY1 0x08 -#define TNX_CDC_ADC1ON 0x04 -#define TNX_CDC_DAC1ON 0x02 -#define TNX_CDC_RESET 0x01 -#define TNX_CDC_ON (TNX_CDC_ADC1ON|TNX_CDC_DAC1ON) - - -#define TR_REG_STARTA 0x80 -#define TR_REG_STOPA 0x84 -#define TR_REG_CSPF_A 0x90 -#define TR_REG_ADDRINTA 0x98 -#define TR_REG_INTENA 0xa4 - -#define TR_REG_STARTB 0xb4 -#define TR_REG_STOPB 0xb8 -#define TR_REG_CSPF_B 0xbc -#define TR_REG_ADDRINTB 0xd8 -#define TR_REG_INTENB 0xdc - -#define TR_REG_CHNBASE 0xe0 -#define TR_CHN_REGS 5 - -#endif diff --git a/src/add-ons/kernel/drivers/audio/sis7018/uninstall.sh b/src/add-ons/kernel/drivers/audio/sis7018/uninstall.sh deleted file mode 100644 index fe6aeee54f..0000000000 --- a/src/add-ons/kernel/drivers/audio/sis7018/uninstall.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -answer=`alert "Do you really want to uninstall the Sis 7018 driver?" "No" "Yes"` -if [ $answer == "No" ]; then - exit -fi - -rm ~/config/add-ons/kernel/drivers/bin/sis7018 -rm ~/config/settings/kernel/drivers/sis7018 -rm ~/config/add-ons/kernel/drivers/dev/audio/old/sis7018 - -alert "The SiS7018 driver has been removed. - -Restart your system now."