[HDAUDBUS]

- start implementing HDAUDIO Bus driver 
- based heavily on Haiku exellent driver 

svn path=/trunk/; revision=68311
This commit is contained in:
Johannes Anderwald 2015-06-29 17:03:33 +00:00
parent 7b665169ed
commit cf7fc816a1
7 changed files with 2135 additions and 0 deletions

View file

@ -3,5 +3,6 @@ add_subdirectory(backpln)
add_subdirectory(drivers)
add_subdirectory(drm)
add_subdirectory(filters)
add_subdirectory(hdaudbus)
add_subdirectory(legacy)
add_subdirectory(sysaudio)

View file

@ -0,0 +1,14 @@
set_cpp()
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
list(APPEND SOURCE
hdaudbus.cpp)
add_library(hdaudbus SHARED ${SOURCE})
set_module_type(hdaudbus kernelmodedriver)
target_link_libraries(hdaudbus libcntpr ${PSEH_LIB})
add_importlibs(hdaudbus ntoskrnl hal)
add_cd_file(TARGET hdaudbus DESTINATION reactos/system32/drivers FOR all)

View file

@ -0,0 +1,402 @@
/*
* Copyright 2007-2012, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar Adema, ithamar AT unet DOT nl
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef _HDA_H_
#define _HDA_H_
#ifndef __REACTOS__
#include <KernelExport.h>
#include <Drivers.h>
#include <PCI.h>
#include <PCI_x86.h>
#include <string.h>
#include <stdlib.h>
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
# define DEVFS_PATH_FORMAT "audio/multi/hda/%lu"
# include <multi_audio.h>
#else
# define DEVFS_PATH_FORMAT "audio/hmulti/hda/%lu"
# include <hmulti_audio.h>
#endif
#endif
#include "hda_controller_defs.h"
#include "hda_codec_defs.h"
#define MAX_CARDS 4
/* values for the class_sub field for class_base = 0x04 (multimedia device) */
#ifndef __HAIKU__
# define PCI_hd_audio 3
#endif
#define HDA_MAX_AUDIO_GROUPS 15
#define HDA_MAX_CODECS 15
#define HDA_MAX_STREAMS 16
#define MAX_CODEC_RESPONSES 16
#define MAX_CODEC_UNSOL_RESPONSES 16
#define MAX_INPUTS 32
#define MAX_IO_WIDGETS 8
#define MAX_ASSOCIATIONS 16
#define MAX_ASSOCIATION_PINS 16
#define STREAM_MAX_BUFFERS 10
#define STREAM_MIN_BUFFERS 2
enum {
STREAM_PLAYBACK,
STREAM_RECORD
};
struct hda_codec;
struct hda_stream;
struct hda_multi;
/*! This structure describes a single HDA compliant
controller. It contains a list of available streams
for use by the codecs contained, and the messaging queue
(verb/response) buffers for communication.
*/
#ifndef __REACTOS__
struct hda_controller {
struct pci_info pci_info;
int32 opened;
const char* devfs_path;
area_id regs_area;
vuint8* regs;
uint32 irq;
bool msi;
bool dma_snooping;
uint16 codec_status;
uint32 num_input_streams;
uint32 num_output_streams;
uint32 num_bidir_streams;
uint32 corb_length;
uint32 rirb_length;
uint32 rirb_read_pos;
uint32 corb_write_pos;
area_id corb_rirb_pos_area;
corb_t* corb;
rirb_t* rirb;
uint32* stream_positions;
hda_codec* codecs[HDA_MAX_CODECS + 1];
hda_codec* active_codec;
uint32 num_codecs;
hda_stream* streams[HDA_MAX_STREAMS];
sem_id buffer_ready_sem;
uint8 Read8(uint32 reg)
{
return *(regs + reg);
}
uint16 Read16(uint32 reg)
{
return *(vuint16*)(regs + reg);
}
uint32 Read32(uint32 reg)
{
return *(vuint32*)(regs + reg);
}
void Write8(uint32 reg, uint8 value)
{
*(regs + reg) = value;
}
void Write16(uint32 reg, uint16 value)
{
*(vuint16*)(regs + reg) = value;
}
void Write32(uint32 reg, uint32 value)
{
*(vuint32*)(regs + reg) = value;
}
void ReadModifyWrite8(uint32 reg, uint8 mask, uint8 value)
{
uint8 temp = Read8(reg);
temp &= ~mask;
temp |= value;
Write8(reg, temp);
}
void ReadModifyWrite16(uint32 reg, uint16 mask, uint16 value)
{
uint16 temp = Read16(reg);
temp &= ~mask;
temp |= value;
Write16(reg, temp);
}
void ReadModifyWrite32(uint32 reg, uint32 mask, uint32 value)
{
uint32 temp = Read32(reg);
temp &= ~mask;
temp |= value;
Write32(reg, temp);
}
};
/*! This structure describes a single stream of audio data,
which is can have multiple channels (for stereo or better).
*/
struct hda_stream {
uint32 id; /* HDA controller stream # */
uint32 offset; /* HDA I/O/B descriptor offset */
bool running;
spinlock lock; /* Write lock */
uint32 type;
hda_controller* controller;
uint32 pin_widget; /* PIN Widget ID */
uint32 io_widgets[MAX_IO_WIDGETS]; /* Input/Output Converter Widget ID */
uint32 num_io_widgets;
uint32 sample_rate;
uint32 sample_format;
uint32 num_buffers;
uint32 num_channels;
uint32 buffer_length; /* size of buffer in samples */
uint32 buffer_size; /* actual (aligned) size of buffer in bytes */
uint32 sample_size;
uint8* buffers[STREAM_MAX_BUFFERS];
/* Virtual addresses for buffer */
phys_addr_t physical_buffers[STREAM_MAX_BUFFERS];
/* Physical addresses for buffer */
volatile bigtime_t real_time;
volatile uint64 frames_count;
uint32 last_link_frame_position;
volatile int32 buffer_cycle;
uint32 rate, bps; /* Samplerate & bits per sample */
area_id buffer_area;
area_id buffer_descriptors_area;
phys_addr_t physical_buffer_descriptors; /* BDL physical address */
int32 incorrect_position_count;
bool use_dma_position;
uint8 Read8(uint32 reg)
{
return controller->Read8(HDAC_STREAM_BASE + offset + reg);
}
uint16 Read16(uint32 reg)
{
return controller->Read16(HDAC_STREAM_BASE + offset + reg);
}
uint32 Read32(uint32 reg)
{
return controller->Read32(HDAC_STREAM_BASE + offset + reg);
}
void Write8(uint32 reg, uint8 value)
{
*(controller->regs + HDAC_STREAM_BASE + offset + reg) = value;
}
void Write16(uint32 reg, uint16 value)
{
*(vuint16*)(controller->regs + HDAC_STREAM_BASE + offset + reg) = value;
}
void Write32(uint32 reg, uint32 value)
{
*(vuint32*)(controller->regs + HDAC_STREAM_BASE + offset + reg) = value;
}
};
struct hda_widget {
uint32 node_id;
uint32 num_inputs;
int32 active_input;
uint32 inputs[MAX_INPUTS];
uint32 flags;
hda_widget_type type;
uint32 pm;
struct {
uint32 audio;
uint32 output_amplifier;
uint32 input_amplifier;
} capabilities;
union {
struct {
uint32 formats;
uint32 rates;
} io;
struct {
} mixer;
struct {
uint32 capabilities;
uint32 config;
} pin;
} d;
};
struct hda_association {
uint32 index;
bool enabled;
uint32 pin_count;
uint32 pins[MAX_ASSOCIATION_PINS];
};
#endif
#define WIDGET_FLAG_OUTPUT_PATH 0x01
#define WIDGET_FLAG_INPUT_PATH 0x02
#define WIDGET_FLAG_WIDGET_PATH 0x04
/*! This structure describes a single Audio Function Group. An AFG
is a group of audio widgets which can be used to configure multiple
streams of audio either from the HDA Link to an output device (= playback)
or from an input device to the HDA link (= recording).
*/
#ifndef __REACTOS__
struct hda_audio_group {
hda_codec* codec;
hda_widget widget;
/* Multi Audio API data */
hda_stream* playback_stream;
hda_stream* record_stream;
uint32 widget_start;
uint32 widget_count;
uint32 association_count;
uint32 gpio;
hda_widget* widgets;
hda_association associations[MAX_ASSOCIATIONS];
hda_multi* multi;
};
/*! This structure describes a single codec module in the
HDA compliant device. This is a discrete component, which
can contain both Audio Function Groups, Modem Function Groups,
and other customized (vendor specific) Function Groups.
NOTE: ATM, only Audio Function Groups are supported.
*/
struct hda_codec {
uint16 vendor_id;
uint16 product_id;
uint8 major;
uint8 minor;
uint8 revision;
uint8 stepping;
uint8 addr;
uint32 quirks;
sem_id response_sem;
uint32 responses[MAX_CODEC_RESPONSES];
uint32 response_count;
sem_id unsol_response_sem;
thread_id unsol_response_thread;
uint32 unsol_responses[MAX_CODEC_UNSOL_RESPONSES];
uint32 unsol_response_read, unsol_response_write;
hda_audio_group* audio_groups[HDA_MAX_AUDIO_GROUPS];
uint32 num_audio_groups;
struct hda_controller* controller;
};
#define MULTI_CONTROL_FIRSTID 1024
#define MULTI_CONTROL_MASTERID 0
#define MULTI_MAX_CONTROLS 128
#define MULTI_MAX_CHANNELS 128
struct hda_multi_mixer_control {
hda_multi *multi;
int32 nid;
int32 type;
bool input;
uint32 mute;
uint32 gain;
uint32 capabilities;
int32 index;
multi_mix_control mix_control;
};
struct hda_multi {
hda_audio_group *group;
hda_multi_mixer_control controls[MULTI_MAX_CONTROLS];
uint32 control_count;
multi_channel_info chans[MULTI_MAX_CHANNELS];
uint32 output_channel_count;
uint32 input_channel_count;
uint32 output_bus_channel_count;
uint32 input_bus_channel_count;
uint32 aux_bus_channel_count;
};
/* driver.c */
extern device_hooks gDriverHooks;
extern pci_module_info* gPci;
extern pci_x86_module_info* gPCIx86Module;
extern hda_controller gCards[MAX_CARDS];
extern uint32 gNumCards;
/* hda_codec.c */
const char* get_widget_location(uint32 location);
hda_widget* hda_audio_group_get_widget(hda_audio_group* audioGroup, uint32 nodeID);
status_t hda_audio_group_get_widgets(hda_audio_group* audioGroup,
hda_stream* stream);
hda_codec* hda_codec_new(hda_controller* controller, uint32 cad);
void hda_codec_delete(hda_codec* codec);
/* hda_multi_audio.c */
status_t multi_audio_control(void* cookie, uint32 op, void* arg, size_t length);
/* hda_controller.c: Basic controller support */
status_t hda_hw_init(hda_controller* controller);
void hda_hw_stop(hda_controller* controller);
void hda_hw_uninit(hda_controller* controller);
status_t hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses,
uint32 count);
status_t hda_verb_write(hda_codec* codec, uint32 nid, uint32 vid, uint16 payload);
status_t hda_verb_read(hda_codec* codec, uint32 nid, uint32 vid, uint32 *response);
/* hda_controller.c: Stream support */
hda_stream* hda_stream_new(hda_audio_group* audioGroup, int type);
void hda_stream_delete(hda_stream* stream);
status_t hda_stream_setup_buffers(hda_audio_group* audioGroup,
hda_stream* stream, const char* desc);
status_t hda_stream_start(hda_controller* controller, hda_stream* stream);
status_t hda_stream_stop(hda_controller* controller, hda_stream* stream);
#endif
#endif /* _HDA_H_ */

View file

@ -0,0 +1,386 @@
/*
* Copyright 2007-2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar Adema, ithamar AT unet DOT nl
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef HDA_CODEC_H
#define HDA_CODEC_H
enum hda_widget_type {
WT_AUDIO_OUTPUT = 0,
WT_AUDIO_INPUT = 1,
WT_AUDIO_MIXER = 2,
WT_AUDIO_SELECTOR = 3,
WT_PIN_COMPLEX = 4,
WT_POWER = 5,
WT_VOLUME_KNOB = 6,
WT_BEEP_GENERATOR = 7,
WT_VENDOR_DEFINED = 15
};
enum pin_connectivity_type {
PIN_CONN_JACK,
PIN_CONN_NONE,
PIN_CONN_FIXED,
PIN_CONN_BOTH
};
enum pin_dev_type {
PIN_DEV_LINE_OUT = 0,
PIN_DEV_SPEAKER,
PIN_DEV_HEAD_PHONE_OUT,
PIN_DEV_CD,
PIN_DEV_SPDIF_OUT,
PIN_DEV_DIGITAL_OTHER_OUT,
PIN_DEV_MODEM_LINE_SIDE,
PIN_DEV_MODEM_HAND_SIDE,
PIN_DEV_LINE_IN,
PIN_DEV_AUX,
PIN_DEV_MIC_IN,
PIN_DEV_TELEPHONY,
PIN_DEV_SPDIF_IN,
PIN_DEV_DIGITAL_OTHER_IN,
PIN_DEV_RESERVED,
PIN_DEV_OTHER
};
/* Verb Helper Macro */
#define MAKE_VERB(cad, nid, vid, payload) \
(((cad) << 28) | ((nid) << 20) | (vid) | (payload))
/* Verb IDs */
#define VID_GET_PARAMETER 0xf0000
#define VID_GET_CONNECTION_SELECT 0xf0100
#define VID_SET_CONNECTION_SELECT 0x70100
#define VID_GET_CONNECTION_LIST_ENTRY 0xf0200
#define VID_GET_PROCESSING_STATE 0xf0300
#define VID_SET_PROCESSING_STATE 0x70300
#define VID_GET_COEFFICIENT_INDEX 0xd0000
#define VID_SET_COEFFICIENT_INDEX 0x50000
#define VID_GET_PROCESSING_COEFFICIENT 0xc0000
#define VID_SET_PROCESSING_COEFFICIENT 0x40000
#define VID_GET_AMPLIFIER_GAIN_MUTE 0xb0000
#define VID_SET_AMPLIFIER_GAIN_MUTE 0x30000
#define VID_GET_CONVERTER_FORMAT 0xa0000
#define VID_SET_CONVERTER_FORMAT 0x20000
#define VID_GET_CONVERTER_STREAM_CHANNEL 0xf0600
#define VID_SET_CONVERTER_STREAM_CHANNEL 0x70600
#define VID_GET_DIGITAL_CONVERTER_CONTROL 0xf0d00
#define VID_SET_DIGITAL_CONVERTER_CONTROL1 0x70d00
#define VID_SET_DIGITAL_CONVERTER_CONTROL2 0x70e00
#define VID_GET_POWER_STATE 0xf0500
#define VID_SET_POWER_STATE 0x70500
#define VID_GET_SDI_SELECT 0xf0400
#define VID_SET_SDI_SELECT 0x70400
#define VID_GET_PIN_WIDGET_CONTROL 0xf0700
#define VID_SET_PIN_WIDGET_CONTROL 0x70700
#define VID_GET_UNSOLRESP 0xF0800
#define VID_SET_UNSOLRESP 0x70800
#define VID_GET_PINSENSE 0xF0900
#define VID_SET_PINSENSE 0x70900
#define VID_GET_EAPDBTL_EN 0xF0C00
#define VID_SET_EAPDBTL_EN 0x70C00
#define VID_GET_VOLUME_KNOB_CONTROL 0xF0F00
#define VID_SET_VOLUME_KNOB_CONTROL 0x70F00
#define VID_GET_GPIDATA 0xF1000
#define VID_SET_GPIDATA 0x71000
#define VID_GET_GPIWAKE_EN 0xF1100
#define VID_SET_GPIWAKE_EN 0x71100
#define VID_GET_GPIUNSOL 0xF1200
#define VID_SET_GPIUNSOL 0x71200
#define VID_GET_GPISTICKY 0xF1300
#define VID_SET_GPISTICKY 0x71300
#define VID_GET_GPO_DATA 0xF1400
#define VID_SET_GPO_DATA 0x71400
#define VID_GET_GPIO_DATA 0xF1500
#define VID_SET_GPIO_DATA 0x71500
#define VID_GET_GPIO_EN 0xF1600
#define VID_SET_GPIO_EN 0x71600
#define VID_GET_GPIO_DIR 0xF1700
#define VID_SET_GPIO_DIR 0x71700
#define VID_GET_GPIOWAKE_EN 0xF1800
#define VID_SET_GPIOWAKE_EN 0x71800
#define VID_GET_GPIOUNSOL_EN 0xF1900
#define VID_SET_GPIOUNSOL_EN 0x71900
#define VID_GET_GPIOSTICKY 0xF1A00
#define VID_SET_GPIOSTICKY 0x71A00
#define VID_GET_BEEPGEN 0xF0A00
#define VID_SET_BEEPGEN 0x70A00
#define VID_GET_VOLUME_KNOB 0xf0f00
#define VID_SET_VOLUME_KNOB 0x70f00
#define VID_GET_SUBSYSTEMID 0xF2000
#define VID_SET_SUBSYSTEMID1 0x72000
#define VID_SET_SUBSYSTEMID2 0x72100
#define VID_SET_SUBSYSTEMID3 0x72200
#define VID_SET_SUBSYSTEMID4 0x72300
#define VID_GET_CONFIGURATION_DEFAULT 0xf1c00
#define VID_SET_CONFIGURATION_DEFAULT1 0x71c00
#define VID_SET_CONFIGURATION_DEFAULT2 0x71d00
#define VID_SET_CONFIGURATION_DEFAULT3 0x71e00
#define VID_SET_CONFIGURATION_DEFAULT4 0x71f00
#define VID_GET_STRIPE_CONTROL 0xf2400
#define VID_SET_STRIPE_CONTROL 0x72000
#define VID_FUNCTION_RESET 0x7ff00
/* later specification updates */
#define VID_GET_EDID_LIKE_DATA 0xf2f00
#define VID_GET_CONVERTER_CHANNEL_COUNT 0xf2d00
#define VID_SET_CONVERTER_CHANNEL_COUNT 0x72d00
#define VID_GET_DATA_ISLAND_PACKET_SIZE 0xf2e00
#define VID_GET_DATA_ISLAND_PACKET_INDEX 0xf3000
#define VID_SET_DATA_ISLAND_PACKET_INDEX 0x73000
#define VID_GET_DATA_ISLAND_PACKET_DATA 0xf3100
#define VID_SET_DATA_ISLAND_PACKET_DATA 0x73100
#define VID_GET_DATA_ISLAND_PACKET_XMITCTRL 0xf3200
#define VID_SET_DATA_ISLAND_PACKET_XMITCTRL 0x73200
#define VID_GET_CONTENT_PROTECTION_CONTROL 0xf3300
#define VID_SET_CONTENT_PROTECTION_CONTROL 0x73300
#define VID_GET_ASP_CHANNEL_MAPPING 0xf3400
#define VID_SET_ASP_CHANNEL_MAPPING 0x73400
/* Parameter IDs */
#define PID_VENDOR_ID 0x00
#define PID_REVISION_ID 0x02
#define PID_SUB_NODE_COUNT 0x04
#define PID_FUNCTION_GROUP_TYPE 0x05
#define PID_AUDIO_GROUP_CAP 0x08
#define PID_AUDIO_WIDGET_CAP 0x09
#define PID_PCM_SUPPORT 0x0a
#define PID_STREAM_SUPPORT 0x0b
#define PID_PIN_CAP 0x0c
#define PID_INPUT_AMPLIFIER_CAP 0x0d
#define PID_CONNECTION_LIST_LENGTH 0x0e
#define PID_POWERSTATE_SUPPORT 0x0f
#define PID_PROCESSING_CAP 0x10
#define PID_GPIO_COUNT 0x11
#define PID_OUTPUT_AMPLIFIER_CAP 0x12
#define PID_VOLUME_KNOB_CAP 0x13
/* Subordinate node count */
#define SUB_NODE_COUNT_TOTAL_MASK 0x000000ff
#define SUB_NODE_COUNT_TOTAL_SHIFT 0
#define SUB_NODE_COUNT_START_MASK 0x00ff0000
#define SUB_NODE_COUNT_START_SHIFT 16
#define SUB_NODE_COUNT_TOTAL(c) ((c & SUB_NODE_COUNT_TOTAL_MASK) \
>> SUB_NODE_COUNT_TOTAL_SHIFT)
#define SUB_NODE_COUNT_START(c) ((c & SUB_NODE_COUNT_START_MASK) \
>> SUB_NODE_COUNT_START_SHIFT)
/* Function group type */
#define FUNCTION_GROUP_NODETYPE_MASK 0x000000ff
#define FUNCTION_GROUP_UNSOLCAPABLE_MASK 0x00000100
#define FUNCTION_GROUP_NODETYPE_AUDIO 0x00000001
#define FUNCTION_GROUP_NODETYPE_MODEM 0x00000002
/* Audio Function group capabilities */
#define AUDIO_GROUP_CAP_OUTPUT_DELAY_MASK 0x0000000f
#define AUDIO_GROUP_CAP_OUTPUT_DELAY_SHIFT 0
#define AUDIO_GROUP_CAP_INPUT_DELAY_MASK 0x00000f00
#define AUDIO_GROUP_CAP_INPUT_DELAY_SHIFT 8
#define AUDIO_GROUP_CAP_BEEPGEN_MASK 0x00010000
#define AUDIO_GROUP_CAP_BEEPGEN_SHIFT 16
#define AUDIO_GROUP_CAP_OUTPUT_DELAY(c) ((c & AUDIO_GROUP_CAP_OUTPUT_DELAY_MASK) \
>> AUDIO_GROUP_CAP_OUTPUT_DELAY_SHIFT)
#define AUDIO_GROUP_CAP_INPUT_DELAY(c) ((c & AUDIO_GROUP_CAP_INPUT_DELAY_MASK) \
>> AUDIO_GROUP_CAP_INPUT_DELAY_SHIFT)
#define AUDIO_GROUP_CAP_BEEPGEN(c) ((c & AUDIO_GROUP_CAP_BEEPGEN_MASK) \
>> AUDIO_GROUP_CAP_BEEPGEN_SHIFT)
/* Audio widget capabilities */
#define AUDIO_CAP_CHANNEL_COUNT_MASK 0x0000e000
#define AUDIO_CAP_CHANNEL_COUNT_SHIFT 13
#define AUDIO_CAP_DELAY_MASK 0x000f0000
#define AUDIO_CAP_DELAY_SHIFT 16
#define AUDIO_CAP_TYPE_MASK 0x00f00000
#define AUDIO_CAP_TYPE_SHIFT 20
#define AUDIO_CAP_STEREO (1L << 0)
#define AUDIO_CAP_INPUT_AMPLIFIER (1L << 1)
#define AUDIO_CAP_OUTPUT_AMPLIFIER (1L << 2)
#define AUDIO_CAP_AMPLIFIER_OVERRIDE (1L << 3)
#define AUDIO_CAP_FORMAT_OVERRIDE (1L << 4)
#define AUDIO_CAP_STRIPE (1L << 5)
#define AUDIO_CAP_PROCESSING_CONTROLS (1L << 6)
#define AUDIO_CAP_UNSOLICITED_RESPONSES (1L << 7)
#define AUDIO_CAP_CONNECTION_LIST (1L << 8)
#define AUDIO_CAP_DIGITAL (1L << 9)
#define AUDIO_CAP_POWER_CONTROL (1L << 10)
#define AUDIO_CAP_LEFT_RIGHT_SWAP (1L << 11)
#define AUDIO_CAP_CP_CAPS (1L << 12)
#define AUDIO_CAP_CHANNEL_COUNT(c) \
(((c & AUDIO_CAP_CHANNEL_COUNT_MASK) >> (AUDIO_CAP_CHANNEL_COUNT_SHIFT - 1)) \
| AUDIO_CAP_STEREO)
/* Amplifier capabilities */
#define AMP_CAP_MUTE 0xf0000000
#define AMP_CAP_STEP_SIZE_MASK 0x007f0000
#define AMP_CAP_STEP_SIZE_SHIFT 16
#define AMP_CAP_NUM_STEPS_MASK 0x00007f00
#define AMP_CAP_NUM_STEPS_SHIFT 8
#define AMP_CAP_OFFSET_MASK 0x0000007f
#define AMP_CAP_STEP_SIZE(c) ((((c & AMP_CAP_STEP_SIZE_MASK) \
>> AMP_CAP_STEP_SIZE_SHIFT) + 1) / 4.0)
#define AMP_CAP_NUM_STEPS(c) ((c & AMP_CAP_NUM_STEPS_MASK) \
>> AMP_CAP_NUM_STEPS_SHIFT)
#define AMP_CAP_OFFSET(c) (c & AMP_CAP_OFFSET_MASK)
/* Pin capabilities */
#define PIN_CAP_IMP_SENSE (1L << 0)
#define PIN_CAP_TRIGGER_REQ (1L << 1)
#define PIN_CAP_PRES_DETECT (1L << 2)
#define PIN_CAP_HP_DRIVE (1L << 3)
#define PIN_CAP_OUTPUT (1L << 4)
#define PIN_CAP_INPUT (1L << 5)
#define PIN_CAP_BALANCE (1L << 6)
#define PIN_CAP_HDMI (1L << 7)
#define PIN_CAP_VREF_CTRL_HIZ (1L << 8)
#define PIN_CAP_VREF_CTRL_50 (1L << 9)
#define PIN_CAP_VREF_CTRL_GROUND (1L << 10)
#define PIN_CAP_VREF_CTRL_80 (1L << 12)
#define PIN_CAP_VREF_CTRL_100 (1L << 13)
#define PIN_CAP_EAPD_CAP (1L << 16)
#define PIN_CAP_DP (1L << 24)
#define PIN_CAP_HBR (1L << 27)
#define PIN_CAP_IS_PRES_DETECT_CAP(c) ((c & PIN_CAP_PRES_DETECT) != 0)
#define PIN_CAP_IS_OUTPUT(c) ((c & PIN_CAP_OUTPUT) != 0)
#define PIN_CAP_IS_INPUT(c) ((c & PIN_CAP_INPUT) != 0)
#define PIN_CAP_IS_BALANCE(c) ((c & PIN_CAP_BALANCE) != 0)
#define PIN_CAP_IS_HDMI(c) ((c & PIN_CAP_HDMI) != 0)
#define PIN_CAP_IS_VREF_CTRL_50_CAP(c) ((c & PIN_CAP_VREF_CTRL_50) != 0)
#define PIN_CAP_IS_VREF_CTRL_80_CAP(c) ((c & PIN_CAP_VREF_CTRL_80) != 0)
#define PIN_CAP_IS_VREF_CTRL_100_CAP(c) ((c & PIN_CAP_VREF_CTRL_100) != 0)
#define PIN_CAP_IS_EAPD_CAP(c) ((c & PIN_CAP_EAPD_CAP) != 0)
#define PIN_CAP_IS_DP(c) ((c & PIN_CAP_DP) != 0)
#define PIN_CAP_IS_HBR(c) ((c & PIN_CAP_HBR) != 0)
/* PCM support */
#define PCM_8_BIT (1L << 16)
#define PCM_16_BIT (1L << 17)
#define PCM_20_BIT (1L << 18)
#define PCM_24_BIT (1L << 19)
#define PCM_32_BIT (1L << 20)
/* stream support */
#define STREAM_AC3 0x00000004
#define STREAM_FLOAT 0x00000002
#define STREAM_PCM 0x00000001
/* Amplifier Gain/Mute */
#define AMP_GET_OUTPUT (1L << 15)
#define AMP_GET_INPUT (0L << 15)
#define AMP_GET_LEFT_CHANNEL (1L << 13)
#define AMP_GET_RIGHT_CHANNEL (0L << 13)
#define AMP_GET_INPUT_INDEX_MASK 0x0000000f
#define AMP_GET_INPUT_INDEX_SHIFT 0
#define AMP_GET_INPUT_INDEX(x) ((x << AMP_GET_INPUT_INDEX_SHIFT) & AMP_GET_INPUT_INDEX_MASK)
#define AMP_SET_OUTPUT (1L << 15)
#define AMP_SET_INPUT (1L << 14)
#define AMP_SET_LEFT_CHANNEL (1L << 13)
#define AMP_SET_RIGHT_CHANNEL (1L << 12)
#define AMP_SET_INPUT_INDEX_MASK 0x00000f00
#define AMP_SET_INPUT_INDEX_SHIFT 8
#define AMP_SET_INPUT_INDEX(x) ((x << AMP_SET_INPUT_INDEX_SHIFT) & AMP_SET_INPUT_INDEX_MASK)
#define AMP_GAIN_MASK 0x0000007f
#define AMP_MUTE (1L << 7)
/* Pin Widget Control */
#define PIN_ENABLE_HEAD_PHONE (1L << 7)
#define PIN_ENABLE_OUTPUT (1L << 6)
#define PIN_ENABLE_INPUT (1L << 5)
#define PIN_ENABLE_VREF_HIZ 0
#define PIN_ENABLE_VREF_50 1
#define PIN_ENABLE_VREF_GROUND 2
#define PIN_ENABLE_VREF_80 4
#define PIN_ENABLE_VREF_100 5
/* Unsolicited Response */
#define UNSOLRESP_ENABLE (1L << 7)
#define UNSOLRESP_TAG_MASK 0x0000003f
#define UNSOLRESP_TAG_SHIFT 0
/* Pin sense */
#define PIN_SENSE_PRESENCE_DETECT (1L << 31)
#define PIN_SENSE_ELD_VALID (1L << 30)
#define PIN_SENSE_IMPEDANCE_MASK 0x7fffffff
#define PIN_SENSE_IMPEDANCE_SHIFT 0
#define PIN_SENSE_IMPEDANCE_INVALID 0x7fffffff
#define PIN_SENSE_SET_CHANNEL_LEFT 0
#define PIN_SENSE_SET_CHANNEL_RIGHT 1
/* Supported power states */
#define POWER_STATE_D0 (1L << 0)
#define POWER_STATE_D1 (1L << 1)
#define POWER_STATE_D2 (1L << 2)
#define POWER_STATE_D3 (1L << 3)
#define POWER_STATE_D3COLD (1L << 4)
#define POWER_STATE_S3D3COLD (1L << 29)
#define POWER_STATE_CLKSTOP (1L << 30)
#define POWER_STATE_EPSS (1L << 31)
/* Configuration default */
#define CONF_DEFAULT_SEQUENCE_MASK 0x0000000f
#define CONF_DEFAULT_SEQUENCE_SHIFT 0
#define CONF_DEFAULT_ASSOCIATION_MASK 0x000000f0
#define CONF_DEFAULT_ASSOCIATION_SHIFT 4
#define CONF_DEFAULT_MISC_MASK 0x00000f00
#define CONF_DEFAULT_MISC_SHIFT 8
#define CONF_DEFAULT_COLOR_MASK 0x0000f000
#define CONF_DEFAULT_COLOR_SHIFT 12
#define CONF_DEFAULT_CONNTYPE_MASK 0x000f0000
#define CONF_DEFAULT_CONNTYPE_SHIFT 16
#define CONF_DEFAULT_DEVICE_MASK 0x00f00000
#define CONF_DEFAULT_DEVICE_SHIFT 20
#define CONF_DEFAULT_LOCATION_MASK 0x3f000000
#define CONF_DEFAULT_LOCATION_SHIFT 24
#define CONF_DEFAULT_CONNECTIVITY_MASK 0xc0000000
#define CONF_DEFAULT_CONNECTIVITY_SHIFT 30
#define CONF_DEFAULT_SEQUENCE(c) ((c & CONF_DEFAULT_SEQUENCE_MASK) >> CONF_DEFAULT_SEQUENCE_SHIFT)
#define CONF_DEFAULT_ASSOCIATION(c) ((c & CONF_DEFAULT_ASSOCIATION_MASK) >> CONF_DEFAULT_ASSOCIATION_SHIFT)
#define CONF_DEFAULT_MISC(c) ((c & CONF_DEFAULT_MISC_MASK) >> CONF_DEFAULT_MISC_SHIFT)
#define CONF_DEFAULT_COLOR(c) ((c & CONF_DEFAULT_COLOR_MASK) >> CONF_DEFAULT_COLOR_SHIFT)
#define CONF_DEFAULT_CONNTYPE(c) ((c & CONF_DEFAULT_CONNTYPE_MASK) >> CONF_DEFAULT_CONNTYPE_SHIFT)
#define CONF_DEFAULT_DEVICE(c) ((c & CONF_DEFAULT_DEVICE_MASK) >> CONF_DEFAULT_DEVICE_SHIFT)
#define CONF_DEFAULT_LOCATION(c) ((c & CONF_DEFAULT_LOCATION_MASK) >> CONF_DEFAULT_LOCATION_SHIFT)
#define CONF_DEFAULT_CONNECTIVITY(c) ((c & CONF_DEFAULT_CONNECTIVITY_MASK) >> CONF_DEFAULT_CONNECTIVITY_SHIFT)
/* EAPD/BTL enable */
#define EAPDBTL_ENABLE_BTL 0x1
#define EAPDBTL_ENABLE_EAPD 0x2
#define EAPDBTL_ENABLE_LRSWAP 0x4
/* GP I/O count */
#define GPIO_COUNT_NUM_GPIO_MASK 0x000000ff
#define GPIO_COUNT_NUM_GPIO_SHIFT 0
#define GPIO_COUNT_NUM_GPO_MASK 0x0000ff00
#define GPIO_COUNT_NUM_GPO_SHIFT 8
#define GPIO_COUNT_NUM_GPI_MASK 0x00ff0000
#define GPIO_COUNT_NUM_GPI_SHIFT 16
#define GPIO_COUNT_GPIUNSOL_MASK 0x40000000
#define GPIO_COUNT_GPIUNSOL_SHIFT 30
#define GPIO_COUNT_GPIWAKE_MASK 0x80000000
#define GPIO_COUNT_GPIWAKE_SHIFT 31
#define GPIO_COUNT_NUM_GPIO(c) ((c & GPIO_COUNT_NUM_GPIO_MASK) >> GPIO_COUNT_NUM_GPIO_SHIFT)
#define GPIO_COUNT_NUM_GPO(c) ((c & GPIO_COUNT_NUM_GPO_MASK) >> GPIO_COUNT_NUM_GPO_SHIFT)
#define GPIO_COUNT_NUM_GPI(c) ((c & GPIO_COUNT_NUM_GPI_MASK) >> GPIO_COUNT_NUM_GPI_SHIFT)
#define GPIO_COUNT_GPIUNSOL(c) ((c & GPIO_COUNT_GPIUNSOL_MASK) >> GPIO_COUNT_GPIUNSOL_SHIFT)
#define GPIO_COUNT_GPIWAKE(c) ((c & GPIO_COUNT_GPIWAKE_MASK) >> GPIO_COUNT_GPIWAKE_SHIFT)
#endif /* HDA_CODEC_H */

View file

@ -0,0 +1,178 @@
/*
* Copyright 2007-2012, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar Adema, ithamar AT unet DOT nl
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef HDAC_REGS_H
#define HDAC_REGS_H
#ifndef __REACTOS__
#include <SupportDefs.h>
#endif
/* Controller register definitions */
#define HDAC_GLOBAL_CAP 0x00 // 16bits, GCAP
#define GLOBAL_CAP_OUTPUT_STREAMS(cap) (((cap) >> 12) & 15)
#define GLOBAL_CAP_INPUT_STREAMS(cap) (((cap) >> 8) & 15)
#define GLOBAL_CAP_BIDIR_STREAMS(cap) (((cap) >> 3) & 15)
#define GLOBAL_CAP_NUM_SDO(cap) ((((cap) >> 1) & 3) ? (cap & 6) : 1)
#define GLOBAL_CAP_64BIT(cap) (((cap) & 1) != 0)
#define HDAC_VERSION_MINOR 0x02 // 8bits, VMIN
#define HDAC_VERSION_MAJOR 0x03 // 8bits, VMAJ
#define HDAC_GLOBAL_CONTROL 0x08 // 32bits, GCTL
#define GLOBAL_CONTROL_UNSOLICITED (1 << 8)
// accept unsolicited responses
#define GLOBAL_CONTROL_FLUSH (1 << 1)
#define GLOBAL_CONTROL_RESET (1 << 0)
#define HDAC_WAKE_ENABLE 0x0c // 16bits, WAKEEN
#define HDAC_WAKE_ENABLE_MASK 0x7fff
#define HDAC_STATE_STATUS 0x0e // 16bits, STATESTS
#define HDAC_INTR_CONTROL 0x20 // 32bits, INTCTL
#define INTR_CONTROL_GLOBAL_ENABLE (1U << 31)
#define INTR_CONTROL_CONTROLLER_ENABLE (1 << 30)
#define HDAC_INTR_STATUS 0x24 // 32bits, INTSTS
#define INTR_STATUS_GLOBAL (1U << 31)
#define INTR_STATUS_CONTROLLER (1 << 30)
#define INTR_STATUS_STREAM_MASK 0x3fffffff
#define HDAC_CORB_BASE_LOWER 0x40 // 32bits, CORBLBASE
#define HDAC_CORB_BASE_UPPER 0x44 // 32bits, CORBUBASE
#define HDAC_CORB_WRITE_POS 0x48 // 16bits, CORBWP
#define HDAC_CORB_WRITE_POS_MASK 0xff
#define HDAC_CORB_READ_POS 0x4a // 16bits, CORBRP
#define CORB_READ_POS_RESET (1 << 15)
#define HDAC_CORB_CONTROL 0x4c // 8bits, CORBCTL
#define HDAC_CORB_CONTROL_MASK 0x3
#define CORB_CONTROL_RUN (1 << 1)
#define CORB_CONTROL_MEMORY_ERROR_INTR (1 << 0)
#define HDAC_CORB_STATUS 0x4d // 8bits, CORBSTS
#define CORB_STATUS_MEMORY_ERROR (1 << 0)
#define HDAC_CORB_SIZE 0x4e // 8bits, CORBSIZE
#define HDAC_CORB_SIZE_MASK 0x3
#define CORB_SIZE_CAP_2_ENTRIES (1 << 4)
#define CORB_SIZE_CAP_16_ENTRIES (1 << 5)
#define CORB_SIZE_CAP_256_ENTRIES (1 << 6)
#define CORB_SIZE_2_ENTRIES 0x00 // 8 byte
#define CORB_SIZE_16_ENTRIES 0x01 // 64 byte
#define CORB_SIZE_256_ENTRIES 0x02 // 1024 byte
#define HDAC_RIRB_BASE_LOWER 0x50 // 32bits, RIRBLBASE
#define HDAC_RIRB_BASE_UPPER 0x54 // 32bits, RIRBUBASE
#define HDAC_RIRB_WRITE_POS 0x58 // 16bits, RIRBWP
#define RIRB_WRITE_POS_RESET (1 << 15)
#define HDAC_RESPONSE_INTR_COUNT 0x5a // 16bits, RINTCNT
#define HDAC_RESPONSE_INTR_COUNT_MASK 0xff
#define HDAC_RIRB_CONTROL 0x5c // 8bits, RIRBCTL
#define HDAC_RIRB_CONTROL_MASK 0x7
#define RIRB_CONTROL_OVERRUN_INTR (1 << 2)
#define RIRB_CONTROL_DMA_ENABLE (1 << 1)
#define RIRB_CONTROL_RESPONSE_INTR (1 << 0)
#define HDAC_RIRB_STATUS 0x5d // 8bits, RIRBSTS
#define RIRB_STATUS_OVERRUN (1 << 2)
#define RIRB_STATUS_RESPONSE (1 << 0)
#define HDAC_RIRB_SIZE 0x5e // 8bits, RIRBSIZE
#define HDAC_RIRB_SIZE_MASK 0x3
#define RIRB_SIZE_CAP_2_ENTRIES (1 << 4)
#define RIRB_SIZE_CAP_16_ENTRIES (1 << 5)
#define RIRB_SIZE_CAP_256_ENTRIES (1 << 6)
#define RIRB_SIZE_2_ENTRIES 0x00
#define RIRB_SIZE_16_ENTRIES 0x01
#define RIRB_SIZE_256_ENTRIES 0x02
#define HDAC_DMA_POSITION_BASE_LOWER 0x70 // 32bits, DPLBASE
#define HDAC_DMA_POSITION_BASE_UPPER 0x74 // 32bits, DPUBASE
#define DMA_POSITION_ENABLED 1
/* Stream Descriptor Registers */
#define HDAC_STREAM_BASE 0x80
#define HDAC_STREAM_SIZE 0x20
#define HDAC_STREAM_CONTROL0 0x00 // 8bits, CTL0
#define CONTROL0_RESET (1 << 0)
#define CONTROL0_RUN (1 << 1)
#define CONTROL0_BUFFER_COMPLETED_INTR (1 << 2)
#define CONTROL0_FIFO_ERROR_INTR (1 << 3)
#define CONTROL0_DESCRIPTOR_ERROR_INTR (1 << 4)
#define HDAC_STREAM_CONTROL1 0x01 // 8bits, CTL1
#define HDAC_STREAM_CONTROL2 0x02 // 8bits, CTL2
#define CONTROL2_STREAM_MASK 0xf0
#define CONTROL2_STREAM_SHIFT 4
#define CONTROL2_BIDIR (1 << 3)
#define CONTROL2_TRAFFIC_PRIORITY (1 << 2)
#define CONTROL2_STRIPE_SDO_MASK 0x03
#define HDAC_STREAM_STATUS 0x03 // 8bits, STS
#define STATUS_BUFFER_COMPLETED (1 << 2)
#define STATUS_FIFO_ERROR (1 << 3)
#define STATUS_DESCRIPTOR_ERROR (1 << 4)
#define STATUS_FIFO_READY (1 << 5)
#define HDAC_STREAM_POSITION 0x04 // 32bits, LPIB
#define HDAC_STREAM_BUFFER_SIZE 0x08 // 32bits, CBL
#define HDAC_STREAM_LAST_VALID 0x0c // 16bits, LVI
#define HDAC_STREAM_FIFO_SIZE 0x10 // 16bits, FIFOS
#define HDAC_STREAM_FORMAT 0x12 // 16bits, FMT
#define FORMAT_8BIT (0 << 4)
#define FORMAT_16BIT (1 << 4)
#define FORMAT_20BIT (2 << 4)
#define FORMAT_24BIT (3 << 4)
#define FORMAT_32BIT (4 << 4)
#define FORMAT_44_1_BASE_RATE (1 << 14)
#define FORMAT_MULTIPLY_RATE_SHIFT 11
#define FORMAT_DIVIDE_RATE_SHIFT 8
#define HDAC_STREAM_BUFFERS_BASE_LOWER 0x18 // 32bits, BDPL
#define HDAC_STREAM_BUFFERS_BASE_UPPER 0x1c // 32bits, BDPU
/* PCI space register definitions */
#define PCI_HDA_TCSEL 0x44
#define PCI_HDA_TCSEL_MASK 0xf8
#define ATI_HDA_MISC_CNTR2 0x42
#define ATI_HDA_MISC_CNTR2_MASK 0xf8
#define ATI_HDA_ENABLE_SNOOP 0x02
#define NVIDIA_HDA_OSTRM_COH 0x4c
#define NVIDIA_HDA_ISTRM_COH 0x4d
#define NVIDIA_HDA_ENABLE_COHBIT 0x01
#define NVIDIA_HDA_TRANSREG 0x4e
#define NVIDIA_HDA_TRANSREG_MASK 0xf0
#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
#define INTEL_SCH_HDA_DEVC 0x78
#define INTEL_SCH_HDA_DEVC_SNOOP 0x800
#ifndef __REACTOS__
typedef uint32 corb_t;
typedef struct {
uint32 response;
uint32 flags;
} rirb_t;
#endif
#define RESPONSE_FLAGS_CODEC_MASK 0x0000000f
#define RESPONSE_FLAGS_UNSOLICITED (1 << 4)
#ifndef __REACTOS__
typedef struct {
uint32 lower;
uint32 upper;
uint32 length;
uint32 ioc;
} bdl_entry_t;
#endif
#endif /* HDAC_REGS_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,103 @@
#pragma once
#define YDEBUG
#include <ntddk.h>
#include <debug.h>
#include <initguid.h>
#include <hdaudio.h>
#include <stdio.h>
#define TAG_HDA 'bADH'
// include Haiku headers
#include "driver.h"
#define MAKE_RATE(base, multiply, divide) \
((base == 44100 ? FORMAT_44_1_BASE_RATE : 0) \
| ((multiply - 1) << FORMAT_MULTIPLY_RATE_SHIFT) \
| ((divide - 1) << FORMAT_DIVIDE_RATE_SHIFT))
#define HDAC_INPUT_STREAM_OFFSET(index) \
((index) * HDAC_STREAM_SIZE)
#define HDAC_OUTPUT_STREAM_OFFSET(num_input_streams, index) \
((num_input_streams + (index)) * HDAC_STREAM_SIZE)
#define HDAC_BIDIR_STREAM_OFFSET(num_input_streams, num_output_streams, index) \
((num_input_streams + num_output_streams \
+ (index)) * HDAC_STREAM_SIZE)
#define ALIGN(size, align) (((size) + align - 1) & ~(align - 1))
typedef struct {
ULONG response;
ULONG flags;
}RIRB_RESPONSE, *PRIRB_RESPONSE;
typedef struct
{
PDEVICE_OBJECT ChildPDO;
ULONG FunctionGroup;
ULONG NodeId;
}HDA_CODEC_AUDIO_GROUP, *PHDA_CODEC_AUDIO_GROUP;
typedef struct
{
USHORT VendorId;
USHORT ProductId;
UCHAR Major;
UCHAR Minor;
UCHAR Revision;
UCHAR Stepping;
UCHAR Addr;
ULONG Responses[MAX_CODEC_RESPONSES];
ULONG ResponseCount;
PHDA_CODEC_AUDIO_GROUP AudioGroups[HDA_MAX_AUDIO_GROUPS];
ULONG AudioGroupCount;
}HDA_CODEC_ENTRY, *PHDA_CODEC_ENTRY;
typedef struct
{
BOOLEAN IsFDO;
PDEVICE_OBJECT LowerDevice;
PUCHAR RegBase;
PKINTERRUPT Interrupt;
ULONG CorbLength;
PULONG CorbBase;
ULONG RirbLength;
PRIRB_RESPONSE RirbBase;
ULONG RirbReadPos;
ULONG CorbWritePos;
PVOID StreamPositions;
PHDA_CODEC_ENTRY Codecs[HDA_MAX_CODECS + 1];
}HDA_FDO_DEVICE_EXTENSION, *PHDA_FDO_DEVICE_EXTENSION;
typedef struct
{
BOOLEAN IsFDO;
PHDA_CODEC_ENTRY Codec;
PHDA_CODEC_AUDIO_GROUP AudioGroup;
}HDA_PDO_DEVICE_EXTENSION, *PHDA_PDO_DEVICE_EXTENSION;
typedef struct {
ULONG device : 16;
ULONG vendor : 16;
ULONG stepping : 8;
ULONG revision : 8;
ULONG minor : 4;
ULONG major : 4;
ULONG _reserved0 : 8;
ULONG count : 8;
ULONG _reserved1 : 8;
ULONG start : 8;
ULONG _reserved2 : 8;
}CODEC_RESPONSE, *PCODEC_RESPONSE;