| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: audio.c,v 1.277 2016/12/11 10:28:00 martin Exp $ */ | | 1 | /* $NetBSD: audio.c,v 1.278 2016/12/13 17:12:51 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> | | 4 | * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 7 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
8 | * All rights reserved. | | 8 | * All rights reserved. |
9 | * | | 9 | * |
10 | * This code is derived from software contributed to The NetBSD Foundation | | 10 | * This code is derived from software contributed to The NetBSD Foundation |
11 | * by Andrew Doran. | | 11 | * by Andrew Doran. |
12 | * | | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | | 13 | * Redistribution and use in source and binary forms, with or without |
14 | * modification, are permitted provided that the following conditions | | 14 | * modification, are permitted provided that the following conditions |
| @@ -138,27 +138,27 @@ | | | @@ -138,27 +138,27 @@ |
138 | * query_devinfo - x | | 138 | * query_devinfo - x |
139 | * allocm - - Called at attach time | | 139 | * allocm - - Called at attach time |
140 | * freem - - Called at attach time | | 140 | * freem - - Called at attach time |
141 | * round_buffersize - x | | 141 | * round_buffersize - x |
142 | * mappage - - Mem. unchanged after attach | | 142 | * mappage - - Mem. unchanged after attach |
143 | * get_props - x | | 143 | * get_props - x |
144 | * trigger_output x x | | 144 | * trigger_output x x |
145 | * trigger_input x x | | 145 | * trigger_input x x |
146 | * dev_ioctl - x | | 146 | * dev_ioctl - x |
147 | * get_locks - - Called at attach time | | 147 | * get_locks - - Called at attach time |
148 | */ | | 148 | */ |
149 | | | 149 | |
150 | #include <sys/cdefs.h> | | 150 | #include <sys/cdefs.h> |
151 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.277 2016/12/11 10:28:00 martin Exp $"); | | 151 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.278 2016/12/13 17:12:51 christos Exp $"); |
152 | | | 152 | |
153 | #include "audio.h" | | 153 | #include "audio.h" |
154 | #if NAUDIO > 0 | | 154 | #if NAUDIO > 0 |
155 | | | 155 | |
156 | #include <sys/types.h> | | 156 | #include <sys/types.h> |
157 | #include <sys/param.h> | | 157 | #include <sys/param.h> |
158 | #include <sys/ioctl.h> | | 158 | #include <sys/ioctl.h> |
159 | #include <sys/fcntl.h> | | 159 | #include <sys/fcntl.h> |
160 | #include <sys/vnode.h> | | 160 | #include <sys/vnode.h> |
161 | #include <sys/select.h> | | 161 | #include <sys/select.h> |
162 | #include <sys/poll.h> | | 162 | #include <sys/poll.h> |
163 | #include <sys/kmem.h> | | 163 | #include <sys/kmem.h> |
164 | #include <sys/malloc.h> | | 164 | #include <sys/malloc.h> |
| @@ -295,26 +295,28 @@ static void stream_filter_list_prepend | | | @@ -295,26 +295,28 @@ static void stream_filter_list_prepend |
295 | const audio_params_t *); | | 295 | const audio_params_t *); |
296 | static void stream_filter_list_set | | 296 | static void stream_filter_list_set |
297 | (stream_filter_list_t *, int, stream_filter_factory_t, | | 297 | (stream_filter_list_t *, int, stream_filter_factory_t, |
298 | const audio_params_t *); | | 298 | const audio_params_t *); |
299 | int audio_set_defaults(struct audio_softc *, u_int, int); | | 299 | int audio_set_defaults(struct audio_softc *, u_int, int); |
300 | static int audio_sysctl_frequency(SYSCTLFN_PROTO); | | 300 | static int audio_sysctl_frequency(SYSCTLFN_PROTO); |
301 | static int audio_sysctl_precision(SYSCTLFN_PROTO); | | 301 | static int audio_sysctl_precision(SYSCTLFN_PROTO); |
302 | static int audio_sysctl_channels(SYSCTLFN_PROTO); | | 302 | static int audio_sysctl_channels(SYSCTLFN_PROTO); |
303 | | | 303 | |
304 | int audioprobe(device_t, cfdata_t, void *); | | 304 | int audioprobe(device_t, cfdata_t, void *); |
305 | void audioattach(device_t, device_t, void *); | | 305 | void audioattach(device_t, device_t, void *); |
306 | int audiodetach(device_t, int); | | 306 | int audiodetach(device_t, int); |
307 | int audioactivate(device_t, enum devact); | | 307 | int audioactivate(device_t, enum devact); |
| | | 308 | void audiochilddet(device_t, device_t); |
| | | 309 | int audiorescan(device_t, const char *, const int *); |
308 | | | 310 | |
309 | #ifdef AUDIO_PM_IDLE | | 311 | #ifdef AUDIO_PM_IDLE |
310 | static void audio_idle(void *); | | 312 | static void audio_idle(void *); |
311 | static void audio_activity(device_t, devactive_t); | | 313 | static void audio_activity(device_t, devactive_t); |
312 | #endif | | 314 | #endif |
313 | | | 315 | |
314 | static bool audio_suspend(device_t dv, const pmf_qual_t *); | | 316 | static bool audio_suspend(device_t dv, const pmf_qual_t *); |
315 | static bool audio_resume(device_t dv, const pmf_qual_t *); | | 317 | static bool audio_resume(device_t dv, const pmf_qual_t *); |
316 | static void audio_volume_down(device_t); | | 318 | static void audio_volume_down(device_t); |
317 | static void audio_volume_up(device_t); | | 319 | static void audio_volume_up(device_t); |
318 | static void audio_volume_toggle(device_t); | | 320 | static void audio_volume_toggle(device_t); |
319 | | | 321 | |
320 | static void audio_mixer_capture(struct audio_softc *); | | 322 | static void audio_mixer_capture(struct audio_softc *); |
| @@ -426,28 +428,28 @@ struct audio_params vchan_default = { | | | @@ -426,28 +428,28 @@ struct audio_params vchan_default = { |
426 | .channels = 2, | | 428 | .channels = 2, |
427 | }; | | 429 | }; |
428 | | | 430 | |
429 | /* The default audio mode: 8 kHz mono mu-law */ | | 431 | /* The default audio mode: 8 kHz mono mu-law */ |
430 | const struct audio_params audio_default = { | | 432 | const struct audio_params audio_default = { |
431 | .sample_rate = 8000, | | 433 | .sample_rate = 8000, |
432 | .encoding = AUDIO_ENCODING_ULAW, | | 434 | .encoding = AUDIO_ENCODING_ULAW, |
433 | .precision = 8, | | 435 | .precision = 8, |
434 | .validbits = 8, | | 436 | .validbits = 8, |
435 | .channels = 1, | | 437 | .channels = 1, |
436 | }; | | 438 | }; |
437 | | | 439 | |
438 | CFATTACH_DECL3_NEW(audio, sizeof(struct audio_softc), | | 440 | CFATTACH_DECL3_NEW(audio, sizeof(struct audio_softc), |
439 | audioprobe, audioattach, audiodetach, audioactivate, NULL, NULL, | | 441 | audioprobe, audioattach, audiodetach, audioactivate, audiorescan, |
440 | DVF_DETACH_SHUTDOWN); | | 442 | audiochilddet, DVF_DETACH_SHUTDOWN); |
441 | | | 443 | |
442 | extern struct cfdriver audio_cd; | | 444 | extern struct cfdriver audio_cd; |
443 | | | 445 | |
444 | int | | 446 | int |
445 | audioprobe(device_t parent, cfdata_t match, void *aux) | | 447 | audioprobe(device_t parent, cfdata_t match, void *aux) |
446 | { | | 448 | { |
447 | struct audio_attach_args *sa; | | 449 | struct audio_attach_args *sa; |
448 | | | 450 | |
449 | sa = aux; | | 451 | sa = aux; |
450 | DPRINTF(("audioprobe: type=%d sa=%p hw=%p\n", | | 452 | DPRINTF(("audioprobe: type=%d sa=%p hw=%p\n", |
451 | sa->type, sa, sa->hwif)); | | 453 | sa->type, sa, sa->hwif)); |
452 | return (sa->type == AUDIODEV_TYPE_AUDIO) ? 1 : 0; | | 454 | return (sa->type == AUDIODEV_TYPE_AUDIO) ? 1 : 0; |
453 | } | | 455 | } |
| @@ -827,26 +829,27 @@ bad_rec: | | | @@ -827,26 +829,27 @@ bad_rec: |
827 | audio_volume_up, true)) | | 829 | audio_volume_up, true)) |
828 | aprint_error_dev(self, "couldn't add volume up handler\n"); | | 830 | aprint_error_dev(self, "couldn't add volume up handler\n"); |
829 | if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_TOGGLE, | | 831 | if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_TOGGLE, |
830 | audio_volume_toggle, true)) | | 832 | audio_volume_toggle, true)) |
831 | aprint_error_dev(self, "couldn't add volume toggle handler\n"); | | 833 | aprint_error_dev(self, "couldn't add volume toggle handler\n"); |
832 | | | 834 | |
833 | #ifdef AUDIO_PM_IDLE | | 835 | #ifdef AUDIO_PM_IDLE |
834 | callout_schedule(&sc->sc_idle_counter, audio_idle_timeout * hz); | | 836 | callout_schedule(&sc->sc_idle_counter, audio_idle_timeout * hz); |
835 | #endif | | 837 | #endif |
836 | kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, | | 838 | kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, |
837 | audio_rec_thread, sc, &sc->sc_recthread, "audiorec"); | | 839 | audio_rec_thread, sc, &sc->sc_recthread, "audiorec"); |
838 | kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, | | 840 | kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, |
839 | audio_play_thread, sc, &sc->sc_playthread, "audiomix"); | | 841 | audio_play_thread, sc, &sc->sc_playthread, "audiomix"); |
| | | 842 | audiorescan(self, "audio", NULL); |
840 | } | | 843 | } |
841 | | | 844 | |
842 | int | | 845 | int |
843 | audioactivate(device_t self, enum devact act) | | 846 | audioactivate(device_t self, enum devact act) |
844 | { | | 847 | { |
845 | struct audio_softc *sc = device_private(self); | | 848 | struct audio_softc *sc = device_private(self); |
846 | | | 849 | |
847 | switch (act) { | | 850 | switch (act) { |
848 | case DVACT_DEACTIVATE: | | 851 | case DVACT_DEACTIVATE: |
849 | mutex_enter(sc->sc_lock); | | 852 | mutex_enter(sc->sc_lock); |
850 | sc->sc_dying = true; | | 853 | sc->sc_dying = true; |
851 | mutex_exit(sc->sc_lock); | | 854 | mutex_exit(sc->sc_lock); |
852 | return 0; | | 855 | return 0; |
| @@ -961,26 +964,57 @@ audiodetach(device_t self, int flags) | | | @@ -961,26 +964,57 @@ audiodetach(device_t self, int flags) |
961 | #ifdef AUDIO_PM_IDLE | | 964 | #ifdef AUDIO_PM_IDLE |
962 | callout_destroy(&sc->sc_idle_counter); | | 965 | callout_destroy(&sc->sc_idle_counter); |
963 | #endif | | 966 | #endif |
964 | seldestroy(&sc->sc_rsel); | | 967 | seldestroy(&sc->sc_rsel); |
965 | seldestroy(&sc->sc_wsel); | | 968 | seldestroy(&sc->sc_wsel); |
966 | | | 969 | |
967 | cv_destroy(&sc->sc_rchan); | | 970 | cv_destroy(&sc->sc_rchan); |
968 | cv_destroy(&sc->sc_wchan); | | 971 | cv_destroy(&sc->sc_wchan); |
969 | cv_destroy(&sc->sc_lchan); | | 972 | cv_destroy(&sc->sc_lchan); |
970 | | | 973 | |
971 | return 0; | | 974 | return 0; |
972 | } | | 975 | } |
973 | | | 976 | |
| | | 977 | void |
| | | 978 | audiochilddet(device_t self, device_t child) |
| | | 979 | { |
| | | 980 | |
| | | 981 | /* we hold no child references, so do nothing */ |
| | | 982 | } |
| | | 983 | |
| | | 984 | static int |
| | | 985 | audiosearch(device_t parent, cfdata_t cf, const int *locs, void *aux) |
| | | 986 | { |
| | | 987 | |
| | | 988 | if (config_match(parent, cf, aux)) |
| | | 989 | config_attach_loc(parent, cf, locs, aux, NULL); |
| | | 990 | |
| | | 991 | return 0; |
| | | 992 | } |
| | | 993 | |
| | | 994 | int |
| | | 995 | audiorescan(device_t self, const char *ifattr, const int *flags) |
| | | 996 | { |
| | | 997 | struct audio_softc *sc = device_private(self); |
| | | 998 | |
| | | 999 | if (!ifattr_match(ifattr, "audio")) |
| | | 1000 | return 0; |
| | | 1001 | |
| | | 1002 | config_search_loc(audiosearch, sc->dev, "audio", NULL, NULL); |
| | | 1003 | |
| | | 1004 | return 0; |
| | | 1005 | } |
| | | 1006 | |
| | | 1007 | |
974 | int | | 1008 | int |
975 | au_portof(struct audio_softc *sc, char *name, int class) | | 1009 | au_portof(struct audio_softc *sc, char *name, int class) |
976 | { | | 1010 | { |
977 | mixer_devinfo_t mi; | | 1011 | mixer_devinfo_t mi; |
978 | | | 1012 | |
979 | for (mi.index = 0; audio_query_devinfo(sc, &mi) == 0; mi.index++) { | | 1013 | for (mi.index = 0; audio_query_devinfo(sc, &mi) == 0; mi.index++) { |
980 | if (mi.mixer_class == class && strcmp(mi.label.name, name) == 0) | | 1014 | if (mi.mixer_class == class && strcmp(mi.label.name, name) == 0) |
981 | return mi.index; | | 1015 | return mi.index; |
982 | } | | 1016 | } |
983 | return -1; | | 1017 | return -1; |
984 | } | | 1018 | } |
985 | | | 1019 | |
986 | void | | 1020 | void |