| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: audio.c,v 1.75 2020/05/29 03:09:14 isaki Exp $ */ | | 1 | /* $NetBSD: audio.c,v 1.76 2020/08/23 04:07:23 isaki Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Andrew Doran. | | 8 | * by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -128,27 +128,27 @@ | | | @@ -128,27 +128,27 @@ |
128 | * get_locks - - Called at attach time | | 128 | * get_locks - - Called at attach time |
129 | * | | 129 | * |
130 | * In addition, there is an additional lock. | | 130 | * In addition, there is an additional lock. |
131 | * | | 131 | * |
132 | * - track->lock. This is an atomic variable and is similar to the | | 132 | * - track->lock. This is an atomic variable and is similar to the |
133 | * "interrupt lock". This is one for each track. If any thread context | | 133 | * "interrupt lock". This is one for each track. If any thread context |
134 | * (and software interrupt context) and hardware interrupt context who | | 134 | * (and software interrupt context) and hardware interrupt context who |
135 | * want to access some variables on this track, they must acquire this | | 135 | * want to access some variables on this track, they must acquire this |
136 | * lock before. It protects track's consistency between hardware | | 136 | * lock before. It protects track's consistency between hardware |
137 | * interrupt context and others. | | 137 | * interrupt context and others. |
138 | */ | | 138 | */ |
139 | | | 139 | |
140 | #include <sys/cdefs.h> | | 140 | #include <sys/cdefs.h> |
141 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.75 2020/05/29 03:09:14 isaki Exp $"); | | 141 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.76 2020/08/23 04:07:23 isaki Exp $"); |
142 | | | 142 | |
143 | #ifdef _KERNEL_OPT | | 143 | #ifdef _KERNEL_OPT |
144 | #include "audio.h" | | 144 | #include "audio.h" |
145 | #include "midi.h" | | 145 | #include "midi.h" |
146 | #endif | | 146 | #endif |
147 | | | 147 | |
148 | #if NAUDIO > 0 | | 148 | #if NAUDIO > 0 |
149 | | | 149 | |
150 | #include <sys/types.h> | | 150 | #include <sys/types.h> |
151 | #include <sys/param.h> | | 151 | #include <sys/param.h> |
152 | #include <sys/atomic.h> | | 152 | #include <sys/atomic.h> |
153 | #include <sys/audioio.h> | | 153 | #include <sys/audioio.h> |
154 | #include <sys/conf.h> | | 154 | #include <sys/conf.h> |
| @@ -891,33 +891,35 @@ audioattach(device_t parent, device_t se | | | @@ -891,33 +891,35 @@ audioattach(device_t parent, device_t se |
891 | has_fulldup = (sc->sc_props & AUDIO_PROP_FULLDUPLEX); | | 891 | has_fulldup = (sc->sc_props & AUDIO_PROP_FULLDUPLEX); |
892 | | | 892 | |
893 | #ifdef DIAGNOSTIC | | 893 | #ifdef DIAGNOSTIC |
894 | if (hw_if->query_format == NULL || | | 894 | if (hw_if->query_format == NULL || |
895 | hw_if->set_format == NULL || | | 895 | hw_if->set_format == NULL || |
896 | hw_if->getdev == NULL || | | 896 | hw_if->getdev == NULL || |
897 | hw_if->set_port == NULL || | | 897 | hw_if->set_port == NULL || |
898 | hw_if->get_port == NULL || | | 898 | hw_if->get_port == NULL || |
899 | hw_if->query_devinfo == NULL) { | | 899 | hw_if->query_devinfo == NULL) { |
900 | aprint_error(": missing mandatory method\n"); | | 900 | aprint_error(": missing mandatory method\n"); |
901 | return; | | 901 | return; |
902 | } | | 902 | } |
903 | if (has_playback) { | | 903 | if (has_playback) { |
904 | if ((hw_if->start_output == NULL && hw_if->trigger_output == NULL) || | | 904 | if ((hw_if->start_output == NULL && |
| | | 905 | hw_if->trigger_output == NULL) || |
905 | hw_if->halt_output == NULL) { | | 906 | hw_if->halt_output == NULL) { |
906 | aprint_error(": missing playback method\n"); | | 907 | aprint_error(": missing playback method\n"); |
907 | } | | 908 | } |
908 | } | | 909 | } |
909 | if (has_capture) { | | 910 | if (has_capture) { |
910 | if ((hw_if->start_input == NULL && hw_if->trigger_input == NULL) || | | 911 | if ((hw_if->start_input == NULL && |
| | | 912 | hw_if->trigger_input == NULL) || |
911 | hw_if->halt_input == NULL) { | | 913 | hw_if->halt_input == NULL) { |
912 | aprint_error(": missing capture method\n"); | | 914 | aprint_error(": missing capture method\n"); |
913 | } | | 915 | } |
914 | } | | 916 | } |
915 | #endif | | 917 | #endif |
916 | | | 918 | |
917 | sc->hw_if = hw_if; | | 919 | sc->hw_if = hw_if; |
918 | sc->hw_hdl = hdlp; | | 920 | sc->hw_hdl = hdlp; |
919 | sc->hw_dev = parent; | | 921 | sc->hw_dev = parent; |
920 | | | 922 | |
921 | sc->sc_exlock = 1; | | 923 | sc->sc_exlock = 1; |
922 | sc->sc_blk_ms = AUDIO_BLK_MS; | | 924 | sc->sc_blk_ms = AUDIO_BLK_MS; |
923 | SLIST_INIT(&sc->sc_files); | | 925 | SLIST_INIT(&sc->sc_files); |
| @@ -6119,27 +6121,27 @@ audio_softintr_wr(void *cookie) | | | @@ -6119,27 +6121,27 @@ audio_softintr_wr(void *cookie) |
6119 | } | | 6121 | } |
6120 | | | 6122 | |
6121 | /* | | 6123 | /* |
6122 | * Check (and convert) the format *p came from userland. | | 6124 | * Check (and convert) the format *p came from userland. |
6123 | * If successful, it writes back the converted format to *p if necessary | | 6125 | * If successful, it writes back the converted format to *p if necessary |
6124 | * and returns 0. Otherwise returns errno (*p may change even this case). | | 6126 | * and returns 0. Otherwise returns errno (*p may change even this case). |
6125 | */ | | 6127 | */ |
6126 | static int | | 6128 | static int |
6127 | audio_check_params(audio_format2_t *p) | | 6129 | audio_check_params(audio_format2_t *p) |
6128 | { | | 6130 | { |
6129 | | | 6131 | |
6130 | /* | | 6132 | /* |
6131 | * Convert obsolete AUDIO_ENCODING_PCM encodings. | | 6133 | * Convert obsolete AUDIO_ENCODING_PCM encodings. |
6132 | * | | 6134 | * |
6133 | * AUDIO_ENCODING_PCM16 == AUDIO_ENCODING_LINEAR | | 6135 | * AUDIO_ENCODING_PCM16 == AUDIO_ENCODING_LINEAR |
6134 | * So, it's always signed, as in SunOS. | | 6136 | * So, it's always signed, as in SunOS. |
6135 | * | | 6137 | * |
6136 | * AUDIO_ENCODING_PCM8 == AUDIO_ENCODING_LINEAR8 | | 6138 | * AUDIO_ENCODING_PCM8 == AUDIO_ENCODING_LINEAR8 |
6137 | * So, it's always unsigned, as in SunOS. | | 6139 | * So, it's always unsigned, as in SunOS. |
6138 | */ | | 6140 | */ |
6139 | if (p->encoding == AUDIO_ENCODING_PCM16) { | | 6141 | if (p->encoding == AUDIO_ENCODING_PCM16) { |
6140 | p->encoding = AUDIO_ENCODING_SLINEAR; | | 6142 | p->encoding = AUDIO_ENCODING_SLINEAR; |
6141 | } else if (p->encoding == AUDIO_ENCODING_PCM8) { | | 6143 | } else if (p->encoding == AUDIO_ENCODING_PCM8) { |
6142 | if (p->precision == 8) | | 6144 | if (p->precision == 8) |
6143 | p->encoding = AUDIO_ENCODING_ULINEAR; | | 6145 | p->encoding = AUDIO_ENCODING_ULINEAR; |
6144 | else | | 6146 | else |
6145 | return EINVAL; | | 6147 | return EINVAL; |
| @@ -6422,27 +6424,27 @@ audio_hw_probe(struct audio_softc *sc, a | | | @@ -6422,27 +6424,27 @@ audio_hw_probe(struct audio_softc *sc, a |
6422 | return ENXIO; | | 6424 | return ENXIO; |
6423 | } | | 6425 | } |
6424 | DPRINTF(1, "%s selected: %s,%d/%d,%dch,%dHz\n", __func__, | | 6426 | DPRINTF(1, "%s selected: %s,%d/%d,%dch,%dHz\n", __func__, |
6425 | audio_encoding_name(cand->encoding), | | 6427 | audio_encoding_name(cand->encoding), |
6426 | cand->precision, cand->stride, cand->channels, cand->sample_rate); | | 6428 | cand->precision, cand->stride, cand->channels, cand->sample_rate); |
6427 | return 0; | | 6429 | return 0; |
6428 | } | | 6430 | } |
6429 | | | 6431 | |
6430 | /* | | 6432 | /* |
6431 | * Validate fmt with query_format. | | 6433 | * Validate fmt with query_format. |
6432 | * If fmt is included in the result of query_format, returns 0. | | 6434 | * If fmt is included in the result of query_format, returns 0. |
6433 | * Otherwise returns EINVAL. | | 6435 | * Otherwise returns EINVAL. |
6434 | * Must be called without sc_lock held. | | 6436 | * Must be called without sc_lock held. |
6435 | */ | | 6437 | */ |
6436 | static int | | 6438 | static int |
6437 | audio_hw_validate_format(struct audio_softc *sc, int mode, | | 6439 | audio_hw_validate_format(struct audio_softc *sc, int mode, |
6438 | const audio_format2_t *fmt) | | 6440 | const audio_format2_t *fmt) |
6439 | { | | 6441 | { |
6440 | audio_format_query_t query; | | 6442 | audio_format_query_t query; |
6441 | struct audio_format *q; | | 6443 | struct audio_format *q; |
6442 | int index; | | 6444 | int index; |
6443 | int error; | | 6445 | int error; |
6444 | int j; | | 6446 | int j; |
6445 | | | 6447 | |
6446 | for (index = 0; ; index++) { | | 6448 | for (index = 0; ; index++) { |
6447 | query.index = index; | | 6449 | query.index = index; |
6448 | mutex_enter(sc->sc_lock); | | 6450 | mutex_enter(sc->sc_lock); |