Sun Jul 26 17:54:46 2015 UTC ()
set HDAUDIO_FLAG_NO_STREAM_RESET quirk


(jmcneill)
diff -r1.3 -r1.4 src/sys/arch/arm/nvidia/tegra_hdaudio.c

cvs diff -r1.3 -r1.4 src/sys/arch/arm/nvidia/tegra_hdaudio.c (switch to unified diff)

--- src/sys/arch/arm/nvidia/tegra_hdaudio.c 2015/05/10 11:04:59 1.3
+++ src/sys/arch/arm/nvidia/tegra_hdaudio.c 2015/07/26 17:54:46 1.4
@@ -1,180 +1,181 @@ @@ -1,180 +1,181 @@
1/* $NetBSD: tegra_hdaudio.c,v 1.3 2015/05/10 11:04:59 jmcneill Exp $ */ 1/* $NetBSD: tegra_hdaudio.c,v 1.4 2015/07/26 17:54:46 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include "locators.h" 29#include "locators.h"
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: tegra_hdaudio.c,v 1.3 2015/05/10 11:04:59 jmcneill Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: tegra_hdaudio.c,v 1.4 2015/07/26 17:54:46 jmcneill Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/bus.h> 35#include <sys/bus.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/intr.h> 37#include <sys/intr.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40 40
41#include <dev/hdaudio/hdaudioreg.h> 41#include <dev/hdaudio/hdaudioreg.h>
42#include <dev/hdaudio/hdaudiovar.h> 42#include <dev/hdaudio/hdaudiovar.h>
43 43
44#include <arm/nvidia/tegra_var.h> 44#include <arm/nvidia/tegra_var.h>
45#include <arm/nvidia/tegra_pmcreg.h> 45#include <arm/nvidia/tegra_pmcreg.h>
46#include <arm/nvidia/tegra_hdaudioreg.h> 46#include <arm/nvidia/tegra_hdaudioreg.h>
47 47
48#define TEGRA_HDAUDIO_OFFSET 0x8000 48#define TEGRA_HDAUDIO_OFFSET 0x8000
49 49
50#define TEGRA_HDA_IFPS_BAR0_REG 0x0080 50#define TEGRA_HDA_IFPS_BAR0_REG 0x0080
51#define TEGRA_HDA_IFPS_CONFIG_REG 0x0180 51#define TEGRA_HDA_IFPS_CONFIG_REG 0x0180
52#define TEGRA_HDA_IFPS_INTR_REG 0x0188 52#define TEGRA_HDA_IFPS_INTR_REG 0x0188
53#define TEGRA_HDA_CFG_CMD_REG 0x1004 53#define TEGRA_HDA_CFG_CMD_REG 0x1004
54#define TEGRA_HDA_CFG_BAR0_REG 0x1010 54#define TEGRA_HDA_CFG_BAR0_REG 0x1010
55 55
56static int tegra_hdaudio_match(device_t, cfdata_t, void *); 56static int tegra_hdaudio_match(device_t, cfdata_t, void *);
57static void tegra_hdaudio_attach(device_t, device_t, void *); 57static void tegra_hdaudio_attach(device_t, device_t, void *);
58static int tegra_hdaudio_detach(device_t, int); 58static int tegra_hdaudio_detach(device_t, int);
59static int tegra_hdaudio_rescan(device_t, const char *, const int *); 59static int tegra_hdaudio_rescan(device_t, const char *, const int *);
60static void tegra_hdaudio_childdet(device_t, device_t); 60static void tegra_hdaudio_childdet(device_t, device_t);
61 61
62static int tegra_hdaudio_intr(void *); 62static int tegra_hdaudio_intr(void *);
63 63
64struct tegra_hdaudio_softc { 64struct tegra_hdaudio_softc {
65 struct hdaudio_softc sc; 65 struct hdaudio_softc sc;
66 bus_space_tag_t sc_bst; 66 bus_space_tag_t sc_bst;
67 bus_space_handle_t sc_bsh; 67 bus_space_handle_t sc_bsh;
68 void *sc_ih; 68 void *sc_ih;
69}; 69};
70 70
71static void tegra_hdaudio_init(struct tegra_hdaudio_softc *); 71static void tegra_hdaudio_init(struct tegra_hdaudio_softc *);
72 72
73CFATTACH_DECL2_NEW(tegra_hdaudio, sizeof(struct tegra_hdaudio_softc), 73CFATTACH_DECL2_NEW(tegra_hdaudio, sizeof(struct tegra_hdaudio_softc),
74 tegra_hdaudio_match, tegra_hdaudio_attach, tegra_hdaudio_detach, NULL, 74 tegra_hdaudio_match, tegra_hdaudio_attach, tegra_hdaudio_detach, NULL,
75 tegra_hdaudio_rescan, tegra_hdaudio_childdet); 75 tegra_hdaudio_rescan, tegra_hdaudio_childdet);
76 76
77static int 77static int
78tegra_hdaudio_match(device_t parent, cfdata_t cf, void *aux) 78tegra_hdaudio_match(device_t parent, cfdata_t cf, void *aux)
79{ 79{
80 return 1; 80 return 1;
81} 81}
82 82
83static void 83static void
84tegra_hdaudio_attach(device_t parent, device_t self, void *aux) 84tegra_hdaudio_attach(device_t parent, device_t self, void *aux)
85{ 85{
86 struct tegra_hdaudio_softc * const sc = device_private(self); 86 struct tegra_hdaudio_softc * const sc = device_private(self);
87 struct tegraio_attach_args * const tio = aux; 87 struct tegraio_attach_args * const tio = aux;
88 const struct tegra_locators * const loc = &tio->tio_loc; 88 const struct tegra_locators * const loc = &tio->tio_loc;
89 89
90 sc->sc_bst = tio->tio_bst; 90 sc->sc_bst = tio->tio_bst;
91 bus_space_subregion(tio->tio_bst, tio->tio_bsh, 91 bus_space_subregion(tio->tio_bst, tio->tio_bsh,
92 loc->loc_offset, loc->loc_size, &sc->sc_bsh); 92 loc->loc_offset, loc->loc_size, &sc->sc_bsh);
93 93
94 sc->sc.sc_memt = tio->tio_bst; 94 sc->sc.sc_memt = tio->tio_bst;
95 bus_space_subregion(tio->tio_bst, tio->tio_bsh, 95 bus_space_subregion(tio->tio_bst, tio->tio_bsh,
96 loc->loc_offset + TEGRA_HDAUDIO_OFFSET, 96 loc->loc_offset + TEGRA_HDAUDIO_OFFSET,
97 loc->loc_size - TEGRA_HDAUDIO_OFFSET, &sc->sc.sc_memh); 97 loc->loc_size - TEGRA_HDAUDIO_OFFSET, &sc->sc.sc_memh);
98 sc->sc.sc_memvalid = true; 98 sc->sc.sc_memvalid = true;
99 sc->sc.sc_dmat = tio->tio_dmat; 99 sc->sc.sc_dmat = tio->tio_dmat;
 100 sc->sc.sc_flags = HDAUDIO_FLAG_NO_STREAM_RESET;
100 101
101 aprint_naive("\n"); 102 aprint_naive("\n");
102 aprint_normal(": HDA\n"); 103 aprint_normal(": HDA\n");
103 104
104 sc->sc_ih = intr_establish(loc->loc_intr, IPL_AUDIO, IST_LEVEL, 105 sc->sc_ih = intr_establish(loc->loc_intr, IPL_AUDIO, IST_LEVEL,
105 tegra_hdaudio_intr, sc); 106 tegra_hdaudio_intr, sc);
106 if (sc->sc_ih == NULL) { 107 if (sc->sc_ih == NULL) {
107 aprint_error_dev(self, "couldn't establish interrupt %d\n", 108 aprint_error_dev(self, "couldn't establish interrupt %d\n",
108 loc->loc_intr); 109 loc->loc_intr);
109 return; 110 return;
110 } 111 }
111 aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); 112 aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr);
112 113
113 tegra_pmc_power(PMC_PARTID_DISB, true); 114 tegra_pmc_power(PMC_PARTID_DISB, true);
114 tegra_car_periph_hda_enable(); 115 tegra_car_periph_hda_enable();
115 tegra_hdaudio_init(sc); 116 tegra_hdaudio_init(sc);
116 117
117 hdaudio_attach(self, &sc->sc); 118 hdaudio_attach(self, &sc->sc);
118} 119}
119 120
120static void 121static void
121tegra_hdaudio_init(struct tegra_hdaudio_softc *sc) 122tegra_hdaudio_init(struct tegra_hdaudio_softc *sc)
122{ 123{
123 tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_IFPS_CONFIG_REG, 124 tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_IFPS_CONFIG_REG,
124 TEGRA_HDA_IFPS_CONFIG_FPCI_EN, 0); 125 TEGRA_HDA_IFPS_CONFIG_FPCI_EN, 0);
125 tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_CFG_CMD_REG, 126 tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_CFG_CMD_REG,
126 TEGRA_HDA_CFG_CMD_ENABLE_SERR | 127 TEGRA_HDA_CFG_CMD_ENABLE_SERR |
127 TEGRA_HDA_CFG_CMD_BUS_MASTER | 128 TEGRA_HDA_CFG_CMD_BUS_MASTER |
128 TEGRA_HDA_CFG_CMD_MEM_SPACE | 129 TEGRA_HDA_CFG_CMD_MEM_SPACE |
129 TEGRA_HDA_CFG_CMD_IO_SPACE, 130 TEGRA_HDA_CFG_CMD_IO_SPACE,
130 TEGRA_HDA_CFG_CMD_DISABLE_INTR); 131 TEGRA_HDA_CFG_CMD_DISABLE_INTR);
131 bus_space_write_4(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_CFG_BAR0_REG, 132 bus_space_write_4(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_CFG_BAR0_REG,
132 0xffffffff); 133 0xffffffff);
133 bus_space_write_4(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_CFG_BAR0_REG, 134 bus_space_write_4(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_CFG_BAR0_REG,
134 0x00004000); 135 0x00004000);
135 bus_space_write_4(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_IFPS_BAR0_REG, 136 bus_space_write_4(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_IFPS_BAR0_REG,
136 TEGRA_HDA_CFG_BAR0_START); 137 TEGRA_HDA_CFG_BAR0_START);
137 tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_IFPS_INTR_REG, 138 tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, TEGRA_HDA_IFPS_INTR_REG,
138 TEGRA_HDA_IFPS_INTR_EN, 0); 139 TEGRA_HDA_IFPS_INTR_EN, 0);
139} 140}
140 141
141static int 142static int
142tegra_hdaudio_detach(device_t self, int flags) 143tegra_hdaudio_detach(device_t self, int flags)
143{ 144{
144 struct tegra_hdaudio_softc * const sc = device_private(self); 145 struct tegra_hdaudio_softc * const sc = device_private(self);
145 146
146 hdaudio_detach(&sc->sc, flags); 147 hdaudio_detach(&sc->sc, flags);
147 148
148 if (sc->sc_ih) { 149 if (sc->sc_ih) {
149 intr_disestablish(sc->sc_ih); 150 intr_disestablish(sc->sc_ih);
150 sc->sc_ih = NULL; 151 sc->sc_ih = NULL;
151 } 152 }
152 153
153 sc->sc.sc_memvalid = false; 154 sc->sc.sc_memvalid = false;
154 155
155 return 0; 156 return 0;
156} 157}
157 158
158static int 159static int
159tegra_hdaudio_rescan(device_t self, const char *ifattr, const int *locs) 160tegra_hdaudio_rescan(device_t self, const char *ifattr, const int *locs)
160{ 161{
161 struct tegra_hdaudio_softc * const sc = device_private(self); 162 struct tegra_hdaudio_softc * const sc = device_private(self);
162 163
163 return hdaudio_rescan(&sc->sc, ifattr, locs); 164 return hdaudio_rescan(&sc->sc, ifattr, locs);
164} 165}
165 166
166static void 167static void
167tegra_hdaudio_childdet(device_t self, device_t child) 168tegra_hdaudio_childdet(device_t self, device_t child)
168{ 169{
169 struct tegra_hdaudio_softc * const sc = device_private(self); 170 struct tegra_hdaudio_softc * const sc = device_private(self);
170 171
171 hdaudio_childdet(&sc->sc, child); 172 hdaudio_childdet(&sc->sc, child);
172} 173}
173 174
174static int 175static int
175tegra_hdaudio_intr(void *priv) 176tegra_hdaudio_intr(void *priv)
176{ 177{
177 struct tegra_hdaudio_softc * const sc = priv; 178 struct tegra_hdaudio_softc * const sc = priv;
178 179
179 return hdaudio_intr(&sc->sc); 180 return hdaudio_intr(&sc->sc);
180} 181}