dde_bsd: update audio driver to OpenBSD 7.1

This commit updates the driver from version 6.6 to 7.1. In contrast
to the old driver the new one will now probe all available HDA devices
and will drive the first usable one, e.g.:

```
[init -> audio_drv] azalia0 [8086:160c]
[init -> audio_drv] :
[init -> audio_drv] azalia0: no supported codecs
[init -> audio_drv] azalia1 [8086:9ca0]
[init -> audio_drv] :
[init -> audio_drv] azalia1: codecs: Realtek ALC292
[init -> audio_drv] audio0 at azalia1
```

Fixes #4629.
This commit is contained in:
Josef Söntgen 2022-09-30 19:35:01 +00:00 committed by Christian Helmuth
parent 3186e47807
commit e0f5cdacf0
17 changed files with 235 additions and 210 deletions

View File

@ -0,0 +1,14 @@
To signal an successful attach attempt we set the ref counter
of the parent, i.e., the dummy pci bus and check that in our
'probe_cfdata' function.
--- a/dev/pci/azalia.c
+++ b/dev/pci/azalia.c
@@ -591,6 +591,7 @@
audio_attach_mi(&azalia_hw_if, sc, NULL, &sc->dev);
+ parent->dv_ref = 1;
return;
err_exit:

View File

@ -1,55 +0,0 @@
--- a/dev/pci/azalia.c
+++ b/dev/pci/azalia.c
@@ -492,7 +492,7 @@
azalia_t *sc;
struct pci_attach_args *pa;
pcireg_t v;
- uint8_t reg;
+ // uint8_t reg;
pci_intr_handle_t ih;
const char *interrupt_str;
@@ -518,12 +518,18 @@
azalia_configure_pci(sc);
- /* disable MSI, use INTx instead */
- if (PCI_VENDOR(sc->pciid) == PCI_VENDOR_INTEL) {
- reg = azalia_pci_read(sc->pc, sc->tag, ICH_PCI_MMC);
- reg &= ~(ICH_PCI_MMC_ME);
- azalia_pci_write(sc->pc, sc->tag, ICH_PCI_MMC, reg);
- }
+ // This was added in CVS rev 1.168 because certain devices do not
+ // support MSIs. For reasons that are not clear yet, this breaks
+ // when using the platform_drv on x86 with MSI support and IOMMU
+ // enabled. All hw we tested seems to work fine when it is removed,
+ // even older kernels, e.g. OKL4, that use legacy IRQs,
+ //
+ // /* disable MSI, use INTx instead */
+ // if (PCI_VENDOR(sc->pciid) == PCI_VENDOR_INTEL) {
+ // reg = azalia_pci_read(sc->pc, sc->tag, ICH_PCI_MMC);
+ // reg &= ~(ICH_PCI_MMC_ME);
+ // azalia_pci_write(sc->pc, sc->tag, ICH_PCI_MMC, reg);
+ // }
/* disable MSI for AMD Summit Ridge/Raven Ridge HD Audio */
if (PCI_VENDOR(sc->pciid) == PCI_VENDOR_AMD) {
@@ -3973,6 +3979,10 @@
azalia_set_blksz(void *v, int mode,
struct audio_params *p, struct audio_params *r, unsigned int blksz)
{
+ // XXX using mult leads to a blksz of 416 in case of a
+ // requested blksz of 441 which in return results in distored
+ // playback.
+#if 0
int mult;
/* must be multiple of 128 bytes */
@@ -3981,6 +3991,7 @@
blksz -= blksz % mult;
if (blksz == 0)
blksz = mult;
+#endif
return blksz;
}

View File

@ -1,42 +0,0 @@
--- a/dev/pci/azalia_codec.c
+++ b/dev/pci/azalia_codec.c
@@ -83,6 +83,13 @@
this->name = "Realtek ALC221";
this->qrks |= AZ_QRK_WID_CDIN_1C | AZ_QRK_WID_BEEP_1D;
break;
+ case 0x10ec0255:
+ this->name = "Realtek ALC255";
+ DPRINTF(("Realtek ALC255 0x%8x\n", this->subid));
+ if (this->subid == 0x193e10cf) { /* FUJITSU S938 */
+ this->qrks |= AZ_QRK_WID_HEADSET;
+ }
+ break;
case 0x10ec0260:
this->name = "Realtek ALC260";
if (this->subid == 0x008f1025)
@@ -656,6 +663,10 @@
CORB_GET_PIN_SENSE, 0, &result);
if (!err && (result & CORB_PS_PRESENCE))
vol = 1;
+
+ // switch microphone to mic2
+ if (!err)
+ notify_hp_sense(result & CORB_PS_PRESENCE);
}
if (err)
break;
@@ -2590,6 +2601,14 @@
w->enable = 1;
}
+ if (this->qrks & AZ_QRK_WID_HEADSET &&
+ nid == 0x19) {
+ /* Fujitsu S398 headphone jack */
+ w->d.pin.config = 0x03a19120;
+ azalia_pin_config_ov(w, CORB_CD_DEVICE_MASK, CORB_CD_MICIN);
+ w->enable = 1;
+ }
+
if (this->qrks & AZ_QRK_WID_CDIN_1C &&
nid == 0x1c && w->enable == 0 && w->d.pin.device == CORB_CD_CD) {
azalia_pin_config_ov(w, CORB_CD_PORT_MASK, CORB_CD_FIXED);

View File

@ -1,10 +0,0 @@
--- a/dev/pci/azalia.h
+++ b/dev/pci/azalia.h
@@ -513,6 +513,7 @@
#define AZ_QRK_WID_TPDOCK1 0x00010000
#define AZ_QRK_WID_TPDOCK2 0x00020000
#define AZ_QRK_WID_TPDOCK3 0x00040000
+#define AZ_QRK_WID_HEADSET 0x00080000
#define AZ_QRK_WID_DOLBY_ATMOS 0x00100000
#define AZ_QRK_WID_SPKR2_DAC 0x00200000

View File

@ -0,0 +1,25 @@
--- a/dev/pci/azalia.c
+++ b/dev/pci/azalia.c
@@ -1063,10 +1063,6 @@
uint16_t corbrp, corbwp;
uint8_t corbctl;
- err = azalia_halt_corb(az);
- if (err)
- return(err);
-
if (!resuming) {
err = azalia_alloc_dmamem(az,
az->corb_entries * sizeof(corb_entry_t), 128,
@@ -1079,6 +1075,11 @@
}
timeout_set(&az->unsol_to, azalia_rirb_kick_unsol_events, az);
+ /* do after the allocation as it will access 'corb_dma' */
+ err = azalia_halt_corb(az);
+ if (err)
+ return(err);
+
AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma));
AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)));
AZ_WRITE_1(az, CORBSIZE, az->corbsize);

View File

@ -1,19 +1,20 @@
diff --git a/dev/audio.c b/dev/audio.c
index 1271bc7..6535d10 100644
Instead of implementing softintr handling add our notification
functions directly.
--- a/dev/audio.c
+++ b/dev/audio.c
@@ -411,6 +411,8 @@ audio_pintr(void *addr)
}
selwakeup(&sc->play.sel);
@@ -572,6 +572,8 @@ audio_pintr(void *addr)
*/
softintr_schedule(sc->play.softintr);
}
+
+ notify_play();
}
/*
@@ -486,6 +488,8 @@ audio_rintr(void *addr)
}
selwakeup(&sc->rec.sel);
@@ -655,6 +657,8 @@ audio_rintr(void *addr)
*/
softintr_schedule(sc->rec.softintr);
}
+
+ notify_record();

View File

@ -1,14 +0,0 @@
dev/audio.c:XXX:Y: warning: type may be used uninitialized in this function [-Wmaybe-uninitialized]
diff --git a/dev/audio.c b/dev/audio.c
index a9fa22b..da8a783 100644
--- a/dev/audio.c
+++ b/dev/audio.c
@@ -639,7 +639,7 @@ int
audioprint(void *aux, const char *pnp)
{
struct audio_attach_args *arg = aux;
- const char *type;
+ const char *type = "never printed";
if (pnp != NULL) {
switch (arg->type) {

View File

@ -0,0 +1,48 @@
diff --git a/dev/pci/azalia.h b/dev/pci/azalia.h
index 8dd7641..2d3ce3a 100644
--- a/dev/pci/azalia.h
+++ b/dev/pci/azalia.h
@@ -516,6 +516,7 @@
#define AZ_QRK_WID_CLOSE_PCBEEP 0x00080000
+#define AZ_QRK_WID_HEADSET 0x00100000
#define AZ_QRK_ROUTE_SPKR2_DAC 0x01000000
#define AZ_QRK_DOLBY_ATMOS 0x02000000
/* memory-mapped types */
typedef struct {
diff --git a/dev/pci/azalia_codec.c b/dev/pci/azalia_codec.c
index 05d157b..8046b3b 100644
--- a/dev/pci/azalia_codec.c
+++ b/dev/pci/azalia_codec.c
@@ -100,6 +100,8 @@ azalia_codec_init_vtbl(codec_t *this)
break;
case 0x10ec0255:
this->name = "Realtek ALC255";
+ if (this->subid == 0x193e10cf)
+ this->qrks |= AZ_QRK_WID_HEADSET;
break;
case 0x10ec0256:
this->name = "Realtek ALC256";
@@ -747,6 +749,9 @@ azalia_unsol_event(codec_t *this, int tag)
CORB_GET_PIN_SENSE, 0, &result);
if (!err && (result & CORB_PS_PRESENCE))
vol = 1;
+ // switch microphone to mic2
+ if (!err)
+ notify_hp_sense(result & CORB_PS_PRESENCE);
}
if (err)
break;
@@ -2702,6 +2707,12 @@ azalia_codec_widget_quirks(codec_t *this, nid_t nid)
0x57d7, NULL);
}
+ if (this->qrks & AZ_QRK_WID_HEADSET && nid == 0x19) {
+ w->d.pin.config = 0x03a19120;
+ azalia_pin_config_ov(w, CORB_CD_DEVICE_MASK, CORB_CD_MICIN);
+ w->enable = 1;
+ }
+
return(0);
}

View File

@ -1 +1 @@
03360eec0f7a11d523e2b0c88568c95cb691d3ac
771f320f0d4e11510d8f565fda456400b4793230

View File

@ -3,13 +3,13 @@ VERSION := 1
DOWNLOADS := audio.archive
#
# Audio drivers from OpenBSD 6.6
# Audio drivers from OpenBSD 7.1
#
SRC_DIR_AUDIO := src/lib/audio
VERSION_AUDIO := 6.6
BASE_URL := https://ftp.openbsd.org/pub/OpenBSD
VERSION_AUDIO := 7.1
BASE_URL := https://cdn.openbsd.org/pub/OpenBSD
URL(audio) := $(BASE_URL)/$(VERSION_AUDIO)/sys.tar.gz
SHA(audio) := a1b19665989c02a2017a639d47a042f4fe7f584b6298727e982a5536020b832d
SHA(audio) := 890cb97c01052f26cefe5430d635e0fdf6047ca701a99992968e16801e2a6565
DIR(audio) := $(SRC_DIR_AUDIO)
TAR_OPT(audio) := --strip-components=1 --files-from $(REP_DIR)/audio.list
HASH_INPUT += $(REP_DIR)/audio.list
@ -18,12 +18,6 @@ HASH_INPUT += $(REP_DIR)/audio.list
# Patches
#
PATCHES := $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/*.patch)))
AUDIO_OPT := -p1 -d$(SRC_DIR_AUDIO)
PATCH_OPT(patches/oppress_warning.patch) := $(AUDIO_OPT)
PATCH_OPT(patches/azalia_c.patch) := $(AUDIO_OPT)
PATCH_OPT(patches/azalia_h.patch) := $(AUDIO_OPT)
PATCH_OPT(patches/azalia_codec_c.patch) := $(AUDIO_OPT)
PATCH_OPT(patches/notify.patch) := $(AUDIO_OPT)
PATCH_OPT := -p1 -d$(SRC_DIR_AUDIO)
# vi: set ft=make :

View File

@ -100,7 +100,7 @@ install_config {
<start name="audio_drv" caps="150">
<binary name="pci_audio_drv"/>
<resource name="RAM" quantum="8M"/>
<resource name="RAM" quantum="10M"/>
<provides> <service name="Audio_out"/> </provides>
<config/>
</start>

View File

@ -45,6 +45,11 @@ struct cfdata cfdata[] = {
struct device pci_bus = { DV_DULL, { 0, 0 }, 0, 0, { 'p', 'c', 'i', '0'}, 0, 0, 0 };
/* global unit counter */
static int dv_unit;
/**
* This function is our little helper that matches and attaches
* the driver to the device.
@ -72,12 +77,23 @@ int probe_cfdata(struct pci_attach_args *pa)
M_DEVBUF, M_NOWAIT|M_ZERO);
dev->dv_cfdata = cf;
dev->dv_unit = dv_unit++;
snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d", cd->cd_name,
dev->dv_unit);
printf("%s at %s\n", dev->dv_xname, pci_bus.dv_xname);
printf("%s [%x:%x]\n", dev->dv_xname,
pa->pa_id & 0xffffu, (pa->pa_id >> 16u) & 0xffffu);
ca->ca_attach(&pci_bus, dev, pa);
/*
* The contrib code is patched to set the dv_ref when the
* driver attached successfully.
*/
if (!pci_bus.dv_ref) {
free(dev, M_DEVBUF, ca->ca_devsize);
return 0;
}
return 1;
}
}

View File

@ -33,8 +33,8 @@
extern struct cfdriver audio_cd;
static dev_t const adev = 0x00; /* audio0 (minor nr 0) */
static dev_t const mdev = 0x10; /* mixer0 (minor nr 16) */
static dev_t const adev = 0x00; /* /dev/audio0 */
static dev_t const mdev = 0xc0; /* /dev/audioctl */
static bool adev_usuable = false;
@ -327,6 +327,11 @@ static bool open_audio_device(dev_t dev)
return false;
int err = audioopen(dev, FWRITE|FREAD, 0 /* ifmt */, 0 /* proc */);
/* try to open playback only, if capturing potentially failed */
if (err == ENODEV)
err = audioopen(dev, FWRITE, 0 /* ifmt */, 0 /* proc */);
if (err)
return false;

View File

@ -46,21 +46,35 @@ DUMMY name(void) { \
DUMMY_RET(1, pci_intr_map_msi) /* do not support MSI API */
DUMMY_RET(0, pci_intr_string)
DUMMY(0, bus_dmamap_unload)
DUMMY(0, bus_dmamem_mmap)
DUMMY(0, bus_dmamem_unmap)
DUMMY(0, bus_space_unmap)
DUMMY(0, config_activate_children)
DUMMY(0, config_deactivate)
DUMMY(0, config_detach)
DUMMY(0, config_detach_children)
DUMMY(0, cpu_info_primary)
DUMMY(0, device_unref)
DUMMY(0, klist_free)
DUMMY(0, klist_init_mutex)
DUMMY(0, klist_insert_locked)
DUMMY(0, klist_invalidate)
DUMMY(0, klist_remove)
DUMMY(0, klist_remove_locked)
DUMMY(0, knote_modify)
DUMMY(0, knote_process)
DUMMY(0, pci_findvendor)
DUMMY(0, pci_intr_disestablish)
DUMMY(0, pci_set_powerstate)
DUMMY(0, psignal)
DUMMY(0, selrecord)
DUMMY(0, selwakeup)
DUMMY(0, softintr_disestablish)
DUMMY(0, softintr_schedule)
DUMMY(0, tsleep)
DUMMY(0, tsleep_nsec)
DUMMY(0, vdevgone)
DUMMY(0, device_unref)
DUMMY(1, softintr_establish)
} /* extern "C" */

View File

@ -65,6 +65,43 @@ typedef signed long long off_t;
#define minor(x) ((int32_t)((x) & 0xff) | (((x) & 0xffff0000) >> 8))
/*******************
** machine/cpu.h **
*******************/
struct cpu_info { };
extern struct cpu_info cpu_info_primary;
#define curcpu() (&cpu_info_primary)
/*********************
** machine/mutex.h **
*********************/
#define MUTEX_INITIALIZER(ipl) { 0, (ipl), 0, NULL }
#define MUTEX_ASSERT_UNLOCK(mtx) do { \
if ((mtx)->mtx_owner != curcpu()) \
panic("mutex %p not held in %s\n", (mtx), __func__); \
} while (0)
#define MUTEX_ASSERT_LOCKED(mtx) do { \
if ((mtx)->mtx_owner != curcpu()) \
panic("mutex %p not held in %s\n", (mtx), __func__); \
} while (0)
#define MUTEX_ASSERT_UNLOCKED(mtx) do { \
if ((mtx)->mtx_owner == curcpu()) \
panic("mutex %p held in %s\n", (mtx), __func__); \
} while (0)
struct mutex
{
volatile int mtx_lock;
int mtx_wantipl; /* interrupt priority level */
int mtx_oldipl;
void *mtx_owner;
};
/*****************
** sys/errno.h **
*****************/
@ -215,12 +252,17 @@ struct kevent
struct knote;
SLIST_HEAD(klist, knote);
#define FILTEROP_ISFD 0x00000001
#define FILTEROP_MPSAFE 0x00000002
struct filterops
{
int f_isfd;
int f_flags;
int (*f_attach)(struct knote*);
void (*f_detach)(struct knote*);
int (*f_event)(struct knote*, long);
int (*f_modify)(struct kevent *, struct knote *);
int (*f_process)(struct knote *, struct kevent *);
};
struct knote
@ -233,6 +275,15 @@ struct knote
void *kn_hook;
};
int knote_modify(const struct kevent *kev, struct knote *kn);
int knote_process(struct knote *kn, struct kevent *kev);
extern void klist_free(struct klist *);
extern void klist_init_mutex(struct klist *, struct mutex *);
extern void klist_insert(struct klist *, struct knote *);
extern void klist_invalidate(struct klist *);
extern void klist_remove(struct klist *, struct knote *);
/*******************
** sys/selinfo.h **
@ -247,43 +298,6 @@ void selrecord(struct proc *selector, struct selinfo *);
void selwakeup(struct selinfo *);
/*******************
** machine/cpu.h **
*******************/
struct cpu_info { };
extern struct cpu_info cpu_info_primary;
#define curcpu() (&cpu_info_primary)
/*********************
** machine/mutex.h **
*********************/
#define MUTEX_INITIALIZER(ipl) { 0, (ipl), 0, NULL }
#define MUTEX_ASSERT_UNLOCK(mtx) do { \
if ((mtx)->mtx_owner != curcpu()) \
panic("mutex %p not held in %s\n", (mtx), __func__); \
} while (0)
#define MUTEX_ASSERT_LOCKED(mtx) do { \
if ((mtx)->mtx_owner != curcpu()) \
panic("mutex %p not held in %s\n", (mtx), __func__); \
} while (0)
#define MUTEX_ASSERT_UNLOCKED(mtx) do { \
if ((mtx)->mtx_owner == curcpu()) \
panic("mutex %p held in %s\n", (mtx), __func__); \
} while (0)
struct mutex
{
volatile int mtx_lock;
int mtx_wantipl; /* interrupt priority level */
int mtx_oldipl;
void *mtx_owner;
};
/*****************
** sys/mutex.h **
*****************/
@ -298,6 +312,8 @@ void mtx_leave(struct mutex *);
#define INFSLP __UINT64_MAX__
#define KERNEL_ASSERT_LOCKED()
extern int nchrdev;
int enodev(void);
@ -315,6 +331,7 @@ void wakeup(const volatile void*);
int tsleep(const volatile void *, int, const char *, int);
int tsleep_nsec(const volatile void *, int, const char *, uint64_t);
int msleep(const volatile void *, struct mutex *, int, const char*, int);
int msleep_nsec(const volatile void *, struct mutex *, int, const char*, uint64_t);
int uiomove(void *, int, struct uio *);
@ -708,6 +725,13 @@ int timeout_del(struct timeout *);
#define htole32(x) ((uint32_t)(x))
/******************
** sys/stdint.h **
******************/
#define UINT64_MAX 0xffffffffffffffffULL
/****************
** sys/time.h **
****************/
@ -720,6 +744,24 @@ struct timeval
void microuptime(struct timeval *);
static inline uint64_t SEC_TO_NSEC(uint64_t seconds)
{
if (seconds > UINT64_MAX / 1000000000ULL)
return UINT64_MAX;
return seconds * 1000000000ULL;
}
/*************************
** arch specifc intr.h **
*************************/
#define IPL_SOFTNET 3
void *softintr_establish(int, void (*)(void *), void *);
void softintr_schedule(void *);
void softintr_disestablish(void *);
/***************************
** lib/libkern/libkern.h **

View File

@ -156,6 +156,7 @@ class Pci_driver
_pci.with_xml([&] (Xml_node node) {
node.for_each_sub_node("device", [&] (Xml_node node)
{
/* only use the first successfully probed device */
if (found) return;
String<16> name = node.attribute_value("name", String<16>());
@ -168,14 +169,9 @@ class Pci_driver
_sub_vendor_id = node.attribute_value("sub_vendor_id", 0U);
_sub_device_id = node.attribute_value("sub_device_id", 0U);
if ((_device_id == PCI_PRODUCT_INTEL_CORE4G_HDA_2) ||
(_vendor_id == PCI_VENDOR_INTEL && name == "00:03.0")) {
warning("ignore ", name,
", not supported HDMI/DP HDA device");
return;
}
if (_device.constructed())
_device.destruct();
/* we only construct the first useable device we find */
_device.construct(_pci, name);
_device->irq.sigh(_irq_handler);
@ -442,13 +438,6 @@ extern "C" int bus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t dmam, void *buf,
}
extern "C" void bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t)
{
Genode::warning("not implemented, called from ",
__builtin_return_address(0));
}
extern "C" int bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment,
bus_size_t boundary, bus_dma_segment_t *segs, int nsegs,
int *rsegs, int flags)
@ -497,15 +486,3 @@ extern "C" int bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int ns
return 0;
}
extern "C" void bus_dmamem_unmap(bus_dma_tag_t, caddr_t, size_t) { }
extern "C" paddr_t bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *,
int, off_t, int, int)
{
Genode::warning("not implemented, called from ",
__builtin_return_address(0));
return 0;
}

View File

@ -220,6 +220,8 @@ class Bsd::Timer
bool const queued = _timeout->scheduled();
_timeout->discard();
_timeout.destruct();
return queued ? 1 : 0;
}
@ -306,6 +308,14 @@ extern "C" int msleep(const volatile void *ident, struct mutex *mtx,
}
extern "C" int
msleep_nsec(const volatile void *ident, struct mutex *mtx, int priority,
const char *wmesg, uint64_t nsecs)
{
return msleep(ident, mtx, priority, wmesg, nsecs / 1000000);
}
extern "C" void wakeup(const volatile void *ident)
{
Bsd::Task *sleep_task = _bsd_timer->sleep_task();