1 1.70 macallan /* $NetBSD: snapper.c,v 1.70 2025/09/08 08:06:19 macallan Exp $ */ 2 1.1 grant /* Id: snapper.c,v 1.11 2002/10/31 17:42:13 tsubai Exp */ 3 1.24 macallan /* Id: i2s.c,v 1.12 2005/01/15 14:32:35 tsubai Exp */ 4 1.24 macallan 5 1.1 grant /*- 6 1.14 macallan * Copyright (c) 2002, 2003 Tsubai Masanari. All rights reserved. 7 1.1 grant * 8 1.1 grant * Redistribution and use in source and binary forms, with or without 9 1.1 grant * modification, are permitted provided that the following conditions 10 1.1 grant * are met: 11 1.1 grant * 1. Redistributions of source code must retain the above copyright 12 1.1 grant * notice, this list of conditions and the following disclaimer. 13 1.1 grant * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 grant * notice, this list of conditions and the following disclaimer in the 15 1.1 grant * documentation and/or other materials provided with the distribution. 16 1.1 grant * 3. The name of the author may not be used to endorse or promote products 17 1.1 grant * derived from this software without specific prior written permission. 18 1.1 grant * 19 1.1 grant * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 1.1 grant * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 1.1 grant * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 grant * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 grant * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 1.1 grant * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 1.1 grant * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 1.1 grant * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 1.1 grant * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 1.1 grant * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 1.1 grant */ 30 1.1 grant 31 1.1 grant /* 32 1.1 grant * Datasheet is available from 33 1.1 grant * http://www.ti.com/sc/docs/products/analog/tas3004.html 34 1.24 macallan * http://www.ti.com/sc/docs/products/analog/tas3001.html 35 1.1 grant */ 36 1.1 grant 37 1.24 macallan #include <sys/cdefs.h> 38 1.70 macallan __KERNEL_RCSID(0, "$NetBSD: snapper.c,v 1.70 2025/09/08 08:06:19 macallan Exp $"); 39 1.24 macallan 40 1.1 grant #include <sys/param.h> 41 1.1 grant #include <sys/audioio.h> 42 1.1 grant #include <sys/device.h> 43 1.1 grant #include <sys/systm.h> 44 1.1 grant 45 1.50 isaki #include <dev/audio/audio_if.h> 46 1.1 grant #include <dev/ofw/openfirm.h> 47 1.1 grant #include <macppc/dev/dbdma.h> 48 1.1 grant 49 1.1 grant #include <uvm/uvm_extern.h> 50 1.6 macallan #include <dev/i2c/i2cvar.h> 51 1.55 macallan #include <dev/onewire/onewirevar.h> 52 1.1 grant 53 1.1 grant #include <machine/autoconf.h> 54 1.1 grant #include <machine/pio.h> 55 1.1 grant 56 1.6 macallan #include <macppc/dev/deqvar.h> 57 1.30 macallan #include <macppc/dev/obiovar.h> 58 1.69 macallan #include <macppc/dev/i2sreg.h> 59 1.55 macallan 60 1.55 macallan #include "opt_snapper.h" 61 1.55 macallan 62 1.1 grant #ifdef SNAPPER_DEBUG 63 1.1 grant # define DPRINTF printf 64 1.1 grant #else 65 1.1 grant # define DPRINTF while (0) printf 66 1.1 grant #endif 67 1.1 grant 68 1.24 macallan #define SNAPPER_MAXPAGES 16 69 1.24 macallan 70 1.1 grant struct snapper_softc { 71 1.26 macallan device_t sc_dev; 72 1.53 macallan int sc_mode; 73 1.53 macallan #define SNAPPER_IS_TAS3004 0 // codec is TAS3004 74 1.24 macallan #define SNAPPER_IS_TAS3001 1 // codec is TAS3001 75 1.53 macallan #define SNAPPER_IS_PCM3052 2 // codec is PCM3052 76 1.53 macallan #define SNAPPER_IS_CS8416 3 // codec is CS8416 77 1.53 macallan #define SNAPPER_SWVOL 4 // software codec 78 1.24 macallan 79 1.1 grant int sc_node; 80 1.1 grant 81 1.1 grant void (*sc_ointr)(void *); /* dma completion intr handler */ 82 1.1 grant void *sc_oarg; /* arg for sc_ointr() */ 83 1.1 grant int sc_opages; /* # of output pages */ 84 1.1 grant 85 1.1 grant void (*sc_iintr)(void *); /* dma completion intr handler */ 86 1.1 grant void *sc_iarg; /* arg for sc_iintr() */ 87 1.10 macallan int sc_ipages; /* # of input pages */ 88 1.1 grant 89 1.1 grant u_int sc_record_source; /* recording source mask */ 90 1.1 grant u_int sc_output_mask; /* output source mask */ 91 1.1 grant 92 1.23 garbled bus_space_tag_t sc_tag; 93 1.23 garbled bus_space_handle_t sc_bsh; 94 1.6 macallan i2c_addr_t sc_deqaddr; 95 1.6 macallan i2c_tag_t sc_i2c; 96 1.24 macallan uint32_t sc_baseaddr; 97 1.1 grant 98 1.14 macallan int sc_rate; /* current sampling rate */ 99 1.14 macallan int sc_bitspersample; 100 1.24 macallan 101 1.50 isaki /* for SNAPPER_SWVOL */ 102 1.50 isaki u_int sc_swvol_l; 103 1.50 isaki u_int sc_swvol_r; 104 1.14 macallan 105 1.1 grant u_int sc_vol_l; 106 1.1 grant u_int sc_vol_r; 107 1.6 macallan u_int sc_treble; 108 1.6 macallan u_int sc_bass; 109 1.6 macallan u_int mixer[6]; /* s1_l, s2_l, an_l, s1_r, s2_r, an_r */ 110 1.50 isaki uint16_t sc_rval; 111 1.1 grant 112 1.23 garbled bus_space_handle_t sc_odmah; 113 1.23 garbled bus_space_handle_t sc_idmah; 114 1.1 grant dbdma_regmap_t *sc_odma; 115 1.1 grant dbdma_regmap_t *sc_idma; 116 1.5 briggs unsigned char dbdma_cmdspace[sizeof(struct dbdma_command) * 40 + 15]; 117 1.5 briggs struct dbdma_command *sc_odmacmd; 118 1.5 briggs struct dbdma_command *sc_idmacmd; 119 1.37 jmcneill 120 1.37 jmcneill kmutex_t sc_lock; 121 1.37 jmcneill kmutex_t sc_intr_lock; 122 1.55 macallan 123 1.55 macallan struct onewire_bus sc_ow_bus; 124 1.55 macallan device_t sc_ow_dev; 125 1.55 macallan int sc_ow_data; 126 1.1 grant }; 127 1.1 grant 128 1.28 macallan static int snapper_match(device_t, struct cfdata *, void *); 129 1.28 macallan static void snapper_attach(device_t, device_t, void *); 130 1.28 macallan static void snapper_defer(device_t); 131 1.28 macallan static int snapper_intr(void *); 132 1.50 isaki static int snapper_query_format(void *, audio_format_query_t *); 133 1.50 isaki static int snapper_set_format(void *, int, 134 1.50 isaki const audio_params_t *, const audio_params_t *, 135 1.50 isaki audio_filter_reg_t *, audio_filter_reg_t *); 136 1.60 jmcneill static int snapper_commit_settings(void *); 137 1.28 macallan static int snapper_round_blocksize(void *, int, int, const audio_params_t *); 138 1.28 macallan static int snapper_halt_output(void *); 139 1.28 macallan static int snapper_halt_input(void *); 140 1.28 macallan static int snapper_getdev(void *, struct audio_device *); 141 1.28 macallan static int snapper_set_port(void *, mixer_ctrl_t *); 142 1.28 macallan static int snapper_get_port(void *, mixer_ctrl_t *); 143 1.28 macallan static int snapper_query_devinfo(void *, mixer_devinfo_t *); 144 1.28 macallan static size_t snapper_round_buffersize(void *, int, size_t); 145 1.28 macallan static int snapper_get_props(void *); 146 1.28 macallan static int snapper_trigger_output(void *, void *, void *, int, void (*)(void *), 147 1.3 kent void *, const audio_params_t *); 148 1.28 macallan static int snapper_trigger_input(void *, void *, void *, int, void (*)(void *), 149 1.3 kent void *, const audio_params_t *); 150 1.37 jmcneill static void snapper_get_locks(void *, kmutex_t **, kmutex_t **); 151 1.28 macallan static void snapper_set_volume(struct snapper_softc *, u_int, u_int); 152 1.28 macallan static int snapper_set_rate(struct snapper_softc *); 153 1.28 macallan static void snapper_set_treble(struct snapper_softc *, u_int); 154 1.28 macallan static void snapper_set_bass(struct snapper_softc *, u_int); 155 1.28 macallan static void snapper_write_mixers(struct snapper_softc *); 156 1.1 grant 157 1.28 macallan static int tas3004_write(struct snapper_softc *, u_int, const void *); 158 1.44 macallan static int gpio_read(bus_size_t); 159 1.44 macallan static void gpio_write(bus_size_t, int); 160 1.28 macallan static void snapper_mute_speaker(struct snapper_softc *, int); 161 1.28 macallan static void snapper_mute_headphone(struct snapper_softc *, int); 162 1.57 macallan static void snapper_mute_lineout(struct snapper_softc *, int); 163 1.28 macallan static int snapper_cint(void *); 164 1.28 macallan static int tas3004_init(struct snapper_softc *); 165 1.28 macallan static void snapper_init(struct snapper_softc *, int); 166 1.1 grant 167 1.55 macallan static void snapper_setup_ow(struct snapper_softc *); 168 1.55 macallan static int snapper_ow_reset(void *); 169 1.55 macallan static int snapper_ow_read_bit(void *); 170 1.55 macallan static void snapper_ow_write_bit(void *, int); 171 1.55 macallan 172 1.55 macallan static void snapper_bb_rx(void *); 173 1.55 macallan static void snapper_bb_tx(void *); 174 1.55 macallan static int snapper_bb_get(void *); 175 1.55 macallan static void snapper_bb_set(void *, int); 176 1.55 macallan 177 1.55 macallan static const struct onewire_bbops snapper_bbops = { 178 1.55 macallan snapper_bb_rx, 179 1.55 macallan snapper_bb_tx, 180 1.55 macallan snapper_bb_get, 181 1.55 macallan snapper_bb_set 182 1.55 macallan }; 183 1.55 macallan 184 1.55 macallan 185 1.50 isaki static void 186 1.50 isaki snapper_volume(audio_filter_arg_t *arg) 187 1.50 isaki { 188 1.50 isaki struct snapper_softc *sc; 189 1.50 isaki const aint_t *src; 190 1.66 mlelstv int16_t *dst; 191 1.50 isaki u_int sample_count; 192 1.50 isaki u_int i; 193 1.50 isaki 194 1.50 isaki sc = arg->context; 195 1.50 isaki src = arg->src; 196 1.50 isaki dst = arg->dst; 197 1.50 isaki sample_count = arg->count * arg->srcfmt->channels; 198 1.50 isaki for (i = 0; i < sample_count; i++) { 199 1.50 isaki aint2_t l = (aint2_t)(*src++); 200 1.50 isaki l = l * sc->sc_swvol_l / 255; 201 1.50 isaki *dst++ = (aint_t)l; 202 1.50 isaki } 203 1.19 jmcneill } 204 1.19 jmcneill 205 1.24 macallan /* 206 1.24 macallan * A hardware bug in the TAS3004 I2S transport 207 1.24 macallan * produces phase differences between channels 208 1.24 macallan * (left channel appears delayed by one sample). 209 1.24 macallan * Fix the phase difference by delaying the right channel 210 1.24 macallan * by one sample. 211 1.24 macallan */ 212 1.19 jmcneill static void 213 1.50 isaki snapper_fixphase(audio_filter_arg_t *arg) 214 1.19 jmcneill { 215 1.50 isaki struct snapper_softc *sc; 216 1.50 isaki const aint_t *src; 217 1.50 isaki aint_t *dst; 218 1.50 isaki u_int i; 219 1.50 isaki 220 1.50 isaki sc = arg->context; 221 1.50 isaki src = arg->src; 222 1.50 isaki dst = arg->dst; 223 1.50 isaki for (i = 0; i < arg->count; i++) { 224 1.50 isaki *dst++ = *src++; 225 1.50 isaki *dst++ = sc->sc_rval; 226 1.50 isaki sc->sc_rval = *src++; 227 1.50 isaki } 228 1.19 jmcneill } 229 1.19 jmcneill 230 1.26 macallan CFATTACH_DECL_NEW(snapper, sizeof(struct snapper_softc), snapper_match, 231 1.22 dogcow snapper_attach, NULL, NULL); 232 1.1 grant 233 1.2 yamt const struct audio_hw_if snapper_hw_if = { 234 1.50 isaki .query_format = snapper_query_format, 235 1.50 isaki .set_format = snapper_set_format, 236 1.60 jmcneill .commit_settings = snapper_commit_settings, 237 1.49 isaki .round_blocksize = snapper_round_blocksize, 238 1.49 isaki .halt_output = snapper_halt_output, 239 1.49 isaki .halt_input = snapper_halt_input, 240 1.49 isaki .getdev = snapper_getdev, 241 1.49 isaki .set_port = snapper_set_port, 242 1.49 isaki .get_port = snapper_get_port, 243 1.49 isaki .query_devinfo = snapper_query_devinfo, 244 1.49 isaki .round_buffersize = snapper_round_buffersize, 245 1.49 isaki .get_props = snapper_get_props, 246 1.49 isaki .trigger_output = snapper_trigger_output, 247 1.49 isaki .trigger_input = snapper_trigger_input, 248 1.49 isaki .get_locks = snapper_get_locks, 249 1.1 grant }; 250 1.1 grant 251 1.1 grant struct audio_device snapper_device = { 252 1.1 grant "SNAPPER", 253 1.1 grant "", 254 1.1 grant "snapper" 255 1.1 grant }; 256 1.1 grant 257 1.24 macallan #define SNAPPER_BASSTAB_0DB 18 258 1.6 macallan const uint8_t snapper_basstab[] = { 259 1.6 macallan 0x96, /* -18dB */ 260 1.6 macallan 0x94, /* -17dB */ 261 1.6 macallan 0x92, /* -16dB */ 262 1.6 macallan 0x90, /* -15dB */ 263 1.6 macallan 0x8e, /* -14dB */ 264 1.6 macallan 0x8c, /* -13dB */ 265 1.6 macallan 0x8a, /* -12dB */ 266 1.6 macallan 0x88, /* -11dB */ 267 1.6 macallan 0x86, /* -10dB */ 268 1.6 macallan 0x84, /* -9dB */ 269 1.6 macallan 0x82, /* -8dB */ 270 1.6 macallan 0x80, /* -7dB */ 271 1.6 macallan 0x7e, /* -6dB */ 272 1.6 macallan 0x7c, /* -5dB */ 273 1.6 macallan 0x7a, /* -4dB */ 274 1.6 macallan 0x78, /* -3dB */ 275 1.6 macallan 0x76, /* -2dB */ 276 1.6 macallan 0x74, /* -1dB */ 277 1.6 macallan 0x72, /* 0dB */ 278 1.6 macallan 0x6f, /* 1dB */ 279 1.6 macallan 0x6d, /* 2dB */ 280 1.6 macallan 0x6a, /* 3dB */ 281 1.6 macallan 0x67, /* 4dB */ 282 1.6 macallan 0x65, /* 5dB */ 283 1.6 macallan 0x62, /* 6dB */ 284 1.6 macallan 0x5f, /* 7dB */ 285 1.6 macallan 0x5b, /* 8dB */ 286 1.6 macallan 0x55, /* 9dB */ 287 1.6 macallan 0x4f, /* 10dB */ 288 1.6 macallan 0x49, /* 11dB */ 289 1.6 macallan 0x43, /* 12dB */ 290 1.6 macallan 0x3b, /* 13dB */ 291 1.6 macallan 0x33, /* 14dB */ 292 1.6 macallan 0x29, /* 15dB */ 293 1.6 macallan 0x1e, /* 16dB */ 294 1.6 macallan 0x11, /* 17dB */ 295 1.6 macallan 0x01, /* 18dB */ 296 1.6 macallan }; 297 1.6 macallan 298 1.24 macallan #define SNAPPER_MIXER_GAIN_0DB 36 299 1.10 macallan const uint8_t snapper_mixer_gain[178][3] = { 300 1.10 macallan { 0x7f, 0x17, 0xaf }, /* 18.0 dB */ 301 1.10 macallan { 0x77, 0xfb, 0xaa }, /* 17.5 dB */ 302 1.10 macallan { 0x71, 0x45, 0x75 }, /* 17.0 dB */ 303 1.10 macallan { 0x6a, 0xef, 0x5d }, /* 16.5 dB */ 304 1.10 macallan { 0x64, 0xf4, 0x03 }, /* 16.0 dB */ 305 1.10 macallan { 0x5f, 0x4e, 0x52 }, /* 15.5 dB */ 306 1.10 macallan { 0x59, 0xf9, 0x80 }, /* 15.0 dB */ 307 1.10 macallan { 0x54, 0xf1, 0x06 }, /* 14.5 dB */ 308 1.10 macallan { 0x50, 0x30, 0xa1 }, /* 14.0 dB */ 309 1.10 macallan { 0x4b, 0xb4, 0x46 }, /* 13.5 dB */ 310 1.10 macallan { 0x47, 0x78, 0x28 }, /* 13.0 dB */ 311 1.10 macallan { 0x43, 0x78, 0xb0 }, /* 12.5 dB */ 312 1.10 macallan { 0x3f, 0xb2, 0x78 }, /* 12.0 dB */ 313 1.10 macallan { 0x3c, 0x22, 0x4c }, /* 11.5 dB */ 314 1.10 macallan { 0x38, 0xc5, 0x28 }, /* 11.0 dB */ 315 1.10 macallan { 0x35, 0x98, 0x2f }, /* 10.5 dB */ 316 1.10 macallan { 0x32, 0x98, 0xb0 }, /* 10.0 dB */ 317 1.10 macallan { 0x2f, 0xc4, 0x20 }, /* 9.5 dB */ 318 1.10 macallan { 0x2d, 0x18, 0x18 }, /* 9.0 dB */ 319 1.10 macallan { 0x2a, 0x92, 0x54 }, /* 8.5 dB */ 320 1.10 macallan { 0x28, 0x30, 0xaf }, /* 8.0 dB */ 321 1.10 macallan { 0x25, 0xf1, 0x25 }, /* 7.5 dB */ 322 1.10 macallan { 0x23, 0xd1, 0xcd }, /* 7.0 dB */ 323 1.10 macallan { 0x21, 0xd0, 0xd9 }, /* 6.5 dB */ 324 1.10 macallan { 0x1f, 0xec, 0x98 }, /* 6.0 dB */ 325 1.10 macallan { 0x1e, 0x23, 0x6d }, /* 5.5 dB */ 326 1.10 macallan { 0x1c, 0x73, 0xd5 }, /* 5.0 dB */ 327 1.10 macallan { 0x1a, 0xdc, 0x61 }, /* 4.5 dB */ 328 1.10 macallan { 0x19, 0x5b, 0xb8 }, /* 4.0 dB */ 329 1.10 macallan { 0x17, 0xf0, 0x94 }, /* 3.5 dB */ 330 1.10 macallan { 0x16, 0x99, 0xc0 }, /* 3.0 dB */ 331 1.10 macallan { 0x15, 0x56, 0x1a }, /* 2.5 dB */ 332 1.10 macallan { 0x14, 0x24, 0x8e }, /* 2.0 dB */ 333 1.10 macallan { 0x13, 0x04, 0x1a }, /* 1.5 dB */ 334 1.10 macallan { 0x11, 0xf3, 0xc9 }, /* 1.0 dB */ 335 1.10 macallan { 0x10, 0xf2, 0xb4 }, /* 0.5 dB */ 336 1.10 macallan { 0x10, 0x00, 0x00 }, /* 0.0 dB */ 337 1.10 macallan { 0x0f, 0x1a, 0xdf }, /* -0.5 dB */ 338 1.10 macallan { 0x0e, 0x42, 0x90 }, /* -1.0 dB */ 339 1.10 macallan { 0x0d, 0x76, 0x5a }, /* -1.5 dB */ 340 1.10 macallan { 0x0c, 0xb5, 0x91 }, /* -2.0 dB */ 341 1.10 macallan { 0x0b, 0xff, 0x91 }, /* -2.5 dB */ 342 1.10 macallan { 0x0b, 0x53, 0xbe }, /* -3.0 dB */ 343 1.10 macallan { 0x0a, 0xb1, 0x89 }, /* -3.5 dB */ 344 1.10 macallan { 0x0a, 0x18, 0x66 }, /* -4.0 dB */ 345 1.10 macallan { 0x09, 0x87, 0xd5 }, /* -4.5 dB */ 346 1.10 macallan { 0x08, 0xff, 0x59 }, /* -5.0 dB */ 347 1.10 macallan { 0x08, 0x7e, 0x80 }, /* -5.5 dB */ 348 1.10 macallan { 0x08, 0x04, 0xdc }, /* -6.0 dB */ 349 1.10 macallan { 0x07, 0x92, 0x07 }, /* -6.5 dB */ 350 1.10 macallan { 0x07, 0x25, 0x9d }, /* -7.0 dB */ 351 1.10 macallan { 0x06, 0xbf, 0x44 }, /* -7.5 dB */ 352 1.10 macallan { 0x06, 0x5e, 0xa5 }, /* -8.0 dB */ 353 1.10 macallan { 0x06, 0x03, 0x6e }, /* -8.5 dB */ 354 1.10 macallan { 0x05, 0xad, 0x50 }, /* -9.0 dB */ 355 1.10 macallan { 0x05, 0x5c, 0x04 }, /* -9.5 dB */ 356 1.10 macallan { 0x05, 0x0f, 0x44 }, /* -10.0 dB */ 357 1.10 macallan { 0x04, 0xc6, 0xd0 }, /* -10.5 dB */ 358 1.10 macallan { 0x04, 0x82, 0x68 }, /* -11.0 dB */ 359 1.10 macallan { 0x04, 0x41, 0xd5 }, /* -11.5 dB */ 360 1.10 macallan { 0x04, 0x04, 0xde }, /* -12.0 dB */ 361 1.10 macallan { 0x03, 0xcb, 0x50 }, /* -12.5 dB */ 362 1.10 macallan { 0x03, 0x94, 0xfa }, /* -13.0 dB */ 363 1.10 macallan { 0x03, 0x61, 0xaf }, /* -13.5 dB */ 364 1.10 macallan { 0x03, 0x31, 0x42 }, /* -14.0 dB */ 365 1.10 macallan { 0x03, 0x03, 0x8a }, /* -14.5 dB */ 366 1.10 macallan { 0x02, 0xd8, 0x62 }, /* -15.0 dB */ 367 1.10 macallan { 0x02, 0xaf, 0xa3 }, /* -15.5 dB */ 368 1.10 macallan { 0x02, 0x89, 0x2c }, /* -16.0 dB */ 369 1.10 macallan { 0x02, 0x64, 0xdb }, /* -16.5 dB */ 370 1.10 macallan { 0x02, 0x42, 0x93 }, /* -17.0 dB */ 371 1.10 macallan { 0x02, 0x22, 0x35 }, /* -17.5 dB */ 372 1.10 macallan { 0x02, 0x03, 0xa7 }, /* -18.0 dB */ 373 1.10 macallan { 0x01, 0xe6, 0xcf }, /* -18.5 dB */ 374 1.10 macallan { 0x01, 0xcb, 0x94 }, /* -19.0 dB */ 375 1.10 macallan { 0x01, 0xb1, 0xde }, /* -19.5 dB */ 376 1.10 macallan { 0x01, 0x99, 0x99 }, /* -20.0 dB */ 377 1.10 macallan { 0x01, 0x82, 0xaf }, /* -20.5 dB */ 378 1.10 macallan { 0x01, 0x6d, 0x0e }, /* -21.0 dB */ 379 1.10 macallan { 0x01, 0x58, 0xa2 }, /* -21.5 dB */ 380 1.10 macallan { 0x01, 0x45, 0x5b }, /* -22.0 dB */ 381 1.10 macallan { 0x01, 0x33, 0x28 }, /* -22.5 dB */ 382 1.10 macallan { 0x01, 0x21, 0xf9 }, /* -23.0 dB */ 383 1.10 macallan { 0x01, 0x11, 0xc0 }, /* -23.5 dB */ 384 1.10 macallan { 0x01, 0x02, 0x70 }, /* -24.0 dB */ 385 1.10 macallan { 0x00, 0xf3, 0xfb }, /* -24.5 dB */ 386 1.10 macallan { 0x00, 0xe6, 0x55 }, /* -25.0 dB */ 387 1.10 macallan { 0x00, 0xd9, 0x73 }, /* -25.5 dB */ 388 1.10 macallan { 0x00, 0xcd, 0x49 }, /* -26.0 dB */ 389 1.10 macallan { 0x00, 0xc1, 0xcd }, /* -26.5 dB */ 390 1.10 macallan { 0x00, 0xb6, 0xf6 }, /* -27.0 dB */ 391 1.10 macallan { 0x00, 0xac, 0xba }, /* -27.5 dB */ 392 1.10 macallan { 0x00, 0xa3, 0x10 }, /* -28.0 dB */ 393 1.10 macallan { 0x00, 0x99, 0xf1 }, /* -28.5 dB */ 394 1.10 macallan { 0x00, 0x91, 0x54 }, /* -29.0 dB */ 395 1.10 macallan { 0x00, 0x89, 0x33 }, /* -29.5 dB */ 396 1.10 macallan { 0x00, 0x81, 0x86 }, /* -30.0 dB */ 397 1.10 macallan { 0x00, 0x7a, 0x48 }, /* -30.5 dB */ 398 1.10 macallan { 0x00, 0x73, 0x70 }, /* -31.0 dB */ 399 1.10 macallan { 0x00, 0x6c, 0xfb }, /* -31.5 dB */ 400 1.10 macallan { 0x00, 0x66, 0xe3 }, /* -32.0 dB */ 401 1.10 macallan { 0x00, 0x61, 0x21 }, /* -32.5 dB */ 402 1.10 macallan { 0x00, 0x5b, 0xb2 }, /* -33.0 dB */ 403 1.10 macallan { 0x00, 0x56, 0x91 }, /* -33.5 dB */ 404 1.10 macallan { 0x00, 0x51, 0xb9 }, /* -34.0 dB */ 405 1.10 macallan { 0x00, 0x4d, 0x27 }, /* -34.5 dB */ 406 1.10 macallan { 0x00, 0x48, 0xd6 }, /* -35.0 dB */ 407 1.10 macallan { 0x00, 0x44, 0xc3 }, /* -35.5 dB */ 408 1.10 macallan { 0x00, 0x40, 0xea }, /* -36.0 dB */ 409 1.10 macallan { 0x00, 0x3d, 0x49 }, /* -36.5 dB */ 410 1.10 macallan { 0x00, 0x39, 0xdb }, /* -37.0 dB */ 411 1.10 macallan { 0x00, 0x36, 0x9e }, /* -37.5 dB */ 412 1.10 macallan { 0x00, 0x33, 0x90 }, /* -38.0 dB */ 413 1.10 macallan { 0x00, 0x30, 0xae }, /* -38.5 dB */ 414 1.10 macallan { 0x00, 0x2d, 0xf5 }, /* -39.0 dB */ 415 1.10 macallan { 0x00, 0x2b, 0x63 }, /* -39.5 dB */ 416 1.10 macallan { 0x00, 0x28, 0xf5 }, /* -40.0 dB */ 417 1.10 macallan { 0x00, 0x26, 0xab }, /* -40.5 dB */ 418 1.10 macallan { 0x00, 0x24, 0x81 }, /* -41.0 dB */ 419 1.10 macallan { 0x00, 0x22, 0x76 }, /* -41.5 dB */ 420 1.10 macallan { 0x00, 0x20, 0x89 }, /* -42.0 dB */ 421 1.10 macallan { 0x00, 0x1e, 0xb7 }, /* -42.5 dB */ 422 1.10 macallan { 0x00, 0x1c, 0xff }, /* -43.0 dB */ 423 1.10 macallan { 0x00, 0x1b, 0x60 }, /* -43.5 dB */ 424 1.10 macallan { 0x00, 0x19, 0xd8 }, /* -44.0 dB */ 425 1.10 macallan { 0x00, 0x18, 0x65 }, /* -44.5 dB */ 426 1.10 macallan { 0x00, 0x17, 0x08 }, /* -45.0 dB */ 427 1.10 macallan { 0x00, 0x15, 0xbe }, /* -45.5 dB */ 428 1.10 macallan { 0x00, 0x14, 0x87 }, /* -46.0 dB */ 429 1.10 macallan { 0x00, 0x13, 0x61 }, /* -46.5 dB */ 430 1.10 macallan { 0x00, 0x12, 0x4b }, /* -47.0 dB */ 431 1.10 macallan { 0x00, 0x11, 0x45 }, /* -47.5 dB */ 432 1.10 macallan { 0x00, 0x10, 0x4e }, /* -48.0 dB */ 433 1.10 macallan { 0x00, 0x0f, 0x64 }, /* -48.5 dB */ 434 1.10 macallan { 0x00, 0x0e, 0x88 }, /* -49.0 dB */ 435 1.10 macallan { 0x00, 0x0d, 0xb8 }, /* -49.5 dB */ 436 1.10 macallan { 0x00, 0x0c, 0xf3 }, /* -50.0 dB */ 437 1.10 macallan { 0x00, 0x0c, 0x3a }, /* -50.5 dB */ 438 1.10 macallan { 0x00, 0x0b, 0x8b }, /* -51.0 dB */ 439 1.10 macallan { 0x00, 0x0a, 0xe5 }, /* -51.5 dB */ 440 1.10 macallan { 0x00, 0x0a, 0x49 }, /* -52.0 dB */ 441 1.10 macallan { 0x00, 0x09, 0xb6 }, /* -52.5 dB */ 442 1.10 macallan { 0x00, 0x09, 0x2b }, /* -53.0 dB */ 443 1.10 macallan { 0x00, 0x08, 0xa8 }, /* -53.5 dB */ 444 1.10 macallan { 0x00, 0x08, 0x2c }, /* -54.0 dB */ 445 1.10 macallan { 0x00, 0x07, 0xb7 }, /* -54.5 dB */ 446 1.10 macallan { 0x00, 0x07, 0x48 }, /* -55.0 dB */ 447 1.10 macallan { 0x00, 0x06, 0xe0 }, /* -55.5 dB */ 448 1.10 macallan { 0x00, 0x06, 0x7d }, /* -56.0 dB */ 449 1.10 macallan { 0x00, 0x06, 0x20 }, /* -56.5 dB */ 450 1.10 macallan { 0x00, 0x05, 0xc9 }, /* -57.0 dB */ 451 1.10 macallan { 0x00, 0x05, 0x76 }, /* -57.5 dB */ 452 1.10 macallan { 0x00, 0x05, 0x28 }, /* -58.0 dB */ 453 1.10 macallan { 0x00, 0x04, 0xde }, /* -58.5 dB */ 454 1.10 macallan { 0x00, 0x04, 0x98 }, /* -59.0 dB */ 455 1.10 macallan { 0x00, 0x04, 0x56 }, /* -59.5 dB */ 456 1.10 macallan { 0x00, 0x04, 0x18 }, /* -60.0 dB */ 457 1.10 macallan { 0x00, 0x03, 0xdd }, /* -60.5 dB */ 458 1.10 macallan { 0x00, 0x03, 0xa6 }, /* -61.0 dB */ 459 1.10 macallan { 0x00, 0x03, 0x72 }, /* -61.5 dB */ 460 1.10 macallan { 0x00, 0x03, 0x40 }, /* -62.0 dB */ 461 1.10 macallan { 0x00, 0x03, 0x12 }, /* -62.5 dB */ 462 1.10 macallan { 0x00, 0x02, 0xe6 }, /* -63.0 dB */ 463 1.10 macallan { 0x00, 0x02, 0xbc }, /* -63.5 dB */ 464 1.10 macallan { 0x00, 0x02, 0x95 }, /* -64.0 dB */ 465 1.10 macallan { 0x00, 0x02, 0x70 }, /* -64.5 dB */ 466 1.10 macallan { 0x00, 0x02, 0x4d }, /* -65.0 dB */ 467 1.10 macallan { 0x00, 0x02, 0x2c }, /* -65.5 dB */ 468 1.10 macallan { 0x00, 0x02, 0x0d }, /* -66.0 dB */ 469 1.10 macallan { 0x00, 0x01, 0xf0 }, /* -66.5 dB */ 470 1.10 macallan { 0x00, 0x01, 0xd4 }, /* -67.0 dB */ 471 1.10 macallan { 0x00, 0x01, 0xba }, /* -67.5 dB */ 472 1.10 macallan { 0x00, 0x01, 0xa1 }, /* -68.0 dB */ 473 1.10 macallan { 0x00, 0x01, 0x8a }, /* -68.5 dB */ 474 1.10 macallan { 0x00, 0x01, 0x74 }, /* -69.0 dB */ 475 1.10 macallan { 0x00, 0x01, 0x5f }, /* -69.5 dB */ 476 1.10 macallan { 0x00, 0x01, 0x4b }, /* -70.0 dB */ 477 1.10 macallan { 0x00, 0x00, 0x00 } /* Mute */ 478 1.10 macallan }; 479 1.10 macallan 480 1.50 isaki /* The HW actually supports precisions more than 16bit, but 16bit is enough. */ 481 1.50 isaki static const struct audio_format snapper_formats[] = { 482 1.50 isaki { 483 1.50 isaki .mode = AUMODE_PLAY | AUMODE_RECORD, 484 1.50 isaki .encoding = AUDIO_ENCODING_SLINEAR_BE, 485 1.50 isaki .validbits = 16, 486 1.50 isaki .precision = 16, 487 1.50 isaki .channels = 2, 488 1.50 isaki .channel_mask = AUFMT_STEREO, 489 1.50 isaki .frequency_type = 3, 490 1.50 isaki .frequency = { 32000, 44100, 48000 }, 491 1.50 isaki } 492 1.3 kent }; 493 1.50 isaki #define SNAPPER_NFORMATS __arraycount(snapper_formats) 494 1.3 kent 495 1.50 isaki static const struct audio_format tumbler_formats[] = { 496 1.50 isaki { 497 1.50 isaki .mode = AUMODE_PLAY | AUMODE_RECORD, 498 1.50 isaki .encoding = AUDIO_ENCODING_SLINEAR_BE, 499 1.50 isaki .validbits = 16, 500 1.50 isaki .precision = 16, 501 1.50 isaki .channels = 2, 502 1.50 isaki .channel_mask = AUFMT_STEREO, 503 1.50 isaki .frequency_type = 4, 504 1.50 isaki .frequency = { 32000, 44100, 48000, 96000 }, 505 1.50 isaki }, 506 1.21 aymeric }; 507 1.50 isaki #define TUMBLER_NFORMATS __arraycount(tumbler_formats) 508 1.21 aymeric 509 1.53 macallan /* OF hands us the codec in 16bit mode, run with it for now */ 510 1.53 macallan static const struct audio_format onyx_formats[] = { 511 1.53 macallan { 512 1.53 macallan .mode = AUMODE_PLAY | AUMODE_RECORD, 513 1.53 macallan .encoding = AUDIO_ENCODING_SLINEAR_BE, 514 1.53 macallan .validbits = 16, 515 1.53 macallan .precision = 16, 516 1.53 macallan .channels = 2, 517 1.53 macallan .channel_mask = AUFMT_STEREO, 518 1.53 macallan .frequency_type = 3, 519 1.53 macallan .frequency = { 44100, 48000, 96000 }, 520 1.53 macallan }, 521 1.53 macallan }; 522 1.53 macallan #define ONYX_NFORMATS __arraycount(onyx_formats) 523 1.53 macallan 524 1.44 macallan static bus_size_t amp_mute; 525 1.57 macallan static bus_size_t headphone_mute = 0; 526 1.44 macallan static bus_size_t audio_hw_reset; 527 1.57 macallan static bus_size_t headphone_detect = 0; 528 1.57 macallan static bus_size_t lineout_detect = 0; 529 1.57 macallan static bus_size_t lineout_mute= 0; 530 1.55 macallan static bus_size_t owaddr = -1; 531 1.57 macallan static uint8_t headphone_detect_active = 0; 532 1.57 macallan static uint8_t lineout_detect_active = 0; 533 1.1 grant 534 1.24 macallan /* TAS3004/TAS3001 registers */ 535 1.1 grant #define DEQ_MCR1 0x01 /* Main control register 1 (1byte) */ 536 1.21 aymeric #define DEQ_DRC 0x02 /* Dynamic range compression (6bytes?) 537 1.24 macallan 2 bytes (reserved) on the TAS 3001 */ 538 1.1 grant #define DEQ_VOLUME 0x04 /* Volume (6bytes) */ 539 1.1 grant #define DEQ_TREBLE 0x05 /* Treble control (1byte) */ 540 1.1 grant #define DEQ_BASS 0x06 /* Bass control (1byte) */ 541 1.21 aymeric #define DEQ_MIXER_L 0x07 /* Mixer left gain (9bytes; 3 on TAS3001) */ 542 1.21 aymeric #define DEQ_MIXER_R 0x08 /* Mixer right gain (9bytes; 3 on TAS3001) */ 543 1.1 grant #define DEQ_LB0 0x0a /* Left biquad 0 (15bytes) */ 544 1.1 grant #define DEQ_LB1 0x0b /* Left biquad 1 (15bytes) */ 545 1.1 grant #define DEQ_LB2 0x0c /* Left biquad 2 (15bytes) */ 546 1.1 grant #define DEQ_LB3 0x0d /* Left biquad 3 (15bytes) */ 547 1.1 grant #define DEQ_LB4 0x0e /* Left biquad 4 (15bytes) */ 548 1.1 grant #define DEQ_LB5 0x0f /* Left biquad 5 (15bytes) */ 549 1.1 grant #define DEQ_LB6 0x10 /* Left biquad 6 (15bytes) */ 550 1.1 grant #define DEQ_RB0 0x13 /* Right biquad 0 (15bytes) */ 551 1.1 grant #define DEQ_RB1 0x14 /* Right biquad 1 (15bytes) */ 552 1.1 grant #define DEQ_RB2 0x15 /* Right biquad 2 (15bytes) */ 553 1.1 grant #define DEQ_RB3 0x16 /* Right biquad 3 (15bytes) */ 554 1.1 grant #define DEQ_RB4 0x17 /* Right biquad 4 (15bytes) */ 555 1.1 grant #define DEQ_RB5 0x18 /* Right biquad 5 (15bytes) */ 556 1.1 grant #define DEQ_RB6 0x19 /* Right biquad 6 (15bytes) */ 557 1.1 grant #define DEQ_LLB 0x21 /* Left loudness biquad (15bytes) */ 558 1.1 grant #define DEQ_RLB 0x22 /* Right loudness biquad (15bytes) */ 559 1.1 grant #define DEQ_LLB_GAIN 0x23 /* Left loudness biquad gain (3bytes) */ 560 1.1 grant #define DEQ_RLB_GAIN 0x24 /* Right loudness biquad gain (3bytes) */ 561 1.24 macallan #define DEQ_ACR 0x40 /* [TAS3004] Analog control register (1byte) */ 562 1.24 macallan #define DEQ_MCR2 0x43 /* [TAS3004] Main control register 2 (1byte) */ 563 1.1 grant #define DEQ_MCR1_FL 0x80 /* Fast load */ 564 1.1 grant #define DEQ_MCR1_SC 0x40 /* SCLK frequency */ 565 1.1 grant #define DEQ_MCR1_SC_32 0x00 /* 32fs */ 566 1.1 grant #define DEQ_MCR1_SC_64 0x40 /* 64fs */ 567 1.1 grant #define DEQ_MCR1_SM 0x30 /* Output serial port mode */ 568 1.1 grant #define DEQ_MCR1_SM_L 0x00 /* Left justified */ 569 1.1 grant #define DEQ_MCR1_SM_R 0x10 /* Right justified */ 570 1.1 grant #define DEQ_MCR1_SM_I2S 0x20 /* I2S */ 571 1.24 macallan #define DEQ_MCR1_ISM 0x0c /* [TAS3001] Input serial port mode */ 572 1.24 macallan #define DEQ_MCR1_ISM_L 0x00 /* Left justified */ 573 1.24 macallan #define DEQ_MCR1_ISM_R 0x04 /* Right justified */ 574 1.24 macallan #define DEQ_MCR1_ISM_I2S 0x08 /* I2S */ 575 1.1 grant #define DEQ_MCR1_W 0x03 /* Serial port word length */ 576 1.1 grant #define DEQ_MCR1_W_16 0x00 /* 16 bit */ 577 1.1 grant #define DEQ_MCR1_W_18 0x01 /* 18 bit */ 578 1.1 grant #define DEQ_MCR1_W_20 0x02 /* 20 bit */ 579 1.34 macallan #define DEQ_MCR1_W_24 0x03 /* 24 bit */ 580 1.1 grant 581 1.1 grant #define DEQ_MCR2_DL 0x80 /* Download */ 582 1.1 grant #define DEQ_MCR2_AP 0x02 /* All pass mode */ 583 1.1 grant 584 1.1 grant #define DEQ_ACR_ADM 0x80 /* ADC output mode */ 585 1.1 grant #define DEQ_ACR_LRB 0x40 /* Select B input */ 586 1.1 grant #define DEQ_ACR_DM 0x0c /* De-emphasis control */ 587 1.1 grant #define DEQ_ACR_DM_OFF 0x00 /* off */ 588 1.1 grant #define DEQ_ACR_DM_48 0x04 /* fs = 48kHz */ 589 1.1 grant #define DEQ_ACR_DM_44 0x08 /* fs = 44.1kHz */ 590 1.1 grant #define DEQ_ACR_INP 0x02 /* Analog input select */ 591 1.1 grant #define DEQ_ACR_INP_A 0x00 /* A */ 592 1.1 grant #define DEQ_ACR_INP_B 0x02 /* B */ 593 1.1 grant #define DEQ_ACR_APD 0x01 /* Analog power down */ 594 1.1 grant 595 1.1 grant struct tas3004_reg { 596 1.1 grant u_char MCR1[1]; 597 1.1 grant u_char DRC[6]; 598 1.1 grant u_char VOLUME[6]; 599 1.1 grant u_char TREBLE[1]; 600 1.1 grant u_char BASS[1]; 601 1.1 grant u_char MIXER_L[9]; 602 1.1 grant u_char MIXER_R[9]; 603 1.1 grant u_char LB0[15]; 604 1.1 grant u_char LB1[15]; 605 1.1 grant u_char LB2[15]; 606 1.1 grant u_char LB3[15]; 607 1.1 grant u_char LB4[15]; 608 1.1 grant u_char LB5[15]; 609 1.1 grant u_char LB6[15]; 610 1.1 grant u_char RB0[15]; 611 1.1 grant u_char RB1[15]; 612 1.1 grant u_char RB2[15]; 613 1.1 grant u_char RB3[15]; 614 1.1 grant u_char RB4[15]; 615 1.1 grant u_char RB5[15]; 616 1.1 grant u_char RB6[15]; 617 1.1 grant u_char LLB[15]; 618 1.1 grant u_char RLB[15]; 619 1.1 grant u_char LLB_GAIN[3]; 620 1.1 grant u_char RLB_GAIN[3]; 621 1.1 grant u_char ACR[1]; 622 1.1 grant u_char MCR2[1]; 623 1.1 grant }; 624 1.1 grant 625 1.28 macallan static int 626 1.26 macallan snapper_match(device_t parent, struct cfdata *match, void *aux) 627 1.1 grant { 628 1.4 kent struct confargs *ca; 629 1.10 macallan int soundbus, soundchip, soundcodec; 630 1.1 grant char compat[32]; 631 1.1 grant 632 1.4 kent ca = aux; 633 1.1 grant if (strcmp(ca->ca_name, "i2s") != 0) 634 1.1 grant return 0; 635 1.1 grant 636 1.1 grant if ((soundbus = OF_child(ca->ca_node)) == 0 || 637 1.1 grant (soundchip = OF_child(soundbus)) == 0) 638 1.1 grant return 0; 639 1.1 grant 640 1.32 cegger memset(compat, 0, sizeof compat); 641 1.1 grant OF_getprop(soundchip, "compatible", compat, sizeof compat); 642 1.1 grant 643 1.10 macallan if (strcmp(compat, "snapper") == 0) 644 1.10 macallan return 1; 645 1.18 jmcneill 646 1.21 aymeric if (strcmp(compat, "tumbler") == 0) 647 1.21 aymeric return 1; 648 1.21 aymeric 649 1.18 jmcneill if (strcmp(compat, "AOAKeylargo") == 0) 650 1.18 jmcneill return 1; 651 1.20 jmcneill 652 1.20 jmcneill if (strcmp(compat, "AOAK2") == 0) 653 1.20 jmcneill return 1; 654 1.57 macallan 655 1.57 macallan if (strcmp(compat, "AOAShasta") == 0) 656 1.57 macallan return 1; 657 1.10 macallan 658 1.53 macallan if (strcmp(compat, "AOAbase") == 0) 659 1.53 macallan return 1; 660 1.53 macallan 661 1.24 macallan if (OF_getprop(soundchip, "platform-tas-codec-ref", 662 1.10 macallan &soundcodec, sizeof soundcodec) == sizeof soundcodec) 663 1.10 macallan return 1; 664 1.1 grant 665 1.10 macallan return 0; 666 1.1 grant } 667 1.1 grant 668 1.28 macallan static void 669 1.26 macallan snapper_attach(device_t parent, device_t self, void *aux) 670 1.1 grant { 671 1.4 kent struct snapper_softc *sc; 672 1.4 kent struct confargs *ca; 673 1.39 mrg int cirq, oirq, iirq, /*cirq_type,*/ oirq_type, iirq_type, soundbus; 674 1.36 phx uint32_t intr[6], reg[6]; 675 1.56 rin char compat[32], intr_xname[INTRDEVNAMEBUF]; 676 1.1 grant 677 1.24 macallan sc = device_private(self); 678 1.26 macallan sc->sc_dev = self; 679 1.26 macallan 680 1.4 kent ca = aux; 681 1.5 briggs 682 1.21 aymeric soundbus = OF_child(ca->ca_node); 683 1.32 cegger memset(compat, 0, sizeof compat); 684 1.21 aymeric OF_getprop(OF_child(soundbus), "compatible", compat, sizeof compat); 685 1.21 aymeric 686 1.53 macallan sc->sc_mode = SNAPPER_IS_TAS3004; 687 1.53 macallan 688 1.21 aymeric if (strcmp(compat, "tumbler") == 0) 689 1.24 macallan sc->sc_mode = SNAPPER_IS_TAS3001; 690 1.50 isaki sc->sc_swvol_l = 255; 691 1.50 isaki sc->sc_swvol_r = 255; 692 1.50 isaki sc->sc_vol_l = 128; 693 1.50 isaki sc->sc_vol_r = 128; 694 1.50 isaki sc->sc_rval = 0; 695 1.21 aymeric 696 1.24 macallan sc->sc_odmacmd = dbdma_alloc((SNAPPER_MAXPAGES + 4) * 697 1.40 macallan sizeof(struct dbdma_command), NULL); 698 1.24 macallan sc->sc_idmacmd = dbdma_alloc((SNAPPER_MAXPAGES + 4) * 699 1.40 macallan sizeof(struct dbdma_command), NULL); 700 1.1 grant 701 1.24 macallan sc->sc_baseaddr = ca->ca_baseaddr; 702 1.44 macallan 703 1.36 phx OF_getprop(soundbus, "reg", reg, sizeof reg); 704 1.51 macallan /* deal with messed up properties on PowerMac7,3 and friends */ 705 1.45 macallan if (reg[0] == 0) { 706 1.45 macallan reg[0] += ca->ca_reg[0]; 707 1.45 macallan reg[2] += ca->ca_reg[2]; 708 1.45 macallan reg[4] += ca->ca_reg[2]; 709 1.45 macallan } 710 1.36 phx reg[0] += ca->ca_baseaddr; 711 1.36 phx reg[2] += ca->ca_baseaddr; 712 1.36 phx reg[4] += ca->ca_baseaddr; 713 1.1 grant 714 1.1 grant sc->sc_node = ca->ca_node; 715 1.23 garbled sc->sc_tag = ca->ca_tag; 716 1.36 phx 717 1.45 macallan #ifdef SNAPPER_DEBUG 718 1.45 macallan { 719 1.45 macallan int i; 720 1.45 macallan printf("\n"); 721 1.45 macallan for (i = 0; i < 6; i++) { 722 1.45 macallan printf(" %08x", reg[i]); 723 1.45 macallan } 724 1.45 macallan printf("\n"); 725 1.45 macallan } 726 1.45 macallan #endif 727 1.45 macallan 728 1.36 phx bus_space_map(sc->sc_tag, reg[0], reg[1], 0, &sc->sc_bsh); 729 1.47 macallan obio_space_map(reg[2], reg[3], &sc->sc_odmah); 730 1.47 macallan obio_space_map(reg[4], reg[5], &sc->sc_idmah); 731 1.36 phx 732 1.23 garbled sc->sc_odma = bus_space_vaddr(sc->sc_tag, sc->sc_odmah); 733 1.23 garbled sc->sc_idma = bus_space_vaddr(sc->sc_tag, sc->sc_idmah); 734 1.1 grant 735 1.45 macallan DPRINTF("reg %08x odma %08x\n", (uint32_t)sc->sc_bsh, (uint32_t)sc->sc_odmah); 736 1.45 macallan 737 1.1 grant OF_getprop(soundbus, "interrupts", intr, sizeof intr); 738 1.1 grant cirq = intr[0]; 739 1.1 grant oirq = intr[2]; 740 1.1 grant iirq = intr[4]; 741 1.39 mrg /* cirq_type = intr[1] ? IST_LEVEL : IST_EDGE; */ 742 1.53 macallan oirq_type = (intr[3] & 1) ? IST_LEVEL : IST_EDGE; 743 1.53 macallan iirq_type = (intr[5] & 1) ? IST_LEVEL : IST_EDGE; 744 1.1 grant 745 1.38 mrg /* intr_establish(cirq, cirq_type, IPL_AUDIO, snapper_intr, sc); */ 746 1.56 rin 747 1.56 rin snprintf(intr_xname, sizeof(intr_xname), "%s out", device_xname(self)); 748 1.56 rin intr_establish_xname(oirq, oirq_type, IPL_AUDIO, snapper_intr, sc, 749 1.56 rin intr_xname); 750 1.56 rin 751 1.56 rin snprintf(intr_xname, sizeof(intr_xname), "%s in", device_xname(self)); 752 1.56 rin intr_establish_xname(iirq, iirq_type, IPL_AUDIO, snapper_intr, sc, 753 1.56 rin intr_xname); 754 1.1 grant 755 1.21 aymeric aprint_normal(": irq %d,%d,%d\n", cirq, oirq, iirq); 756 1.1 grant 757 1.37 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 758 1.38 mrg mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 759 1.37 jmcneill 760 1.27 macallan /* PMF event handler */ 761 1.34 macallan pmf_device_register(sc->sc_dev, NULL, NULL); 762 1.34 macallan 763 1.21 aymeric config_defer(self, snapper_defer); 764 1.1 grant } 765 1.1 grant 766 1.28 macallan static void 767 1.26 macallan snapper_defer(device_t dev) 768 1.1 grant { 769 1.4 kent struct snapper_softc *sc; 770 1.26 macallan device_t dv; 771 1.33 dyoung deviter_t di; 772 1.6 macallan struct deq_softc *deq; 773 1.53 macallan char prop[64], next[64], codec[64], *cref; 774 1.53 macallan int codec_node, soundbus, sound, ok, deqnode = 0; 775 1.6 macallan 776 1.24 macallan sc = device_private(dev); 777 1.53 macallan 778 1.53 macallan /* look for platform-*-codec-ref node */ 779 1.53 macallan 780 1.53 macallan /* 781 1.53 macallan * XXX 782 1.53 macallan * there can be more than one i2sbus, the one we want just so happens 783 1.53 macallan * to be the first we see 784 1.53 macallan */ 785 1.53 macallan soundbus = OF_child(sc->sc_node); 786 1.53 macallan sound = OF_child(soundbus); 787 1.53 macallan ok = OF_nextprop(sound, NULL, next); 788 1.53 macallan codec_node = 0; 789 1.53 macallan while (ok && (codec_node == 0)) { 790 1.53 macallan DPRINTF("prop %d %s\n", ok, next); 791 1.53 macallan strncpy(prop, next, 64); 792 1.53 macallan if ((cref = strstr(next, "-codec-ref")) != NULL) { 793 1.53 macallan OF_getprop(sound, next, &codec_node, 4); 794 1.53 macallan if (codec_node != 0) { 795 1.53 macallan OF_getprop(codec_node, "compatible", codec, 64); 796 1.53 macallan DPRINTF("%08x %s\n", codec_node, codec); 797 1.53 macallan } 798 1.53 macallan } 799 1.53 macallan ok = OF_nextprop(sound, prop, next); 800 1.53 macallan } 801 1.53 macallan 802 1.33 dyoung for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); 803 1.33 dyoung dv != NULL; 804 1.33 dyoung dv = deviter_next(&di)) { 805 1.24 macallan if (device_is_a(dv, "deq")) { 806 1.24 macallan deq = device_private(dv); 807 1.53 macallan if (codec_node != 0) { 808 1.53 macallan if (codec_node != deq->sc_node) 809 1.53 macallan continue; 810 1.53 macallan } 811 1.6 macallan sc->sc_i2c = deq->sc_i2c; 812 1.24 macallan sc->sc_deqaddr = deq->sc_address; 813 1.53 macallan deqnode = deq->sc_node; 814 1.6 macallan } 815 1.24 macallan } 816 1.33 dyoung deviter_release(&di); 817 1.6 macallan 818 1.53 macallan DPRINTF("deqnode: %08x\n", deqnode); 819 1.53 macallan 820 1.20 jmcneill /* If we don't find a codec, it's not the end of the world; 821 1.20 jmcneill * we can control the volume in software in this case. 822 1.20 jmcneill */ 823 1.53 macallan if (sc->sc_i2c == NULL) { 824 1.24 macallan sc->sc_mode = SNAPPER_SWVOL; 825 1.53 macallan } else if (deqnode != 0) { 826 1.53 macallan int ret; 827 1.53 macallan codec[0] = 0; 828 1.53 macallan ret = OF_getprop(deqnode, "compatible", codec, 64); 829 1.53 macallan 830 1.53 macallan DPRINTF("codec <%s> %d\n", codec, ret); 831 1.53 macallan 832 1.53 macallan if (codec[0] == 0) { 833 1.53 macallan if (sc->sc_deqaddr == 0x34) { 834 1.53 macallan sc->sc_mode = SNAPPER_IS_TAS3001; 835 1.57 macallan } else { 836 1.57 macallan int root = OF_finddevice("/"); 837 1.57 macallan char model[32]; 838 1.53 macallan sc->sc_mode = SNAPPER_IS_TAS3004; 839 1.57 macallan if (OF_getprop(root, "model", model, 32) > 0) { 840 1.57 macallan printf("model %s\n", model); 841 1.57 macallan if (strcmp(model, "PowerMac8,1") == 0) { 842 1.57 macallan sc->sc_mode = SNAPPER_IS_PCM3052; 843 1.57 macallan } 844 1.57 macallan } 845 1.57 macallan } 846 1.53 macallan } else if (strcmp(codec, "tas3004") == 0) { 847 1.53 macallan sc->sc_mode = SNAPPER_IS_TAS3004; 848 1.53 macallan } else if (strcmp(codec, "pcm3052") == 0) { 849 1.53 macallan sc->sc_mode = SNAPPER_IS_PCM3052; 850 1.53 macallan } else if (strcmp(codec, "cs8416") == 0) { 851 1.53 macallan sc->sc_mode = SNAPPER_IS_CS8416; 852 1.53 macallan } 853 1.53 macallan } 854 1.53 macallan DPRINTF("mode %d\n", sc->sc_mode); 855 1.24 macallan switch (sc->sc_mode) { 856 1.24 macallan case SNAPPER_SWVOL: 857 1.24 macallan aprint_verbose("%s: software codec\n", device_xname(dev)); 858 1.24 macallan break; 859 1.24 macallan case SNAPPER_IS_TAS3001: 860 1.24 macallan aprint_verbose("%s: codec: TAS3001\n", device_xname(dev)); 861 1.24 macallan break; 862 1.53 macallan case SNAPPER_IS_TAS3004: 863 1.24 macallan aprint_verbose("%s: codec: TAS3004\n", device_xname(dev)); 864 1.24 macallan break; 865 1.53 macallan case SNAPPER_IS_PCM3052: 866 1.53 macallan aprint_verbose("%s: codec: PCM3052 / ONYX\n", device_xname(dev)); 867 1.53 macallan break; 868 1.53 macallan default: 869 1.53 macallan aprint_error_dev(sc->sc_dev, "unsupported codec\n"); 870 1.53 macallan sc->sc_mode = SNAPPER_SWVOL; 871 1.24 macallan } 872 1.4 kent 873 1.1 grant snapper_init(sc, sc->sc_node); 874 1.42 sevan 875 1.42 sevan audio_attach_mi(&snapper_hw_if, sc, sc->sc_dev); 876 1.1 grant } 877 1.1 grant 878 1.28 macallan static int 879 1.4 kent snapper_intr(void *v) 880 1.1 grant { 881 1.4 kent struct snapper_softc *sc; 882 1.4 kent struct dbdma_command *cmd; 883 1.4 kent int count; 884 1.1 grant int status; 885 1.1 grant 886 1.4 kent sc = v; 887 1.37 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 888 1.4 kent cmd = sc->sc_odmacmd; 889 1.4 kent count = sc->sc_opages; 890 1.1 grant /* Fill used buffer(s). */ 891 1.1 grant while (count-- > 0) { 892 1.23 garbled if ((in16rb(&cmd->d_command) & 0x30) == 0x30) { 893 1.23 garbled status = in16rb(&cmd->d_status); 894 1.1 grant cmd->d_status = 0; 895 1.1 grant if (status) /* status == 0x8400 */ 896 1.1 grant if (sc->sc_ointr) 897 1.1 grant (*sc->sc_ointr)(sc->sc_oarg); 898 1.1 grant } 899 1.1 grant cmd++; 900 1.1 grant } 901 1.1 grant 902 1.10 macallan cmd = sc->sc_idmacmd; 903 1.10 macallan count = sc->sc_ipages; 904 1.10 macallan while (count-- > 0) { 905 1.23 garbled if ((in16rb(&cmd->d_command) & 0x30) == 0x30) { 906 1.23 garbled status = in16rb(&cmd->d_status); 907 1.10 macallan cmd->d_status = 0; 908 1.10 macallan if (status) /* status == 0x8400 */ 909 1.10 macallan if (sc->sc_iintr) 910 1.10 macallan (*sc->sc_iintr)(sc->sc_iarg); 911 1.10 macallan } 912 1.10 macallan cmd++; 913 1.10 macallan } 914 1.37 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 915 1.10 macallan 916 1.1 grant return 1; 917 1.1 grant } 918 1.1 grant 919 1.1 grant 920 1.28 macallan static int 921 1.50 isaki snapper_query_format(void *h, audio_format_query_t *afp) 922 1.1 grant { 923 1.21 aymeric struct snapper_softc *sc = h; 924 1.21 aymeric 925 1.53 macallan switch (sc->sc_mode) { 926 1.53 macallan case SNAPPER_IS_TAS3001: 927 1.53 macallan return audio_query_format(tumbler_formats, 928 1.53 macallan TUMBLER_NFORMATS, afp); 929 1.53 macallan case SNAPPER_SWVOL: 930 1.53 macallan case SNAPPER_IS_TAS3004: 931 1.53 macallan return audio_query_format(snapper_formats, 932 1.53 macallan SNAPPER_NFORMATS, afp); 933 1.53 macallan case SNAPPER_IS_PCM3052: 934 1.53 macallan return audio_query_format(onyx_formats, 935 1.53 macallan ONYX_NFORMATS, afp); 936 1.50 isaki } 937 1.53 macallan return -1; 938 1.1 grant } 939 1.1 grant 940 1.28 macallan static int 941 1.50 isaki snapper_set_format(void *h, int setmode, 942 1.50 isaki const audio_params_t *play, const audio_params_t *rec, 943 1.50 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 944 1.1 grant { 945 1.4 kent struct snapper_softc *sc; 946 1.1 grant 947 1.4 kent sc = h; 948 1.1 grant 949 1.50 isaki /* *play and *rec are the identical because !AUDIO_PROP_INDEPENDENT. */ 950 1.1 grant 951 1.50 isaki if (sc->sc_mode == SNAPPER_SWVOL) { 952 1.50 isaki pfil->codec = snapper_volume; 953 1.50 isaki pfil->context = sc; 954 1.50 isaki rfil->codec = snapper_volume; 955 1.50 isaki rfil->context = sc; 956 1.50 isaki } else if (sc->sc_mode == 0 && play->channels == 2) { 957 1.50 isaki /* Fix phase problems on TAS3004. */ 958 1.50 isaki pfil->codec = snapper_fixphase; 959 1.50 isaki pfil->context = sc; 960 1.50 isaki rfil->codec = snapper_fixphase; 961 1.50 isaki rfil->context = sc; 962 1.1 grant } 963 1.1 grant 964 1.50 isaki /* Set the speed. */ 965 1.50 isaki sc->sc_rate = play->sample_rate; 966 1.50 isaki sc->sc_bitspersample = play->precision; 967 1.1 grant return 0; 968 1.1 grant } 969 1.1 grant 970 1.28 macallan static int 971 1.60 jmcneill snapper_commit_settings(void *h) 972 1.60 jmcneill { 973 1.60 jmcneill struct snapper_softc *sc; 974 1.60 jmcneill 975 1.60 jmcneill DPRINTF("commit_settings\n"); 976 1.60 jmcneill sc = h; 977 1.60 jmcneill 978 1.60 jmcneill return snapper_set_rate(sc); 979 1.60 jmcneill } 980 1.60 jmcneill 981 1.60 jmcneill static int 982 1.4 kent snapper_round_blocksize(void *h, int size, int mode, 983 1.4 kent const audio_params_t *param) 984 1.1 grant { 985 1.4 kent 986 1.53 macallan if (size < (3 * NBPG)) 987 1.53 macallan size = (3 * NBPG); 988 1.1 grant return size & ~PGOFSET; 989 1.1 grant } 990 1.1 grant 991 1.28 macallan static int 992 1.4 kent snapper_halt_output(void *h) 993 1.1 grant { 994 1.4 kent struct snapper_softc *sc; 995 1.1 grant 996 1.4 kent sc = h; 997 1.1 grant dbdma_stop(sc->sc_odma); 998 1.1 grant dbdma_reset(sc->sc_odma); 999 1.21 aymeric sc->sc_ointr = NULL; 1000 1.50 isaki sc->sc_rval = 0; 1001 1.1 grant return 0; 1002 1.1 grant } 1003 1.1 grant 1004 1.28 macallan static int 1005 1.4 kent snapper_halt_input(void *h) 1006 1.1 grant { 1007 1.4 kent struct snapper_softc *sc; 1008 1.1 grant 1009 1.4 kent sc = h; 1010 1.1 grant dbdma_stop(sc->sc_idma); 1011 1.1 grant dbdma_reset(sc->sc_idma); 1012 1.21 aymeric sc->sc_iintr = NULL; 1013 1.50 isaki sc->sc_rval = 0; 1014 1.1 grant return 0; 1015 1.1 grant } 1016 1.1 grant 1017 1.28 macallan static int 1018 1.4 kent snapper_getdev(void *h, struct audio_device *retp) 1019 1.1 grant { 1020 1.4 kent 1021 1.1 grant *retp = snapper_device; 1022 1.1 grant return 0; 1023 1.1 grant } 1024 1.1 grant 1025 1.1 grant enum { 1026 1.1 grant SNAPPER_MONITOR_CLASS, 1027 1.1 grant SNAPPER_OUTPUT_CLASS, 1028 1.1 grant SNAPPER_RECORD_CLASS, 1029 1.1 grant SNAPPER_OUTPUT_SELECT, 1030 1.1 grant SNAPPER_VOL_OUTPUT, 1031 1.6 macallan SNAPPER_DIGI1, 1032 1.6 macallan SNAPPER_DIGI2, 1033 1.1 grant SNAPPER_VOL_INPUT, 1034 1.6 macallan SNAPPER_TREBLE, 1035 1.6 macallan SNAPPER_BASS, 1036 1.21 aymeric /* From this point, unsupported by the TAS 3001 */ 1037 1.21 aymeric SNAPPER_ANALOG, 1038 1.21 aymeric SNAPPER_INPUT_SELECT, 1039 1.1 grant SNAPPER_ENUM_LAST 1040 1.1 grant }; 1041 1.1 grant 1042 1.28 macallan static int 1043 1.4 kent snapper_set_port(void *h, mixer_ctrl_t *mc) 1044 1.1 grant { 1045 1.4 kent struct snapper_softc *sc; 1046 1.1 grant int l, r; 1047 1.10 macallan u_char data; 1048 1.1 grant 1049 1.1 grant DPRINTF("snapper_set_port dev = %d, type = %d\n", mc->dev, mc->type); 1050 1.4 kent sc = h; 1051 1.1 grant l = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1052 1.1 grant r = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1053 1.1 grant 1054 1.1 grant switch (mc->dev) { 1055 1.1 grant case SNAPPER_OUTPUT_SELECT: 1056 1.1 grant /* No change necessary? */ 1057 1.1 grant if (mc->un.mask == sc->sc_output_mask) 1058 1.1 grant return 0; 1059 1.1 grant 1060 1.1 grant snapper_mute_speaker(sc, 1); 1061 1.1 grant snapper_mute_headphone(sc, 1); 1062 1.57 macallan snapper_mute_lineout(sc, 1); 1063 1.1 grant if (mc->un.mask & 1 << 0) 1064 1.1 grant snapper_mute_speaker(sc, 0); 1065 1.1 grant if (mc->un.mask & 1 << 1) 1066 1.1 grant snapper_mute_headphone(sc, 0); 1067 1.57 macallan if (mc->un.mask & 1 << 2) 1068 1.57 macallan snapper_mute_lineout(sc, 0); 1069 1.1 grant 1070 1.1 grant sc->sc_output_mask = mc->un.mask; 1071 1.1 grant return 0; 1072 1.1 grant 1073 1.1 grant case SNAPPER_VOL_OUTPUT: 1074 1.1 grant snapper_set_volume(sc, l, r); 1075 1.1 grant return 0; 1076 1.1 grant 1077 1.1 grant case SNAPPER_INPUT_SELECT: 1078 1.24 macallan if (sc->sc_mode != 0) 1079 1.21 aymeric return ENXIO; 1080 1.21 aymeric 1081 1.1 grant /* no change necessary? */ 1082 1.1 grant if (mc->un.mask == sc->sc_record_source) 1083 1.1 grant return 0; 1084 1.1 grant switch (mc->un.mask) { 1085 1.10 macallan case 1 << 0: /* microphone */ 1086 1.10 macallan /* Select right channel of B input */ 1087 1.10 macallan data = DEQ_ACR_ADM | DEQ_ACR_LRB | DEQ_ACR_INP_B; 1088 1.10 macallan tas3004_write(sc, DEQ_ACR, &data); 1089 1.10 macallan break; 1090 1.10 macallan case 1 << 1: /* line in */ 1091 1.10 macallan /* Select both channels of A input */ 1092 1.10 macallan data = 0; 1093 1.10 macallan tas3004_write(sc, DEQ_ACR, &data); 1094 1.1 grant break; 1095 1.1 grant default: /* invalid argument */ 1096 1.1 grant return EINVAL; 1097 1.1 grant } 1098 1.1 grant sc->sc_record_source = mc->un.mask; 1099 1.1 grant return 0; 1100 1.1 grant 1101 1.1 grant case SNAPPER_VOL_INPUT: 1102 1.1 grant /* XXX TO BE DONE */ 1103 1.1 grant return 0; 1104 1.1 grant 1105 1.6 macallan case SNAPPER_BASS: 1106 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1107 1.24 macallan return ENXIO; 1108 1.24 macallan snapper_set_bass(sc, l); 1109 1.6 macallan return 0; 1110 1.6 macallan case SNAPPER_TREBLE: 1111 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1112 1.24 macallan return ENXIO; 1113 1.24 macallan snapper_set_treble(sc, l); 1114 1.6 macallan return 0; 1115 1.6 macallan case SNAPPER_DIGI1: 1116 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1117 1.24 macallan return ENXIO; 1118 1.24 macallan 1119 1.24 macallan sc->mixer[0] = l; 1120 1.24 macallan sc->mixer[3] = r; 1121 1.6 macallan snapper_write_mixers(sc); 1122 1.6 macallan return 0; 1123 1.6 macallan case SNAPPER_DIGI2: 1124 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1125 1.24 macallan return ENXIO; 1126 1.24 macallan 1127 1.24 macallan if (sc->sc_mode == SNAPPER_IS_TAS3001) 1128 1.21 aymeric sc->mixer[3] = l; 1129 1.21 aymeric else { 1130 1.24 macallan sc->mixer[1] = l; 1131 1.24 macallan sc->mixer[4] = r; 1132 1.21 aymeric } 1133 1.6 macallan snapper_write_mixers(sc); 1134 1.6 macallan return 0; 1135 1.6 macallan case SNAPPER_ANALOG: 1136 1.24 macallan if (sc->sc_mode != 0) 1137 1.21 aymeric return ENXIO; 1138 1.21 aymeric 1139 1.24 macallan sc->mixer[2] = l; 1140 1.24 macallan sc->mixer[5] = r; 1141 1.6 macallan snapper_write_mixers(sc); 1142 1.6 macallan return 0; 1143 1.6 macallan } 1144 1.1 grant return ENXIO; 1145 1.1 grant } 1146 1.1 grant 1147 1.28 macallan static int 1148 1.4 kent snapper_get_port(void *h, mixer_ctrl_t *mc) 1149 1.1 grant { 1150 1.4 kent struct snapper_softc *sc; 1151 1.1 grant 1152 1.1 grant DPRINTF("snapper_get_port dev = %d, type = %d\n", mc->dev, mc->type); 1153 1.4 kent sc = h; 1154 1.1 grant switch (mc->dev) { 1155 1.1 grant case SNAPPER_OUTPUT_SELECT: 1156 1.1 grant mc->un.mask = sc->sc_output_mask; 1157 1.1 grant return 0; 1158 1.1 grant 1159 1.1 grant case SNAPPER_VOL_OUTPUT: 1160 1.24 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_vol_l; 1161 1.24 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_vol_r; 1162 1.1 grant return 0; 1163 1.1 grant 1164 1.1 grant case SNAPPER_INPUT_SELECT: 1165 1.24 macallan if (sc->sc_mode != 0) 1166 1.21 aymeric return ENXIO; 1167 1.21 aymeric 1168 1.1 grant mc->un.mask = sc->sc_record_source; 1169 1.1 grant return 0; 1170 1.1 grant 1171 1.1 grant case SNAPPER_VOL_INPUT: 1172 1.1 grant /* XXX TO BE DONE */ 1173 1.1 grant mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 0; 1174 1.1 grant mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 0; 1175 1.1 grant return 0; 1176 1.24 macallan 1177 1.6 macallan case SNAPPER_TREBLE: 1178 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1179 1.24 macallan return ENXIO; 1180 1.11 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_treble; 1181 1.6 macallan return 0; 1182 1.6 macallan case SNAPPER_BASS: 1183 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1184 1.24 macallan return ENXIO; 1185 1.11 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_bass; 1186 1.6 macallan return 0; 1187 1.24 macallan 1188 1.6 macallan case SNAPPER_DIGI1: 1189 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1190 1.24 macallan return ENXIO; 1191 1.24 macallan 1192 1.6 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->mixer[0]; 1193 1.6 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->mixer[3]; 1194 1.6 macallan return 0; 1195 1.6 macallan case SNAPPER_DIGI2: 1196 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1197 1.24 macallan return ENXIO; 1198 1.24 macallan 1199 1.6 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->mixer[1]; 1200 1.6 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->mixer[4]; 1201 1.6 macallan return 0; 1202 1.6 macallan case SNAPPER_ANALOG: 1203 1.24 macallan if (sc->sc_mode != 0) 1204 1.21 aymeric return ENXIO; 1205 1.21 aymeric 1206 1.6 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->mixer[2]; 1207 1.6 macallan mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->mixer[5]; 1208 1.6 macallan return 0; 1209 1.1 grant default: 1210 1.1 grant return ENXIO; 1211 1.1 grant } 1212 1.1 grant 1213 1.1 grant return 0; 1214 1.1 grant } 1215 1.1 grant 1216 1.28 macallan static int 1217 1.4 kent snapper_query_devinfo(void *h, mixer_devinfo_t *dip) 1218 1.1 grant { 1219 1.21 aymeric struct snapper_softc *sc = h; 1220 1.21 aymeric 1221 1.1 grant switch (dip->index) { 1222 1.1 grant 1223 1.1 grant case SNAPPER_OUTPUT_SELECT: 1224 1.34 macallan dip->mixer_class = SNAPPER_OUTPUT_CLASS; 1225 1.1 grant strcpy(dip->label.name, AudioNoutput); 1226 1.1 grant dip->type = AUDIO_MIXER_SET; 1227 1.1 grant dip->prev = dip->next = AUDIO_MIXER_LAST; 1228 1.57 macallan dip->un.s.num_mem = 3; 1229 1.1 grant strcpy(dip->un.s.member[0].label.name, AudioNspeaker); 1230 1.64 martin dip->un.s.member[0].mask = 1 << 0; 1231 1.1 grant strcpy(dip->un.s.member[1].label.name, AudioNheadphone); 1232 1.64 martin dip->un.s.member[1].mask = 1 << 1; 1233 1.57 macallan strcpy(dip->un.s.member[2].label.name, AudioNline); 1234 1.64 martin dip->un.s.member[2].mask = 1 << 2; 1235 1.1 grant return 0; 1236 1.1 grant 1237 1.1 grant case SNAPPER_VOL_OUTPUT: 1238 1.34 macallan dip->mixer_class = SNAPPER_OUTPUT_CLASS; 1239 1.1 grant strcpy(dip->label.name, AudioNmaster); 1240 1.1 grant dip->type = AUDIO_MIXER_VALUE; 1241 1.1 grant dip->prev = dip->next = AUDIO_MIXER_LAST; 1242 1.1 grant dip->un.v.num_channels = 2; 1243 1.34 macallan dip->un.v.delta = 16; 1244 1.1 grant strcpy(dip->un.v.units.name, AudioNvolume); 1245 1.1 grant return 0; 1246 1.1 grant 1247 1.1 grant case SNAPPER_INPUT_SELECT: 1248 1.24 macallan if (sc->sc_mode != 0) 1249 1.21 aymeric return ENXIO; 1250 1.21 aymeric 1251 1.1 grant dip->mixer_class = SNAPPER_RECORD_CLASS; 1252 1.1 grant strcpy(dip->label.name, AudioNsource); 1253 1.1 grant dip->type = AUDIO_MIXER_SET; 1254 1.1 grant dip->prev = dip->next = AUDIO_MIXER_LAST; 1255 1.10 macallan dip->un.s.num_mem = 2; 1256 1.10 macallan strcpy(dip->un.s.member[0].label.name, AudioNmicrophone); 1257 1.1 grant dip->un.s.member[0].mask = 1 << 0; 1258 1.10 macallan strcpy(dip->un.s.member[1].label.name, AudioNline); 1259 1.1 grant dip->un.s.member[1].mask = 1 << 1; 1260 1.1 grant return 0; 1261 1.1 grant 1262 1.1 grant case SNAPPER_VOL_INPUT: 1263 1.1 grant dip->mixer_class = SNAPPER_RECORD_CLASS; 1264 1.1 grant strcpy(dip->label.name, AudioNrecord); 1265 1.1 grant dip->type = AUDIO_MIXER_VALUE; 1266 1.1 grant dip->prev = dip->next = AUDIO_MIXER_LAST; 1267 1.1 grant dip->un.v.num_channels = 2; 1268 1.1 grant strcpy(dip->un.v.units.name, AudioNvolume); 1269 1.1 grant return 0; 1270 1.1 grant 1271 1.1 grant case SNAPPER_MONITOR_CLASS: 1272 1.1 grant dip->mixer_class = SNAPPER_MONITOR_CLASS; 1273 1.1 grant strcpy(dip->label.name, AudioCmonitor); 1274 1.1 grant dip->type = AUDIO_MIXER_CLASS; 1275 1.1 grant dip->next = dip->prev = AUDIO_MIXER_LAST; 1276 1.1 grant return 0; 1277 1.1 grant 1278 1.1 grant case SNAPPER_OUTPUT_CLASS: 1279 1.1 grant dip->mixer_class = SNAPPER_OUTPUT_CLASS; 1280 1.1 grant strcpy(dip->label.name, AudioCoutputs); 1281 1.1 grant dip->type = AUDIO_MIXER_CLASS; 1282 1.1 grant dip->next = dip->prev = AUDIO_MIXER_LAST; 1283 1.1 grant return 0; 1284 1.1 grant 1285 1.1 grant case SNAPPER_RECORD_CLASS: 1286 1.1 grant dip->mixer_class = SNAPPER_RECORD_CLASS; 1287 1.1 grant strcpy(dip->label.name, AudioCrecord); 1288 1.1 grant dip->type = AUDIO_MIXER_CLASS; 1289 1.1 grant dip->next = dip->prev = AUDIO_MIXER_LAST; 1290 1.1 grant return 0; 1291 1.6 macallan 1292 1.6 macallan case SNAPPER_TREBLE: 1293 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1294 1.24 macallan return ENXIO; 1295 1.24 macallan 1296 1.34 macallan dip->mixer_class = SNAPPER_OUTPUT_CLASS; 1297 1.6 macallan strcpy(dip->label.name, AudioNtreble); 1298 1.6 macallan dip->type = AUDIO_MIXER_VALUE; 1299 1.6 macallan dip->prev = dip->next = AUDIO_MIXER_LAST; 1300 1.6 macallan dip->un.v.num_channels = 1; 1301 1.6 macallan return 0; 1302 1.6 macallan 1303 1.6 macallan case SNAPPER_BASS: 1304 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1305 1.24 macallan return ENXIO; 1306 1.24 macallan 1307 1.34 macallan dip->mixer_class = SNAPPER_OUTPUT_CLASS; 1308 1.6 macallan strcpy(dip->label.name, AudioNbass); 1309 1.6 macallan dip->type = AUDIO_MIXER_VALUE; 1310 1.6 macallan dip->prev = dip->next = AUDIO_MIXER_LAST; 1311 1.6 macallan dip->un.v.num_channels = 1; 1312 1.6 macallan return 0; 1313 1.6 macallan 1314 1.6 macallan case SNAPPER_DIGI1: 1315 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1316 1.24 macallan return ENXIO; 1317 1.24 macallan 1318 1.34 macallan dip->mixer_class = SNAPPER_OUTPUT_CLASS; 1319 1.6 macallan strcpy(dip->label.name, AudioNdac); 1320 1.6 macallan dip->type = AUDIO_MIXER_VALUE; 1321 1.6 macallan dip->prev = dip->next = AUDIO_MIXER_LAST; 1322 1.21 aymeric dip->un.v.num_channels = 1323 1.24 macallan sc->sc_mode == SNAPPER_IS_TAS3001? 1 : 2; 1324 1.6 macallan return 0; 1325 1.6 macallan case SNAPPER_DIGI2: 1326 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) 1327 1.24 macallan return ENXIO; 1328 1.24 macallan 1329 1.34 macallan dip->mixer_class = SNAPPER_OUTPUT_CLASS; 1330 1.10 macallan strcpy(dip->label.name, AudioNline); 1331 1.6 macallan dip->type = AUDIO_MIXER_VALUE; 1332 1.6 macallan dip->prev = dip->next = AUDIO_MIXER_LAST; 1333 1.21 aymeric dip->un.v.num_channels = 1334 1.24 macallan sc->sc_mode == SNAPPER_IS_TAS3001? 1 : 2; 1335 1.6 macallan return 0; 1336 1.6 macallan case SNAPPER_ANALOG: 1337 1.24 macallan if (sc->sc_mode != 0) 1338 1.21 aymeric return ENXIO; 1339 1.21 aymeric 1340 1.6 macallan dip->mixer_class = SNAPPER_MONITOR_CLASS; 1341 1.10 macallan strcpy(dip->label.name, AudioNmicrophone); 1342 1.6 macallan dip->type = AUDIO_MIXER_VALUE; 1343 1.6 macallan dip->prev = dip->next = AUDIO_MIXER_LAST; 1344 1.6 macallan dip->un.v.num_channels = 2; 1345 1.6 macallan return 0; 1346 1.1 grant } 1347 1.1 grant 1348 1.1 grant return ENXIO; 1349 1.1 grant } 1350 1.1 grant 1351 1.28 macallan static size_t 1352 1.4 kent snapper_round_buffersize(void *h, int dir, size_t size) 1353 1.1 grant { 1354 1.4 kent 1355 1.1 grant if (size > 65536) 1356 1.1 grant size = 65536; 1357 1.1 grant return size; 1358 1.1 grant } 1359 1.1 grant 1360 1.28 macallan static int 1361 1.4 kent snapper_get_props(void *h) 1362 1.1 grant { 1363 1.52 isaki 1364 1.52 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE | 1365 1.52 isaki AUDIO_PROP_FULLDUPLEX; 1366 1.1 grant } 1367 1.1 grant 1368 1.28 macallan static int 1369 1.4 kent snapper_trigger_output(void *h, void *start, void *end, int bsize, 1370 1.4 kent void (*intr)(void *), void *arg, 1371 1.4 kent const audio_params_t *param) 1372 1.1 grant { 1373 1.4 kent struct snapper_softc *sc; 1374 1.4 kent struct dbdma_command *cmd; 1375 1.1 grant vaddr_t va; 1376 1.1 grant int i, len, intmode; 1377 1.1 grant 1378 1.1 grant DPRINTF("trigger_output %p %p 0x%x\n", start, end, bsize); 1379 1.4 kent sc = h; 1380 1.14 macallan 1381 1.4 kent cmd = sc->sc_odmacmd; 1382 1.1 grant sc->sc_ointr = intr; 1383 1.1 grant sc->sc_oarg = arg; 1384 1.1 grant sc->sc_opages = ((char *)end - (char *)start) / NBPG; 1385 1.1 grant 1386 1.1 grant #ifdef DIAGNOSTIC 1387 1.24 macallan if (sc->sc_opages > SNAPPER_MAXPAGES) 1388 1.1 grant panic("snapper_trigger_output"); 1389 1.1 grant #endif 1390 1.1 grant 1391 1.1 grant va = (vaddr_t)start; 1392 1.1 grant len = 0; 1393 1.1 grant for (i = sc->sc_opages; i > 0; i--) { 1394 1.1 grant len += NBPG; 1395 1.1 grant if (len < bsize) 1396 1.1 grant intmode = 0; 1397 1.1 grant else { 1398 1.1 grant len = 0; 1399 1.1 grant intmode = DBDMA_INT_ALWAYS; 1400 1.1 grant } 1401 1.1 grant 1402 1.4 kent DBDMA_BUILD(cmd, DBDMA_CMD_OUT_MORE, 0, NBPG, vtophys(va), 1403 1.4 kent intmode, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 1404 1.1 grant cmd++; 1405 1.1 grant va += NBPG; 1406 1.1 grant } 1407 1.1 grant 1408 1.1 grant DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 1409 1.4 kent 0/*vtophys((vaddr_t)sc->sc_odmacmd)*/, 0, DBDMA_WAIT_NEVER, 1410 1.4 kent DBDMA_BRANCH_ALWAYS); 1411 1.1 grant 1412 1.23 garbled out32rb(&cmd->d_cmddep, vtophys((vaddr_t)sc->sc_odmacmd)); 1413 1.1 grant 1414 1.1 grant dbdma_start(sc->sc_odma, sc->sc_odmacmd); 1415 1.1 grant 1416 1.1 grant return 0; 1417 1.1 grant } 1418 1.1 grant 1419 1.28 macallan static int 1420 1.4 kent snapper_trigger_input(void *h, void *start, void *end, int bsize, 1421 1.4 kent void (*intr)(void *), void *arg, 1422 1.4 kent const audio_params_t *param) 1423 1.1 grant { 1424 1.10 macallan struct snapper_softc *sc; 1425 1.10 macallan struct dbdma_command *cmd; 1426 1.10 macallan vaddr_t va; 1427 1.10 macallan int i, len, intmode; 1428 1.10 macallan 1429 1.10 macallan DPRINTF("trigger_input %p %p 0x%x\n", start, end, bsize); 1430 1.10 macallan sc = h; 1431 1.14 macallan 1432 1.10 macallan cmd = sc->sc_idmacmd; 1433 1.10 macallan sc->sc_iintr = intr; 1434 1.10 macallan sc->sc_iarg = arg; 1435 1.10 macallan sc->sc_ipages = ((char *)end - (char *)start) / NBPG; 1436 1.10 macallan 1437 1.10 macallan #ifdef DIAGNOSTIC 1438 1.24 macallan if (sc->sc_ipages > SNAPPER_MAXPAGES) 1439 1.10 macallan panic("snapper_trigger_input"); 1440 1.10 macallan #endif 1441 1.10 macallan 1442 1.10 macallan va = (vaddr_t)start; 1443 1.10 macallan len = 0; 1444 1.10 macallan for (i = sc->sc_ipages; i > 0; i--) { 1445 1.10 macallan len += NBPG; 1446 1.10 macallan if (len < bsize) 1447 1.10 macallan intmode = 0; 1448 1.10 macallan else { 1449 1.10 macallan len = 0; 1450 1.10 macallan intmode = DBDMA_INT_ALWAYS; 1451 1.10 macallan } 1452 1.10 macallan 1453 1.10 macallan DBDMA_BUILD(cmd, DBDMA_CMD_IN_MORE, 0, NBPG, vtophys(va), 1454 1.10 macallan intmode, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 1455 1.10 macallan cmd++; 1456 1.10 macallan va += NBPG; 1457 1.10 macallan } 1458 1.10 macallan 1459 1.10 macallan DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 1460 1.10 macallan 0/*vtophys((vaddr_t)sc->sc_odmacmd)*/, 0, DBDMA_WAIT_NEVER, 1461 1.10 macallan DBDMA_BRANCH_ALWAYS); 1462 1.10 macallan 1463 1.23 garbled out32rb(&cmd->d_cmddep, vtophys((vaddr_t)sc->sc_idmacmd)); 1464 1.4 kent 1465 1.10 macallan dbdma_start(sc->sc_idma, sc->sc_idmacmd); 1466 1.10 macallan 1467 1.10 macallan return 0; 1468 1.1 grant } 1469 1.1 grant 1470 1.28 macallan static void 1471 1.37 jmcneill snapper_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread) 1472 1.37 jmcneill { 1473 1.37 jmcneill struct snapper_softc *sc = opaque; 1474 1.37 jmcneill 1475 1.37 jmcneill *intr = &sc->sc_intr_lock; 1476 1.37 jmcneill *thread = &sc->sc_lock; 1477 1.37 jmcneill } 1478 1.37 jmcneill 1479 1.37 jmcneill static void 1480 1.24 macallan snapper_set_volume(struct snapper_softc *sc, u_int left, u_int right) 1481 1.1 grant { 1482 1.12 macallan u_char regs[6]; 1483 1.12 macallan int l, r; 1484 1.19 jmcneill 1485 1.48 riastrad left = uimin(255, left); 1486 1.48 riastrad right = uimin(255, right); 1487 1.24 macallan 1488 1.24 macallan if (sc->sc_mode == SNAPPER_SWVOL) { 1489 1.50 isaki sc->sc_swvol_l = left; 1490 1.50 isaki sc->sc_swvol_r = right; 1491 1.24 macallan } else { 1492 1.24 macallan /* 1493 1.24 macallan * for some insane reason the gain table for master volume and the 1494 1.24 macallan * mixer channels is almost identical - just shifted by 4 bits 1495 1.24 macallan * so we use the mixer_gain table and bit-twiddle it... 1496 1.24 macallan */ 1497 1.24 macallan l = 177 - (left * 178 / 256); 1498 1.12 macallan regs[0] = (snapper_mixer_gain[l][0] >> 4); 1499 1.12 macallan regs[1] = ((snapper_mixer_gain[l][0] & 0x0f) << 4) | 1500 1.12 macallan (snapper_mixer_gain[l][1] >> 4); 1501 1.12 macallan regs[2] = ((snapper_mixer_gain[l][1] & 0x0f) << 4) | 1502 1.12 macallan (snapper_mixer_gain[l][2] >> 4); 1503 1.12 macallan 1504 1.24 macallan r = 177 - (right * 178 / 256); 1505 1.12 macallan regs[3] = (snapper_mixer_gain[r][0] >> 4); 1506 1.12 macallan regs[4] = ((snapper_mixer_gain[r][0] & 0x0f) << 4) | 1507 1.12 macallan (snapper_mixer_gain[r][1] >> 4); 1508 1.12 macallan regs[5] = ((snapper_mixer_gain[r][1] & 0x0f) << 4) | 1509 1.12 macallan (snapper_mixer_gain[r][2] >> 4); 1510 1.1 grant 1511 1.12 macallan tas3004_write(sc, DEQ_VOLUME, regs); 1512 1.12 macallan 1513 1.12 macallan DPRINTF("%d %02x %02x %02x : %d %02x %02x %02x\n", l, regs[0], 1514 1.12 macallan regs[1], regs[2], r, regs[3], regs[4], regs[5]); 1515 1.12 macallan } 1516 1.24 macallan 1517 1.24 macallan sc->sc_vol_l = left; 1518 1.24 macallan sc->sc_vol_r = right; 1519 1.6 macallan } 1520 1.6 macallan 1521 1.24 macallan static void 1522 1.24 macallan snapper_set_basstreble(struct snapper_softc *sc, u_int val, u_int mode) 1523 1.6 macallan { 1524 1.24 macallan int i = val & 0xFF; 1525 1.6 macallan uint8_t reg; 1526 1.24 macallan 1527 1.24 macallan /* 1528 1.24 macallan * Make 128 match the 0 dB point 1529 1.24 macallan */ 1530 1.24 macallan i = (i - (128 - (SNAPPER_BASSTAB_0DB << 2))) >> 2; 1531 1.24 macallan if (i < 0) 1532 1.24 macallan i = 0; 1533 1.24 macallan else if (i >= sizeof(snapper_basstab)) 1534 1.24 macallan i = sizeof(snapper_basstab) - 1; 1535 1.24 macallan reg = snapper_basstab[i]; 1536 1.24 macallan 1537 1.24 macallan if (sc->sc_mode == SNAPPER_IS_TAS3001 && 1538 1.24 macallan mode == DEQ_BASS) { 1539 1.24 macallan /* 1540 1.24 macallan * XXX -- The TAS3001 bass table is different 1541 1.24 macallan * than the other tables. 1542 1.24 macallan */ 1543 1.24 macallan reg = (reg >> 1) + 5; // map 0x72 -> 0x3E (0 dB) 1544 1.24 macallan } 1545 1.24 macallan 1546 1.24 macallan tas3004_write(sc, mode, ®); 1547 1.24 macallan } 1548 1.24 macallan 1549 1.28 macallan static void 1550 1.24 macallan snapper_set_treble(struct snapper_softc *sc, u_int val) 1551 1.24 macallan { 1552 1.24 macallan if (sc->sc_treble != (u_char)val) { 1553 1.24 macallan sc->sc_treble = val; 1554 1.24 macallan snapper_set_basstreble(sc, val, DEQ_TREBLE); 1555 1.6 macallan } 1556 1.6 macallan } 1557 1.1 grant 1558 1.28 macallan static void 1559 1.24 macallan snapper_set_bass(struct snapper_softc *sc, u_int val) 1560 1.6 macallan { 1561 1.24 macallan if (sc->sc_bass != (u_char)val) { 1562 1.24 macallan sc->sc_bass = val; 1563 1.24 macallan snapper_set_basstreble(sc, val, DEQ_BASS); 1564 1.6 macallan } 1565 1.6 macallan } 1566 1.6 macallan 1567 1.24 macallan 1568 1.24 macallan /* 1569 1.24 macallan * In the mixer gain setting, make 128 correspond to 1570 1.24 macallan * the 0dB value from the table. 1571 1.24 macallan * Note that the table values are complemented. 1572 1.24 macallan */ 1573 1.24 macallan #define SNAPPER_MIXER_GAIN_SIZE (sizeof(snapper_mixer_gain) / \ 1574 1.24 macallan sizeof(snapper_mixer_gain[0])) 1575 1.24 macallan #define NORMALIZE(i) ((~(i) & 0xff) - ((~128 & 0xff) - SNAPPER_MIXER_GAIN_0DB)) 1576 1.24 macallan #define ADJUST(v, i) do { \ 1577 1.24 macallan (v) = NORMALIZE(i);\ 1578 1.24 macallan if ((v) < 0) \ 1579 1.24 macallan (v) = 0; \ 1580 1.24 macallan else if ((v) >= SNAPPER_MIXER_GAIN_SIZE) \ 1581 1.24 macallan (v) = SNAPPER_MIXER_GAIN_SIZE - 1; \ 1582 1.24 macallan \ 1583 1.24 macallan } while (0) 1584 1.28 macallan static void 1585 1.24 macallan snapper_write_mixers(struct snapper_softc *sc) 1586 1.6 macallan { 1587 1.6 macallan uint8_t regs[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 1588 1.10 macallan int i; 1589 1.53 macallan if (sc->sc_mode > 1) return; 1590 1.10 macallan /* Left channel of SDIN1 */ 1591 1.24 macallan ADJUST(i, sc->mixer[0]); 1592 1.10 macallan regs[0] = snapper_mixer_gain[i][0]; 1593 1.10 macallan regs[1] = snapper_mixer_gain[i][1]; 1594 1.10 macallan regs[2] = snapper_mixer_gain[i][2]; 1595 1.10 macallan 1596 1.10 macallan /* Left channel of SDIN2 */ 1597 1.24 macallan ADJUST(i, sc->mixer[1]); 1598 1.10 macallan regs[3] = snapper_mixer_gain[i][0]; 1599 1.10 macallan regs[4] = snapper_mixer_gain[i][1]; 1600 1.10 macallan regs[5] = snapper_mixer_gain[i][2]; 1601 1.10 macallan 1602 1.10 macallan /* Left channel of analog input */ 1603 1.24 macallan ADJUST(i, sc->mixer[2]); 1604 1.10 macallan regs[6] = snapper_mixer_gain[i][0]; 1605 1.10 macallan regs[7] = snapper_mixer_gain[i][1]; 1606 1.10 macallan regs[8] = snapper_mixer_gain[i][2]; 1607 1.10 macallan 1608 1.6 macallan tas3004_write(sc, DEQ_MIXER_L, regs); 1609 1.10 macallan 1610 1.10 macallan /* Right channel of SDIN1 */ 1611 1.24 macallan ADJUST(i, sc->mixer[3]); 1612 1.10 macallan regs[0] = snapper_mixer_gain[i][0]; 1613 1.10 macallan regs[1] = snapper_mixer_gain[i][1]; 1614 1.10 macallan regs[2] = snapper_mixer_gain[i][2]; 1615 1.10 macallan 1616 1.10 macallan /* Right channel of SDIN2 */ 1617 1.24 macallan ADJUST(i, sc->mixer[4]); 1618 1.10 macallan regs[3] = snapper_mixer_gain[i][0]; 1619 1.10 macallan regs[4] = snapper_mixer_gain[i][1]; 1620 1.10 macallan regs[5] = snapper_mixer_gain[i][2]; 1621 1.10 macallan 1622 1.10 macallan /* Right channel of analog input */ 1623 1.24 macallan ADJUST(i, sc->mixer[5]); 1624 1.10 macallan regs[6] = snapper_mixer_gain[i][0]; 1625 1.10 macallan regs[7] = snapper_mixer_gain[i][1]; 1626 1.10 macallan regs[8] = snapper_mixer_gain[i][2]; 1627 1.10 macallan 1628 1.6 macallan tas3004_write(sc, DEQ_MIXER_R, regs); 1629 1.1 grant } 1630 1.1 grant 1631 1.13 jmcneill /* 1632 1.13 jmcneill * rate = fs = LRCLK 1633 1.13 jmcneill * SCLK = 64*LRCLK (I2S) 1634 1.13 jmcneill * MCLK = 256fs (typ. -- changeable) 1635 1.13 jmcneill * 1636 1.13 jmcneill * MCLK = clksrc / mdiv 1637 1.13 jmcneill * SCLK = MCLK / sdiv 1638 1.13 jmcneill * rate = SCLK / 64 ( = LRCLK = fs) 1639 1.13 jmcneill */ 1640 1.1 grant 1641 1.1 grant int 1642 1.14 macallan snapper_set_rate(struct snapper_softc *sc) 1643 1.1 grant { 1644 1.14 macallan u_int reg = 0, x; 1645 1.14 macallan u_int rate = sc->sc_rate; 1646 1.14 macallan uint32_t wordsize, ows; 1647 1.1 grant int MCLK; 1648 1.1 grant int clksrc, mdiv, sdiv; 1649 1.1 grant int mclk_fs; 1650 1.14 macallan int timo; 1651 1.14 macallan uint8_t mcr1; 1652 1.1 grant 1653 1.1 grant switch (rate) { 1654 1.1 grant case 44100: 1655 1.1 grant clksrc = 45158400; /* 45MHz */ 1656 1.1 grant reg = CLKSRC_45MHz; 1657 1.1 grant mclk_fs = 256; 1658 1.1 grant break; 1659 1.1 grant 1660 1.14 macallan case 32000: 1661 1.1 grant case 48000: 1662 1.24 macallan case 96000: 1663 1.1 grant clksrc = 49152000; /* 49MHz */ 1664 1.1 grant reg = CLKSRC_49MHz; 1665 1.1 grant mclk_fs = 256; 1666 1.1 grant break; 1667 1.1 grant 1668 1.1 grant default: 1669 1.10 macallan DPRINTF("snapper_set_rate: invalid rate %u\n", rate); 1670 1.1 grant return EINVAL; 1671 1.1 grant } 1672 1.1 grant 1673 1.1 grant MCLK = rate * mclk_fs; 1674 1.13 jmcneill mdiv = clksrc / MCLK; /* 4 */ 1675 1.13 jmcneill sdiv = mclk_fs / 64; /* 4 */ 1676 1.1 grant 1677 1.1 grant switch (mdiv) { 1678 1.1 grant case 1: 1679 1.1 grant reg |= MCLK_DIV1; 1680 1.1 grant break; 1681 1.1 grant case 3: 1682 1.1 grant reg |= MCLK_DIV3; 1683 1.1 grant break; 1684 1.1 grant case 5: 1685 1.1 grant reg |= MCLK_DIV5; 1686 1.1 grant break; 1687 1.1 grant default: 1688 1.1 grant reg |= ((mdiv / 2 - 1) << 24) & 0x1f000000; 1689 1.1 grant break; 1690 1.1 grant } 1691 1.1 grant 1692 1.1 grant switch (sdiv) { 1693 1.1 grant case 1: 1694 1.1 grant reg |= SCLK_DIV1; 1695 1.1 grant break; 1696 1.1 grant case 3: 1697 1.1 grant reg |= SCLK_DIV3; 1698 1.1 grant break; 1699 1.1 grant default: 1700 1.1 grant reg |= ((sdiv / 2 - 1) << 20) & 0x00f00000; 1701 1.1 grant break; 1702 1.1 grant } 1703 1.1 grant 1704 1.1 grant reg |= SCLK_MASTER; /* XXX master mode */ 1705 1.1 grant 1706 1.1 grant reg |= SERIAL_64x; 1707 1.1 grant 1708 1.1 grant /* stereo input and output */ 1709 1.14 macallan 1710 1.14 macallan DPRINTF("precision: %d\n", sc->sc_bitspersample); 1711 1.14 macallan switch(sc->sc_bitspersample) { 1712 1.14 macallan case 16: 1713 1.53 macallan wordsize = INPUT_STEREO | INPUT_16BIT | 1714 1.53 macallan OUTPUT_STEREO | OUTPUT_16BIT; 1715 1.14 macallan mcr1 = DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_16; 1716 1.14 macallan break; 1717 1.14 macallan case 24: 1718 1.53 macallan wordsize = INPUT_STEREO | INPUT_24BIT | 1719 1.53 macallan OUTPUT_STEREO | OUTPUT_24BIT; 1720 1.14 macallan mcr1 = DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_24; 1721 1.14 macallan break; 1722 1.14 macallan default: 1723 1.14 macallan printf("%s: unsupported sample size %d\n", 1724 1.26 macallan device_xname(sc->sc_dev), sc->sc_bitspersample); 1725 1.14 macallan return EINVAL; 1726 1.14 macallan } 1727 1.14 macallan 1728 1.24 macallan if (sc->sc_mode == SNAPPER_IS_TAS3001) 1729 1.21 aymeric mcr1 |= DEQ_MCR1_ISM_I2S; 1730 1.21 aymeric 1731 1.23 garbled ows = bus_space_read_4(sc->sc_tag, sc->sc_bsh, I2S_WORDSIZE); 1732 1.23 garbled 1733 1.1 grant DPRINTF("I2SSetDataWordSizeReg 0x%08x -> 0x%08x\n", 1734 1.14 macallan ows, wordsize); 1735 1.14 macallan if (ows != wordsize) { 1736 1.24 macallan bus_space_write_4(sc->sc_tag, sc->sc_bsh, I2S_WORDSIZE, 1737 1.24 macallan wordsize); 1738 1.24 macallan if (sc->sc_mode != SNAPPER_SWVOL) 1739 1.24 macallan tas3004_write(sc, DEQ_MCR1, &mcr1); 1740 1.14 macallan } 1741 1.14 macallan 1742 1.23 garbled x = bus_space_read_4(sc->sc_tag, sc->sc_bsh, I2S_FORMAT); 1743 1.14 macallan if (x == reg) 1744 1.14 macallan return 0; /* No change; do nothing. */ 1745 1.1 grant 1746 1.1 grant DPRINTF("I2SSetSerialFormatReg 0x%x -> 0x%x\n", 1747 1.23 garbled bus_space_read_4(sc->sc_tag, sc->sc_bsh, + I2S_FORMAT), reg); 1748 1.14 macallan 1749 1.14 macallan /* Clear CLKSTOPPEND. */ 1750 1.23 garbled bus_space_write_4(sc->sc_tag, sc->sc_bsh, I2S_INT, I2S_INT_CLKSTOPPEND); 1751 1.14 macallan 1752 1.30 macallan x = obio_read_4(KEYLARGO_FCR1); /* FCR */ 1753 1.14 macallan x &= ~I2S0CLKEN; /* XXX I2S0 */ 1754 1.30 macallan obio_write_4(KEYLARGO_FCR1, x); 1755 1.14 macallan 1756 1.14 macallan /* Wait until clock is stopped. */ 1757 1.14 macallan for (timo = 1000; timo > 0; timo--) { 1758 1.24 macallan if (bus_space_read_4(sc->sc_tag, sc->sc_bsh, I2S_INT) & 1759 1.24 macallan I2S_INT_CLKSTOPPEND) 1760 1.14 macallan goto done; 1761 1.14 macallan delay(1); 1762 1.14 macallan } 1763 1.14 macallan DPRINTF("snapper_set_rate: timeout\n"); 1764 1.14 macallan done: 1765 1.23 garbled bus_space_write_4(sc->sc_tag, sc->sc_bsh, I2S_FORMAT, reg); 1766 1.1 grant 1767 1.30 macallan x = obio_read_4(KEYLARGO_FCR1); 1768 1.14 macallan x |= I2S0CLKEN; 1769 1.30 macallan obio_write_4(KEYLARGO_FCR1, x); 1770 1.14 macallan 1771 1.1 grant return 0; 1772 1.1 grant } 1773 1.1 grant 1774 1.1 grant const struct tas3004_reg tas3004_initdata = { 1775 1.14 macallan { DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_16 }, /* MCR1 */ 1776 1.1 grant { 1, 0, 0, 0, 0, 0 }, /* DRC */ 1777 1.1 grant { 0, 0, 0, 0, 0, 0 }, /* VOLUME */ 1778 1.1 grant { 0x72 }, /* TREBLE */ 1779 1.1 grant { 0x72 }, /* BASS */ 1780 1.1 grant { 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 }, /* MIXER_L */ 1781 1.1 grant { 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 }, /* MIXER_R */ 1782 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1783 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1784 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1785 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1786 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1787 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1788 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1789 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1790 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1791 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1792 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1793 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1794 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1795 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1796 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1797 1.1 grant { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 1798 1.1 grant { 0, 0, 0 }, /* LLB_GAIN */ 1799 1.1 grant { 0, 0, 0 }, /* RLB_GAIN */ 1800 1.51 macallan { 0 }, /* ACR - line in */ 1801 1.6 macallan { 2 } /* MCR2 - AllPass mode since we don't use the equalizer anyway */ 1802 1.1 grant }; 1803 1.1 grant 1804 1.1 grant const char tas3004_regsize[] = { 1805 1.1 grant 0, /* 0x00 */ 1806 1.1 grant sizeof tas3004_initdata.MCR1, /* 0x01 */ 1807 1.1 grant sizeof tas3004_initdata.DRC, /* 0x02 */ 1808 1.1 grant 0, /* 0x03 */ 1809 1.1 grant sizeof tas3004_initdata.VOLUME, /* 0x04 */ 1810 1.1 grant sizeof tas3004_initdata.TREBLE, /* 0x05 */ 1811 1.1 grant sizeof tas3004_initdata.BASS, /* 0x06 */ 1812 1.1 grant sizeof tas3004_initdata.MIXER_L, /* 0x07 */ 1813 1.1 grant sizeof tas3004_initdata.MIXER_R, /* 0x08 */ 1814 1.1 grant 0, /* 0x09 */ 1815 1.1 grant sizeof tas3004_initdata.LB0, /* 0x0a */ 1816 1.1 grant sizeof tas3004_initdata.LB1, /* 0x0b */ 1817 1.1 grant sizeof tas3004_initdata.LB2, /* 0x0c */ 1818 1.1 grant sizeof tas3004_initdata.LB3, /* 0x0d */ 1819 1.1 grant sizeof tas3004_initdata.LB4, /* 0x0e */ 1820 1.1 grant sizeof tas3004_initdata.LB5, /* 0x0f */ 1821 1.1 grant sizeof tas3004_initdata.LB6, /* 0x10 */ 1822 1.1 grant 0, /* 0x11 */ 1823 1.1 grant 0, /* 0x12 */ 1824 1.1 grant sizeof tas3004_initdata.RB0, /* 0x13 */ 1825 1.1 grant sizeof tas3004_initdata.RB1, /* 0x14 */ 1826 1.1 grant sizeof tas3004_initdata.RB2, /* 0x15 */ 1827 1.1 grant sizeof tas3004_initdata.RB3, /* 0x16 */ 1828 1.1 grant sizeof tas3004_initdata.RB4, /* 0x17 */ 1829 1.1 grant sizeof tas3004_initdata.RB5, /* 0x18 */ 1830 1.1 grant sizeof tas3004_initdata.RB6, /* 0x19 */ 1831 1.1 grant 0,0,0,0, 0,0, 1832 1.1 grant 0, /* 0x20 */ 1833 1.1 grant sizeof tas3004_initdata.LLB, /* 0x21 */ 1834 1.1 grant sizeof tas3004_initdata.RLB, /* 0x22 */ 1835 1.1 grant sizeof tas3004_initdata.LLB_GAIN, /* 0x23 */ 1836 1.1 grant sizeof tas3004_initdata.RLB_GAIN, /* 0x24 */ 1837 1.1 grant 0,0,0,0, 0,0,0,0, 0,0,0, 1838 1.1 grant 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1839 1.1 grant sizeof tas3004_initdata.ACR, /* 0x40 */ 1840 1.1 grant 0, /* 0x41 */ 1841 1.1 grant 0, /* 0x42 */ 1842 1.1 grant sizeof tas3004_initdata.MCR2 /* 0x43 */ 1843 1.1 grant }; 1844 1.1 grant 1845 1.28 macallan static int 1846 1.4 kent tas3004_write(struct snapper_softc *sc, u_int reg, const void *data) 1847 1.1 grant { 1848 1.1 grant int size; 1849 1.6 macallan static char regblock[sizeof(struct tas3004_reg)+1]; 1850 1.18 jmcneill 1851 1.18 jmcneill if (sc->sc_i2c == NULL) 1852 1.18 jmcneill return 0; 1853 1.10 macallan 1854 1.1 grant KASSERT(reg < sizeof tas3004_regsize); 1855 1.1 grant size = tas3004_regsize[reg]; 1856 1.1 grant KASSERT(size > 0); 1857 1.1 grant 1858 1.14 macallan DPRINTF("reg: %x, %d %d\n", reg, size, ((const char*)data)[0]); 1859 1.14 macallan 1860 1.6 macallan regblock[0] = reg; 1861 1.6 macallan memcpy(®block[1], data, size); 1862 1.24 macallan if (sc->sc_mode == SNAPPER_IS_TAS3001) { 1863 1.21 aymeric if (reg == DEQ_MIXER_L || reg == DEQ_MIXER_R) 1864 1.21 aymeric size = 3; 1865 1.24 macallan else if (reg == DEQ_DRC || reg == DEQ_ACR || 1866 1.24 macallan reg == DEQ_MCR2) { 1867 1.24 macallan /* these registers are not available on TAS3001 */ 1868 1.24 macallan return 0; 1869 1.21 aymeric } 1870 1.21 aymeric } 1871 1.6 macallan iic_acquire_bus(sc->sc_i2c, 0); 1872 1.10 macallan iic_exec(sc->sc_i2c, I2C_OP_WRITE, sc->sc_deqaddr, regblock, size + 1, 1873 1.6 macallan NULL, 0, 0); 1874 1.6 macallan iic_release_bus(sc->sc_i2c, 0); 1875 1.43 macallan 1876 1.1 grant return 0; 1877 1.1 grant } 1878 1.1 grant 1879 1.28 macallan static int 1880 1.44 macallan gpio_read(bus_size_t addr) 1881 1.1 grant { 1882 1.4 kent 1883 1.44 macallan if (obio_read_1(addr) & GPIO_DATA) 1884 1.1 grant return 1; 1885 1.1 grant return 0; 1886 1.1 grant } 1887 1.1 grant 1888 1.28 macallan static void 1889 1.44 macallan gpio_write(bus_size_t addr, int val) 1890 1.1 grant { 1891 1.44 macallan uint8_t data; 1892 1.1 grant 1893 1.4 kent data = GPIO_DDR_OUTPUT; 1894 1.1 grant if (val) 1895 1.1 grant data |= GPIO_DATA; 1896 1.44 macallan obio_write_1(addr, data); 1897 1.1 grant } 1898 1.1 grant 1899 1.65 macallan int headphone_active = 0; 1900 1.65 macallan int lineout_active = 0; 1901 1.65 macallan int amp_active = 0; 1902 1.1 grant 1903 1.28 macallan static void 1904 1.4 kent snapper_mute_speaker(struct snapper_softc *sc, int mute) 1905 1.1 grant { 1906 1.44 macallan int x; 1907 1.1 grant 1908 1.35 phx if (amp_mute) { 1909 1.35 phx DPRINTF("ampmute %d --> ", gpio_read(amp_mute)); 1910 1.1 grant 1911 1.35 phx if (mute) 1912 1.35 phx x = amp_active; /* mute */ 1913 1.35 phx else 1914 1.65 macallan x = amp_active ^ 1; /* unmute */ 1915 1.65 macallan 1916 1.65 macallan gpio_write(amp_mute, x); 1917 1.1 grant 1918 1.35 phx DPRINTF("%d\n", gpio_read(amp_mute)); 1919 1.35 phx } 1920 1.1 grant } 1921 1.1 grant 1922 1.28 macallan static void 1923 1.4 kent snapper_mute_headphone(struct snapper_softc *sc, int mute) 1924 1.1 grant { 1925 1.1 grant u_int x; 1926 1.1 grant 1927 1.44 macallan if (headphone_mute != 0) { 1928 1.35 phx DPRINTF("headphonemute %d --> ", gpio_read(headphone_mute)); 1929 1.1 grant 1930 1.35 phx if (mute) 1931 1.35 phx x = headphone_active; /* mute */ 1932 1.35 phx else 1933 1.65 macallan x = headphone_active ^ 1; /* unmute */ 1934 1.65 macallan 1935 1.65 macallan gpio_write(headphone_mute, x); 1936 1.1 grant 1937 1.35 phx DPRINTF("%d\n", gpio_read(headphone_mute)); 1938 1.35 phx } 1939 1.1 grant } 1940 1.1 grant 1941 1.57 macallan static void 1942 1.57 macallan snapper_mute_lineout(struct snapper_softc *sc, int mute) 1943 1.57 macallan { 1944 1.57 macallan u_int x; 1945 1.57 macallan 1946 1.57 macallan if (lineout_mute != 0) { 1947 1.57 macallan DPRINTF("lineoutmute %d --> ", gpio_read(lineout_mute)); 1948 1.57 macallan 1949 1.57 macallan if (mute) 1950 1.57 macallan x = lineout_active; /* mute */ 1951 1.57 macallan else 1952 1.65 macallan x = lineout_active ^ 1; /* unmute */ 1953 1.65 macallan 1954 1.65 macallan gpio_write(lineout_mute, x); 1955 1.57 macallan 1956 1.57 macallan DPRINTF("%d\n", gpio_read(lineout_mute)); 1957 1.57 macallan } 1958 1.57 macallan } 1959 1.57 macallan 1960 1.28 macallan static int 1961 1.4 kent snapper_cint(void *v) 1962 1.1 grant { 1963 1.57 macallan struct snapper_softc *sc = v; 1964 1.1 grant u_int sense; 1965 1.57 macallan int mask = 1 << 0; 1966 1.1 grant 1967 1.44 macallan if (headphone_detect != 0) { 1968 1.44 macallan sense = obio_read_1(headphone_detect); 1969 1.35 phx DPRINTF("headphone detect = 0x%x\n", sense); 1970 1.35 phx 1971 1.35 phx if (((sense & 0x02) >> 1) == headphone_detect_active) { 1972 1.35 phx DPRINTF("headphone is inserted\n"); 1973 1.57 macallan mask |= 1 << 1; 1974 1.57 macallan mask &= ~(1 << 0); 1975 1.35 phx } else { 1976 1.35 phx DPRINTF("headphone is NOT inserted\n"); 1977 1.57 macallan } 1978 1.57 macallan } 1979 1.57 macallan if (lineout_detect != 0) { 1980 1.57 macallan sense = obio_read_1(lineout_detect); 1981 1.57 macallan DPRINTF("lineout detect = 0x%x\n", sense); 1982 1.57 macallan 1983 1.57 macallan if (((sense & 0x02) >> 1) == lineout_detect_active) { 1984 1.57 macallan DPRINTF("lineout is inserted\n"); 1985 1.57 macallan mask |= 1 << 2; 1986 1.57 macallan mask &= ~(1 << 0); 1987 1.57 macallan } else { 1988 1.57 macallan DPRINTF("lineout is NOT inserted\n"); 1989 1.57 macallan } 1990 1.57 macallan } 1991 1.57 macallan if (mask != sc->sc_output_mask) { 1992 1.57 macallan sc->sc_output_mask = mask; 1993 1.57 macallan if (mask & (1 << 0)) { 1994 1.35 phx snapper_mute_speaker(sc, 0); 1995 1.57 macallan } else snapper_mute_speaker(sc, 1); 1996 1.57 macallan if (mask & (1 << 1)) { 1997 1.57 macallan snapper_mute_headphone(sc, 0); 1998 1.57 macallan } else snapper_mute_headphone(sc, 1); 1999 1.57 macallan if (mask & (1 << 2)) { 2000 1.57 macallan snapper_mute_lineout(sc, 0); 2001 1.57 macallan } else snapper_mute_lineout(sc, 1); 2002 1.1 grant } 2003 1.1 grant return 1; 2004 1.1 grant } 2005 1.1 grant 2006 1.1 grant #define reset_active 0 /* XXX OF */ 2007 1.1 grant 2008 1.1 grant #define DEQ_WRITE(sc, reg, addr) \ 2009 1.1 grant if (tas3004_write(sc, reg, addr)) goto err 2010 1.1 grant 2011 1.28 macallan static int 2012 1.4 kent tas3004_init(struct snapper_softc *sc) 2013 1.1 grant { 2014 1.1 grant 2015 1.1 grant /* No reset port. Nothing to do. */ 2016 1.44 macallan if (audio_hw_reset == 0) 2017 1.1 grant goto noreset; 2018 1.1 grant 2019 1.1 grant /* Reset TAS3004. */ 2020 1.1 grant gpio_write(audio_hw_reset, !reset_active); /* Negate RESET */ 2021 1.1 grant delay(100000); /* XXX Really needed? */ 2022 1.1 grant 2023 1.1 grant gpio_write(audio_hw_reset, reset_active); /* Assert RESET */ 2024 1.1 grant delay(1); 2025 1.1 grant 2026 1.1 grant gpio_write(audio_hw_reset, !reset_active); /* Negate RESET */ 2027 1.1 grant delay(10000); 2028 1.1 grant 2029 1.1 grant noreset: 2030 1.53 macallan if ((sc->sc_mode == SNAPPER_IS_TAS3004) || 2031 1.53 macallan (sc->sc_mode == SNAPPER_IS_TAS3001)) { 2032 1.53 macallan DEQ_WRITE(sc, DEQ_LB0, tas3004_initdata.LB0); 2033 1.53 macallan DEQ_WRITE(sc, DEQ_LB1, tas3004_initdata.LB1); 2034 1.53 macallan DEQ_WRITE(sc, DEQ_LB2, tas3004_initdata.LB2); 2035 1.53 macallan DEQ_WRITE(sc, DEQ_LB3, tas3004_initdata.LB3); 2036 1.53 macallan DEQ_WRITE(sc, DEQ_LB4, tas3004_initdata.LB4); 2037 1.53 macallan DEQ_WRITE(sc, DEQ_LB5, tas3004_initdata.LB5); 2038 1.53 macallan DEQ_WRITE(sc, DEQ_LB6, tas3004_initdata.LB6); 2039 1.53 macallan DEQ_WRITE(sc, DEQ_RB0, tas3004_initdata.RB0); 2040 1.53 macallan DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1); 2041 1.53 macallan DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1); 2042 1.53 macallan DEQ_WRITE(sc, DEQ_RB2, tas3004_initdata.RB2); 2043 1.53 macallan DEQ_WRITE(sc, DEQ_RB3, tas3004_initdata.RB3); 2044 1.53 macallan DEQ_WRITE(sc, DEQ_RB4, tas3004_initdata.RB4); 2045 1.53 macallan DEQ_WRITE(sc, DEQ_RB5, tas3004_initdata.RB5); 2046 1.53 macallan DEQ_WRITE(sc, DEQ_MCR1, tas3004_initdata.MCR1); 2047 1.53 macallan DEQ_WRITE(sc, DEQ_MCR2, tas3004_initdata.MCR2); 2048 1.53 macallan DEQ_WRITE(sc, DEQ_DRC, tas3004_initdata.DRC); 2049 1.53 macallan DEQ_WRITE(sc, DEQ_VOLUME, tas3004_initdata.VOLUME); 2050 1.53 macallan DEQ_WRITE(sc, DEQ_TREBLE, tas3004_initdata.TREBLE); 2051 1.53 macallan DEQ_WRITE(sc, DEQ_BASS, tas3004_initdata.BASS); 2052 1.53 macallan DEQ_WRITE(sc, DEQ_MIXER_L, tas3004_initdata.MIXER_L); 2053 1.53 macallan DEQ_WRITE(sc, DEQ_MIXER_R, tas3004_initdata.MIXER_R); 2054 1.53 macallan DEQ_WRITE(sc, DEQ_LLB, tas3004_initdata.LLB); 2055 1.53 macallan DEQ_WRITE(sc, DEQ_RLB, tas3004_initdata.RLB); 2056 1.53 macallan DEQ_WRITE(sc, DEQ_LLB_GAIN, tas3004_initdata.LLB_GAIN); 2057 1.53 macallan DEQ_WRITE(sc, DEQ_RLB_GAIN, tas3004_initdata.RLB_GAIN); 2058 1.53 macallan DEQ_WRITE(sc, DEQ_ACR, tas3004_initdata.ACR); 2059 1.53 macallan } 2060 1.1 grant return 0; 2061 1.1 grant err: 2062 1.1 grant printf("tas3004_init: error\n"); 2063 1.1 grant return -1; 2064 1.1 grant } 2065 1.1 grant 2066 1.28 macallan static void 2067 1.4 kent snapper_init(struct snapper_softc *sc, int node) 2068 1.1 grant { 2069 1.1 grant int gpio; 2070 1.57 macallan int headphone_detect_intr, lineout_detect_intr; 2071 1.65 macallan uint32_t gpio_base, reg[1], fcreg, buf[8]; 2072 1.56 rin char intr_xname[INTRDEVNAMEBUF]; 2073 1.1 grant #ifdef SNAPPER_DEBUG 2074 1.1 grant char fcr[32]; 2075 1.1 grant 2076 1.31 christos snprintb(fcr, sizeof(fcr), FCR3C_BITMASK, obio_read_4(KEYLARGO_FCR1)); 2077 1.41 msaitoh printf("FCR(0x3c) %s\n", fcr); 2078 1.1 grant #endif 2079 1.46 macallan fcreg = obio_read_4(KEYLARGO_FCR1); 2080 1.46 macallan fcreg |= I2S0CLKEN | I2S0EN; 2081 1.46 macallan obio_write_4(KEYLARGO_FCR1, fcreg); 2082 1.46 macallan 2083 1.4 kent headphone_detect_intr = -1; 2084 1.57 macallan lineout_detect_intr = -1; 2085 1.1 grant 2086 1.25 garbled gpio = of_getnode_byname(OF_parent(node), "gpio"); 2087 1.35 phx if (OF_getprop(gpio, "reg", reg, sizeof(reg)) == sizeof(reg)) 2088 1.35 phx gpio_base = reg[0]; 2089 1.35 phx else 2090 1.35 phx gpio_base = 0; 2091 1.35 phx DPRINTF(" /gpio 0x%x@0x%x\n", (unsigned)gpio, gpio_base); 2092 1.35 phx 2093 1.1 grant gpio = OF_child(gpio); 2094 1.1 grant while (gpio) { 2095 1.55 macallan char name[64], audio_gpio[64], sid[64]; 2096 1.1 grant int intr[2]; 2097 1.44 macallan bus_size_t addr; 2098 1.1 grant 2099 1.32 cegger memset(name, 0, sizeof name); 2100 1.32 cegger memset(audio_gpio, 0, sizeof audio_gpio); 2101 1.1 grant addr = 0; 2102 1.1 grant OF_getprop(gpio, "name", name, sizeof name); 2103 1.1 grant OF_getprop(gpio, "audio-gpio", audio_gpio, sizeof audio_gpio); 2104 1.55 macallan OF_getprop(gpio, "one-wire-bus", sid, sizeof sid); 2105 1.35 phx if (OF_getprop(gpio, "AAPL,address", &addr, sizeof addr) == -1) 2106 1.35 phx if (OF_getprop(gpio, "reg", reg, sizeof reg) 2107 1.35 phx == sizeof reg) 2108 1.44 macallan addr = gpio_base + reg[0]; 2109 1.44 macallan /* 2110 1.44 macallan * XXX 2111 1.44 macallan * APL,address contains the absolute address, we only want the 2112 1.44 macallan * offset from mac-io's base address 2113 1.44 macallan */ 2114 1.44 macallan addr &= 0x7fff; 2115 1.44 macallan DPRINTF(" 0x%x %s %s %08x\n", gpio, name, audio_gpio, addr); 2116 1.1 grant 2117 1.1 grant /* gpio5 */ 2118 1.35 phx if (strcmp(audio_gpio, "headphone-mute") == 0 || 2119 1.65 macallan strcmp(name, "headphone-mute") == 0) { 2120 1.1 grant headphone_mute = addr; 2121 1.65 macallan if (OF_getprop(gpio, 2122 1.65 macallan "platform-do-headphone-mute", buf, 20) == 20) { 2123 1.65 macallan headphone_active = buf[3] & 1; 2124 1.65 macallan DPRINTF("platform-do-headphone-mute %d\n", 2125 1.65 macallan headphone_active); 2126 1.65 macallan } 2127 1.65 macallan } 2128 1.1 grant /* gpio6 */ 2129 1.35 phx if (strcmp(audio_gpio, "amp-mute") == 0 || 2130 1.65 macallan strcmp(name, "amp-mute") == 0) { 2131 1.1 grant amp_mute = addr; 2132 1.65 macallan if (OF_getprop(gpio, 2133 1.65 macallan "platform-do-amp-mute", buf, 20) == 20) { 2134 1.65 macallan amp_active = buf[3] & 1; 2135 1.65 macallan DPRINTF("platform-do-amp-mute %d\n", 2136 1.65 macallan amp_active); 2137 1.65 macallan } 2138 1.65 macallan } 2139 1.1 grant /* extint-gpio15 */ 2140 1.35 phx if (strcmp(audio_gpio, "headphone-detect") == 0 || 2141 1.35 phx strcmp(name, "headphone-detect") == 0) { 2142 1.55 macallan uint32_t act = 0; 2143 1.1 grant headphone_detect = addr; 2144 1.54 macallan OF_getprop(gpio, "audio-gpio-active-state", &act, 4); 2145 1.54 macallan headphone_detect_active = act; 2146 1.35 phx if (OF_getprop(gpio, "interrupts", intr, 8) == 8) { 2147 1.35 phx headphone_detect_intr = intr[0]; 2148 1.35 phx } 2149 1.1 grant } 2150 1.57 macallan if (strcmp(audio_gpio, "lineout-mute") == 0 || 2151 1.62 martin strcmp(name, "lineout-mute") == 0 || 2152 1.65 macallan strcmp(name, "line-output-mute") == 0) { 2153 1.57 macallan lineout_mute = addr; 2154 1.65 macallan if (OF_getprop(gpio, 2155 1.65 macallan "platform-do-lineout-mute", buf, 20) == 20) { 2156 1.65 macallan lineout_active = buf[3] & 1; 2157 1.65 macallan DPRINTF("platform-do-lineout-mute %d\n", 2158 1.65 macallan lineout_active); 2159 1.65 macallan } 2160 1.65 macallan } 2161 1.57 macallan if (strcmp(audio_gpio, "lineout-detect") == 0 || 2162 1.62 martin strcmp(name, "lineout-detect") == 0 || 2163 1.62 martin strcmp(name, "line-output-detect") == 0) { 2164 1.57 macallan uint32_t act = 0; 2165 1.57 macallan lineout_detect = addr; 2166 1.57 macallan OF_getprop(gpio, "audio-gpio-active-state", &act, 4); 2167 1.57 macallan lineout_detect_active = act; 2168 1.57 macallan if (OF_getprop(gpio, "interrupts", intr, 8) == 8) { 2169 1.57 macallan lineout_detect_intr = intr[0]; 2170 1.57 macallan } 2171 1.57 macallan } 2172 1.55 macallan /* extint-gpio16 on Quicksilver */ 2173 1.55 macallan if (strcmp(sid, "speaker-id") == 0) { 2174 1.55 macallan owaddr = addr; 2175 1.55 macallan } 2176 1.1 grant /* gpio11 (keywest-11) */ 2177 1.35 phx if (strcmp(audio_gpio, "audio-hw-reset") == 0 || 2178 1.35 phx strcmp(name, "hw-reset") == 0) 2179 1.1 grant audio_hw_reset = addr; 2180 1.35 phx 2181 1.1 grant gpio = OF_peer(gpio); 2182 1.1 grant } 2183 1.35 phx 2184 1.55 macallan if (owaddr != -1) snapper_setup_ow(sc); 2185 1.55 macallan 2186 1.44 macallan DPRINTF(" headphone-mute %x\n", headphone_mute); 2187 1.57 macallan DPRINTF(" lineout-mute %x\n", lineout_mute); 2188 1.44 macallan DPRINTF(" amp-mute %x\n", amp_mute); 2189 1.44 macallan DPRINTF(" headphone-detect %x\n", headphone_detect); 2190 1.1 grant DPRINTF(" headphone-detect active %x\n", headphone_detect_active); 2191 1.1 grant DPRINTF(" headphone-detect intr %x\n", headphone_detect_intr); 2192 1.57 macallan DPRINTF(" lineout-detect %x\n", lineout_detect); 2193 1.57 macallan DPRINTF(" lineout-detect active %x\n", lineout_detect_active); 2194 1.57 macallan DPRINTF(" lineout-detect intr %x\n", lineout_detect_intr); 2195 1.44 macallan DPRINTF(" audio-hw-reset %x\n", audio_hw_reset); 2196 1.1 grant 2197 1.56 rin if (headphone_detect_intr != -1) { 2198 1.56 rin snprintf(intr_xname, sizeof(intr_xname), "%s headphone", 2199 1.56 rin device_xname(sc->sc_dev)); 2200 1.65 macallan intr_establish_xname(headphone_detect_intr, IST_EDGE, 2201 1.65 macallan IPL_AUDIO, snapper_cint, sc, intr_xname); 2202 1.56 rin } 2203 1.1 grant 2204 1.57 macallan if (lineout_detect_intr != -1) { 2205 1.57 macallan snprintf(intr_xname, sizeof(intr_xname), "%s line out", 2206 1.57 macallan device_xname(sc->sc_dev)); 2207 1.57 macallan intr_establish_xname(lineout_detect_intr, IST_EDGE, IPL_AUDIO, 2208 1.57 macallan snapper_cint, sc, intr_xname); 2209 1.57 macallan } 2210 1.57 macallan 2211 1.14 macallan sc->sc_rate = 44100; /* default rate */ 2212 1.14 macallan sc->sc_bitspersample = 16; 2213 1.1 grant 2214 1.1 grant /* Enable headphone interrupt? */ 2215 1.44 macallan if (headphone_detect != 0) { 2216 1.44 macallan obio_write_1(headphone_detect, 2217 1.44 macallan obio_read_1(headphone_detect) | 0x80); 2218 1.35 phx } 2219 1.57 macallan if (lineout_detect != 0) { 2220 1.57 macallan obio_write_1(lineout_detect, 2221 1.57 macallan obio_read_1(lineout_detect) | 0x80); 2222 1.57 macallan } 2223 1.1 grant 2224 1.1 grant if (tas3004_init(sc)) 2225 1.1 grant return; 2226 1.1 grant 2227 1.1 grant /* Update headphone status. */ 2228 1.1 grant snapper_cint(sc); 2229 1.1 grant 2230 1.14 macallan snapper_set_volume(sc, 128, 128); 2231 1.24 macallan snapper_set_bass(sc, 128); 2232 1.24 macallan snapper_set_treble(sc, 128); 2233 1.10 macallan 2234 1.51 macallan /* Record source defaults to line in. This reflects the 2235 1.10 macallan * default value for the ACR (see tas3004_initdata). 2236 1.10 macallan */ 2237 1.51 macallan sc->sc_record_source = 1 << 1; 2238 1.6 macallan 2239 1.6 macallan /* We mute the analog input for now */ 2240 1.24 macallan sc->mixer[0] = 128; 2241 1.24 macallan sc->mixer[1] = 128; 2242 1.6 macallan sc->mixer[2] = 0; 2243 1.53 macallan if (sc->sc_mode == SNAPPER_IS_TAS3001) { 2244 1.53 macallan sc->mixer[3] = 0; 2245 1.53 macallan } else 2246 1.53 macallan sc->mixer[3] = 128; 2247 1.24 macallan sc->mixer[4] = 128; 2248 1.6 macallan sc->mixer[5] = 0; 2249 1.6 macallan snapper_write_mixers(sc); 2250 1.1 grant } 2251 1.55 macallan 2252 1.55 macallan static void 2253 1.55 macallan snapper_setup_ow(struct snapper_softc *sc) 2254 1.55 macallan { 2255 1.55 macallan struct onewirebus_attach_args oba; 2256 1.55 macallan 2257 1.55 macallan /* Attach 1-Wire bus */ 2258 1.55 macallan sc->sc_ow_bus.bus_cookie = sc; 2259 1.55 macallan sc->sc_ow_bus.bus_reset = snapper_ow_reset; 2260 1.55 macallan sc->sc_ow_bus.bus_read_bit = snapper_ow_read_bit; 2261 1.55 macallan sc->sc_ow_bus.bus_write_bit = snapper_ow_write_bit; 2262 1.55 macallan 2263 1.55 macallan memset(&oba, 0, sizeof(oba)); 2264 1.55 macallan oba.oba_bus = &sc->sc_ow_bus; 2265 1.58 thorpej sc->sc_ow_dev = config_found(sc->sc_dev, &oba, onewirebus_print, 2266 1.61 thorpej CFARGS(.iattr = "onewirebus")); 2267 1.55 macallan } 2268 1.55 macallan 2269 1.55 macallan static int 2270 1.55 macallan snapper_ow_reset(void *cookie) 2271 1.55 macallan { 2272 1.55 macallan return (onewire_bb_reset(&snapper_bbops, cookie)); 2273 1.55 macallan } 2274 1.55 macallan 2275 1.55 macallan static int 2276 1.55 macallan snapper_ow_read_bit(void *cookie) 2277 1.55 macallan { 2278 1.55 macallan return (onewire_bb_read_bit(&snapper_bbops, cookie)); 2279 1.55 macallan } 2280 1.55 macallan 2281 1.55 macallan static void 2282 1.55 macallan snapper_ow_write_bit(void *cookie, int bit) 2283 1.55 macallan { 2284 1.55 macallan onewire_bb_write_bit(&snapper_bbops, cookie, bit); 2285 1.55 macallan } 2286 1.55 macallan 2287 1.55 macallan static void 2288 1.55 macallan snapper_bb_rx(void *cookie) 2289 1.55 macallan { 2290 1.55 macallan struct snapper_softc *sc = cookie; 2291 1.55 macallan 2292 1.55 macallan sc->sc_ow_data &= ~GPIO_DDR_OUTPUT; 2293 1.55 macallan obio_write_1(owaddr, sc->sc_ow_data); 2294 1.55 macallan } 2295 1.55 macallan 2296 1.55 macallan static void 2297 1.55 macallan snapper_bb_tx(void *cookie) 2298 1.55 macallan { 2299 1.55 macallan struct snapper_softc *sc = cookie; 2300 1.55 macallan 2301 1.55 macallan sc->sc_ow_data |= GPIO_DDR_OUTPUT; 2302 1.55 macallan obio_write_1(owaddr, sc->sc_ow_data); 2303 1.55 macallan } 2304 1.55 macallan 2305 1.55 macallan static int snapper_bb_get(void *cookie) 2306 1.55 macallan { 2307 1.55 macallan int data = (obio_read_1(owaddr) & GPIO_LEVEL) ? 1 : 0; 2308 1.55 macallan return data; 2309 1.55 macallan } 2310 1.55 macallan 2311 1.55 macallan static void snapper_bb_set(void *cookie, int bit) 2312 1.55 macallan { 2313 1.55 macallan struct snapper_softc *sc = cookie; 2314 1.55 macallan 2315 1.55 macallan if (bit) { 2316 1.55 macallan sc->sc_ow_data |= GPIO_DATA; 2317 1.55 macallan } else 2318 1.55 macallan sc->sc_ow_data &= ~GPIO_DATA; 2319 1.55 macallan 2320 1.55 macallan obio_write_1(owaddr, sc->sc_ow_data); 2321 1.55 macallan } 2322