diff --git a/sys/dev/pci/hdaudio/hdaudio.c b/sys/dev/pci/hdaudio/hdaudio.c index a7bafbbe1041..11b4a224a3be 100644 --- a/sys/dev/pci/hdaudio/hdaudio.c +++ b/sys/dev/pci/hdaudio/hdaudio.c @@ -1,4 +1,4 @@ -/* $NetBSD: hdaudio.c,v 1.8 2010/09/02 01:55:31 jmcneill Exp $ */ +/* $NetBSD: hdaudio.c,v 1.9 2011/01/07 15:30:29 jmcneill Exp $ */ /* * Copyright (c) 2009 Precedence Technologies Ltd @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.8 2010/09/02 01:55:31 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.9 2011/01/07 15:30:29 jmcneill Exp $"); #include #include @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.8 2010/09/02 01:55:31 jmcneill Exp $") #include #include #include +#include #include #include @@ -864,6 +865,46 @@ hdaudio_resume(struct hdaudio_softc *sc) return true; } +int +hdaudio_rescan(struct hdaudio_softc *sc, const char *ifattr, const int *locs) +{ + struct hdaudio_codec *co; + struct hdaudio_function_group *fg; + unsigned int codec; + + if (!ifattr_match(ifattr, "hdaudiobus")) + return 0; + + for (codec = 0; codec < HDAUDIO_MAX_CODECS; codec++) { + co = &sc->sc_codec[codec]; + fg = co->co_fg; + if (!co->co_valid || fg == NULL) + continue; + if (fg->fg_device) + continue; + hdaudio_attach_fg(fg, NULL); + } + + return 0; +} + +void +hdaudio_childdet(struct hdaudio_softc *sc, device_t child) +{ + struct hdaudio_codec *co; + struct hdaudio_function_group *fg; + unsigned int codec; + + for (codec = 0; codec < HDAUDIO_MAX_CODECS; codec++) { + co = &sc->sc_codec[codec]; + fg = co->co_fg; + if (!co->co_valid || fg == NULL) + continue; + if (fg->fg_device == child) + fg->fg_device = NULL; + } +} + int hdaudio_intr(struct hdaudio_softc *sc) { @@ -1348,8 +1389,12 @@ hdaudio_dispatch_fgrp_ioctl(struct hdaudio_softc *sc, u_long cmd, prop_dictionary_t request, prop_dictionary_t response) { struct hdaudio_function_group *fg; + int (*infocb)(void *, prop_dictionary_t, prop_dictionary_t); + prop_dictionary_t fgrp_dict; + uint64_t info_fn; int16_t codecid, nid; void *fgrp_sc; + bool rv; int err; if (!prop_dictionary_get_int16(request, "codecid", &codecid) || @@ -1360,17 +1405,26 @@ hdaudio_dispatch_fgrp_ioctl(struct hdaudio_softc *sc, u_long cmd, if (fg == NULL) return ENODEV; fgrp_sc = device_private(fg->fg_device); + fgrp_dict = device_properties(fg->fg_device); switch (fg->fg_type) { case HDAUDIO_GROUP_TYPE_AFG: switch (cmd) { case HDAUDIO_FGRP_CODEC_INFO: - err = hdaudio_afg_codec_info(fgrp_sc, - request, response); + rv = prop_dictionary_get_uint64(fgrp_dict, + "codecinfo-callback", &info_fn); + if (!rv) + return ENXIO; + infocb = (void *)(uintptr_t)info_fn; + err = infocb(fgrp_sc, request, response); break; case HDAUDIO_FGRP_WIDGET_INFO: - err = hdaudio_afg_widget_info(fgrp_sc, - request, response); + rv = prop_dictionary_get_uint64(fgrp_dict, + "widgetinfo-callback", &info_fn); + if (!rv) + return ENXIO; + infocb = (void *)(uintptr_t)info_fn; + err = infocb(fgrp_sc, request, response); break; default: err = EINVAL; @@ -1452,3 +1506,43 @@ hdaudioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) prop_object_release(request); return err; } + +MODULE(MODULE_CLASS_DRIVER, hdaudio, NULL); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +hdaudio_modcmd(modcmd_t cmd, void *opaque) +{ + int error = 0; +#ifdef _MODULE + int bmaj = -1, cmaj = -1; +#endif + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_hdaudio, + cfattach_ioconf_hdaudio, cfdata_ioconf_hdaudio); + if (error) + return error; + error = devsw_attach("hdaudio", NULL, &bmaj, + &hdaudio_cdevsw, &cmaj); + if (error) + config_fini_component(cfdriver_ioconf_hdaudio, + cfattach_ioconf_hdaudio, cfdata_ioconf_hdaudio); +#endif + return error; + case MODULE_CMD_FINI: +#ifdef _MODULE + devsw_detach(NULL, &hdaudio_cdevsw); + error = config_fini_component(cfdriver_ioconf_hdaudio, + cfattach_ioconf_hdaudio, cfdata_ioconf_hdaudio); +#endif + return error; + default: + return ENOTTY; + } +} diff --git a/sys/dev/pci/hdaudio/hdaudio_afg.c b/sys/dev/pci/hdaudio/hdaudio_afg.c index 4c543775dbda..efcf91a7c214 100644 --- a/sys/dev/pci/hdaudio/hdaudio_afg.c +++ b/sys/dev/pci/hdaudio/hdaudio_afg.c @@ -1,4 +1,4 @@ -/* $NetBSD: hdaudio_afg.c,v 1.27 2010/09/02 01:55:31 jmcneill Exp $ */ +/* $NetBSD: hdaudio_afg.c,v 1.28 2011/01/07 15:30:29 jmcneill Exp $ */ /* * Copyright (c) 2009 Precedence Technologies Ltd @@ -60,7 +60,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.27 2010/09/02 01:55:31 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.28 2011/01/07 15:30:29 jmcneill Exp $"); #include #include @@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.27 2010/09/02 01:55:31 jmcneill Ex #include #include #include +#include #include #include @@ -321,6 +322,11 @@ static void hdaudio_afg_childdet(device_t, device_t); static bool hdaudio_afg_suspend(device_t, const pmf_qual_t *); static bool hdaudio_afg_resume(device_t, const pmf_qual_t *); +static int hdaudio_afg_widget_info(void *, prop_dictionary_t, + prop_dictionary_t); +static int hdaudio_afg_codec_info(void *, prop_dictionary_t, + prop_dictionary_t); + CFATTACH_DECL2_NEW( hdafg, sizeof(struct hdaudio_afg_softc), @@ -378,7 +384,7 @@ static const struct audio_hw_if hdaudio_afg_hw_if = { .get_props = hdaudio_afg_get_props, .trigger_output = hdaudio_afg_trigger_output, .trigger_input = hdaudio_afg_trigger_input, - .dev_ioctl = hdaudio_afg_dev_ioctl + .dev_ioctl = hdaudio_afg_dev_ioctl, }; static int @@ -3729,7 +3735,7 @@ hdaudio_afg_trigger_input(void *opaque, void *start, void *end, int blksize, return 0; } -int +static int hdaudio_afg_widget_info(void *opaque, prop_dictionary_t request, prop_dictionary_t response) { @@ -3774,7 +3780,7 @@ hdaudio_afg_widget_info(void *opaque, prop_dictionary_t request, return 0; } -int +static int hdaudio_afg_codec_info(void *opaque, prop_dictionary_t request, prop_dictionary_t response) { @@ -3825,3 +3831,32 @@ hdaudio_afg_dev_ioctl(void *opaque, u_long cmd, void *addr, int flag, lwp_t *l) prop_object_release(request); return err; } + +MODULE(MODULE_CLASS_DRIVER, hdafg, "hdaudio"); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +hdafg_modcmd(modcmd_t cmd, void *opaque) +{ + int error; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_hdafg, + cfattach_ioconf_hdafg, cfdata_ioconf_hdafg); +#endif + return error; + case MODULE_CMD_FINI: +#ifdef _MODULE + error = config_fini_component(cfdriver_ioconf_hdafg, + cfattach_ioconf_hdafg, cfdata_ioconf_hdafg); +#endif + return error; + default: + return ENOTTY; + } +} diff --git a/sys/dev/pci/hdaudio/hdaudio_pci.c b/sys/dev/pci/hdaudio/hdaudio_pci.c index 091735ace763..72a0e16a8bfa 100644 --- a/sys/dev/pci/hdaudio/hdaudio_pci.c +++ b/sys/dev/pci/hdaudio/hdaudio_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: hdaudio_pci.c,v 1.6 2010/08/07 16:59:48 jmcneill Exp $ */ +/* $NetBSD: hdaudio_pci.c,v 1.7 2011/01/07 15:30:30 jmcneill Exp $ */ /* * Copyright (c) 2009 Precedence Technologies Ltd @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: hdaudio_pci.c,v 1.6 2010/08/07 16:59:48 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hdaudio_pci.c,v 1.7 2011/01/07 15:30:30 jmcneill Exp $"); #include #include @@ -61,6 +61,7 @@ struct hdaudio_pci_softc { static int hdaudio_pci_match(device_t, cfdata_t, void *); static void hdaudio_pci_attach(device_t, device_t, void *); static int hdaudio_pci_detach(device_t, int); +static int hdaudio_pci_rescan(device_t, const char *, const int *); static void hdaudio_pci_childdet(device_t, device_t); static int hdaudio_pci_intr(void *); @@ -75,7 +76,7 @@ CFATTACH_DECL2_NEW( hdaudio_pci_attach, hdaudio_pci_detach, NULL, - NULL, + hdaudio_pci_rescan, hdaudio_pci_childdet ); @@ -170,14 +171,20 @@ hdaudio_pci_attach(device_t parent, device_t self, void *opaque) hdaudio_attach(self, &sc->sc_hdaudio); } +static int +hdaudio_pci_rescan(device_t self, const char *ifattr, const int *locs) +{ + struct hdaudio_pci_softc *sc = device_private(self); + + return hdaudio_rescan(&sc->sc_hdaudio, ifattr, locs); +} + void hdaudio_pci_childdet(device_t self, device_t child) { -#if notyet struct hdaudio_pci_softc *sc = device_private(self); hdaudio_childdet(&sc->sc_hdaudio, child); -#endif } static int diff --git a/sys/dev/pci/hdaudio/hdaudiovar.h b/sys/dev/pci/hdaudio/hdaudiovar.h index fa54af11b0cd..cd727ade30e0 100644 --- a/sys/dev/pci/hdaudio/hdaudiovar.h +++ b/sys/dev/pci/hdaudio/hdaudiovar.h @@ -1,4 +1,4 @@ -/* $NetBSD: hdaudiovar.h,v 1.6 2010/08/15 19:39:56 jmcneill Exp $ */ +/* $NetBSD: hdaudiovar.h,v 1.7 2011/01/07 15:30:30 jmcneill Exp $ */ /* * Copyright (c) 2009 Precedence Technologies Ltd @@ -163,6 +163,9 @@ struct hdaudio_softc { int hdaudio_attach(device_t, struct hdaudio_softc *); int hdaudio_detach(struct hdaudio_softc *, int); bool hdaudio_resume(struct hdaudio_softc *); +int hdaudio_rescan(struct hdaudio_softc *, const char *, const int *); +void hdaudio_childdet(struct hdaudio_softc *, device_t); + uint32_t hdaudio_command(struct hdaudio_codec *, int, uint32_t, uint32_t); int hdaudio_intr(struct hdaudio_softc *); @@ -180,7 +183,4 @@ void hdaudio_stream_reset(struct hdaudio_stream *); int hdaudio_stream_tag(struct hdaudio_stream *); uint16_t hdaudio_stream_param(struct hdaudio_stream *, const audio_params_t *); -int hdaudio_afg_widget_info(void *, prop_dictionary_t, prop_dictionary_t); -int hdaudio_afg_codec_info(void *, prop_dictionary_t, prop_dictionary_t); - #endif /* !_HDAUDIOVAR_H */